[
  {
    "path": ".idea/.name",
    "content": "kotlin-nosql"
  },
  {
    "path": ".idea/compiler.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"CompilerConfiguration\">\n    <resourceExtensions />\n    <wildcardResourcePatterns>\n      <entry name=\"!?*.java\" />\n      <entry name=\"!?*.form\" />\n      <entry name=\"!?*.class\" />\n      <entry name=\"!?*.groovy\" />\n      <entry name=\"!?*.scala\" />\n      <entry name=\"!?*.flex\" />\n      <entry name=\"!?*.kt\" />\n      <entry name=\"!?*.clj\" />\n      <entry name=\"!?*.aj\" />\n    </wildcardResourcePatterns>\n    <annotationProcessing>\n      <profile default=\"true\" name=\"Default\" enabled=\"false\">\n        <processorPath useClasspath=\"true\" />\n      </profile>\n    </annotationProcessing>\n    <bytecodeTargetLevel>\n      <module name=\"kotlin_nosql_main\" target=\"1.8\" />\n      <module name=\"kotlin_nosql_mongodb_main\" target=\"1.8\" />\n      <module name=\"kotlin_nosql_mongodb_test\" target=\"1.8\" />\n      <module name=\"kotlin_nosql_test\" target=\"1.8\" />\n    </bytecodeTargetLevel>\n  </component>\n</project>"
  },
  {
    "path": ".idea/copyright/profiles_settings.xml",
    "content": "<component name=\"CopyrightManager\">\n  <settings default=\"\" />\n</component>"
  },
  {
    "path": ".idea/encodings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"Encoding\">\n    <file url=\"PROJECT\" charset=\"UTF-8\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/gradle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleSettings\">\n    <option name=\"linkedExternalProjectsSettings\">\n      <GradleProjectSettings>\n        <option name=\"disableWrapperSourceDistributionNotification\" value=\"true\" />\n        <option name=\"distributionType\" value=\"DEFAULT_WRAPPED\" />\n        <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n        <option name=\"gradleHome\" value=\"/usr/local/Cellar/gradle/2.2.1/bin\" />\n        <option name=\"gradleJvm\" value=\"1.8\" />\n        <option name=\"modules\">\n          <set>\n            <option value=\"$PROJECT_DIR$\" />\n            <option value=\"$PROJECT_DIR$/kotlin-nosql-mongodb\" />\n          </set>\n        </option>\n        <option name=\"useAutoImport\" value=\"true\" />\n        <option name=\"myModules\">\n          <set>\n            <option value=\"$PROJECT_DIR$\" />\n            <option value=\"$PROJECT_DIR$/kotlin-nosql-mongodb\" />\n          </set>\n        </option>\n      </GradleProjectSettings>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/libraries/Gradle__joda_time_joda_time_2_3.xml",
    "content": "<component name=\"libraryTable\">\n  <library name=\"Gradle: joda-time:joda-time:2.3\">\n    <CLASSES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/joda-time/joda-time/2.3/56498efd17752898cfcc3868c1b6211a07b12b8f/joda-time-2.3.jar!/\" />\n    </CLASSES>\n    <JAVADOC />\n    <SOURCES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/joda-time/joda-time/2.3/ecd8588d8ce0963eb443de31d5fea29e3205f160/joda-time-2.3-sources.jar!/\" />\n    </SOURCES>\n  </library>\n</component>"
  },
  {
    "path": ".idea/libraries/Gradle__junit_junit_4_11.xml",
    "content": "<component name=\"libraryTable\">\n  <library name=\"Gradle: junit:junit:4.11\">\n    <CLASSES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/junit/junit/4.11/4e031bb61df09069aeb2bffb4019e7a5034a4ee0/junit-4.11.jar!/\" />\n    </CLASSES>\n    <JAVADOC />\n    <SOURCES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/junit/junit/4.11/28e0ad201304e4a4abf999ca0570b7cffc352c3c/junit-4.11-sources.jar!/\" />\n    </SOURCES>\n  </library>\n</component>"
  },
  {
    "path": ".idea/libraries/Gradle__org_hamcrest_hamcrest_core_1_3.xml",
    "content": "<component name=\"libraryTable\">\n  <library name=\"Gradle: org.hamcrest:hamcrest-core:1.3\">\n    <CLASSES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/42a25dc3219429f0e5d060061f71acb49bf010a0/hamcrest-core-1.3.jar!/\" />\n    </CLASSES>\n    <JAVADOC />\n    <SOURCES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/1dc37250fbc78e23a65a67fbbaf71d2e9cbc3c0b/hamcrest-core-1.3-sources.jar!/\" />\n    </SOURCES>\n  </library>\n</component>"
  },
  {
    "path": ".idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_reflect_1_0_0.xml",
    "content": "<component name=\"libraryTable\">\n  <library name=\"Gradle: org.jetbrains.kotlin:kotlin-reflect:1.0.0\">\n    <CLASSES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-reflect/1.0.0/a082d34e973f906f839fd01381f6cd1d177354af/kotlin-reflect-1.0.0.jar!/\" />\n    </CLASSES>\n    <JAVADOC />\n    <SOURCES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-reflect/1.0.0/98cb9e87c2b88492443968480e3d6b3a817c4465/kotlin-reflect-1.0.0-sources.jar!/\" />\n    </SOURCES>\n  </library>\n</component>"
  },
  {
    "path": ".idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_runtime_1_0_0.xml",
    "content": "<component name=\"libraryTable\">\n  <library name=\"Gradle: org.jetbrains.kotlin:kotlin-runtime:1.0.0\">\n    <CLASSES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-runtime/1.0.0/8739b3cd3bf98584cf2d1cabf59b55dbd5f7349d/kotlin-runtime-1.0.0.jar!/\" />\n    </CLASSES>\n    <JAVADOC />\n    <SOURCES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-runtime/1.0.0/d0c738e20f1658e1705ce166caa1768267bf4262/kotlin-runtime-1.0.0-sources.jar!/\" />\n    </SOURCES>\n  </library>\n</component>"
  },
  {
    "path": ".idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_0_0.xml",
    "content": "<component name=\"libraryTable\">\n  <library name=\"Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.0.0\">\n    <CLASSES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.0.0/2db5ac6eb2746708e77e4c439625f9331c25e766/kotlin-stdlib-1.0.0.jar!/\" />\n    </CLASSES>\n    <JAVADOC />\n    <SOURCES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.0.0/3a8a73d14b5fdda2425b40b440bb0ce71cb627fc/kotlin-stdlib-1.0.0-sources.jar!/\" />\n    </SOURCES>\n  </library>\n</component>"
  },
  {
    "path": ".idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_test_1_0_0.xml",
    "content": "<component name=\"libraryTable\">\n  <library name=\"Gradle: org.jetbrains.kotlin:kotlin-test:1.0.0\">\n    <CLASSES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-test/1.0.0/1ec4ba71422eb4cb7133a6611792b471183b5a11/kotlin-test-1.0.0.jar!/\" />\n    </CLASSES>\n    <JAVADOC />\n    <SOURCES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-test/1.0.0/1fa859d6fbc04d8b1a71c1f09f362760498cec65/kotlin-test-1.0.0-sources.jar!/\" />\n    </SOURCES>\n  </library>\n</component>"
  },
  {
    "path": ".idea/libraries/Gradle__org_jetbrains_spek_spek_0_1_195.xml",
    "content": "<component name=\"libraryTable\">\n  <library name=\"Gradle: org.jetbrains.spek:spek:0.1.195\">\n    <CLASSES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.spek/spek/0.1.195/94e5aa0dd854b86b5b43102f5eb89d9ac2821a58/spek-0.1.195.jar!/\" />\n    </CLASSES>\n    <JAVADOC />\n    <SOURCES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.spek/spek/0.1.195/2781b9a0edfddeb18e4680743795b0495cdefa6d/spek-0.1.195-sources.jar!/\" />\n    </SOURCES>\n  </library>\n</component>"
  },
  {
    "path": ".idea/libraries/Gradle__org_mongodb_mongo_java_driver_3_0_3.xml",
    "content": "<component name=\"libraryTable\">\n  <library name=\"Gradle: org.mongodb:mongo-java-driver:3.0.3\">\n    <CLASSES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.mongodb/mongo-java-driver/3.0.3/2861ec441c95b6cff99ad6761c01776cf708817a/mongo-java-driver-3.0.3.jar!/\" />\n    </CLASSES>\n    <JAVADOC />\n    <SOURCES>\n      <root url=\"jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.mongodb/mongo-java-driver/3.0.3/9101a823cdd4d76b8121f500d7ca2545223749cf/mongo-java-driver-3.0.3-sources.jar!/\" />\n    </SOURCES>\n  </library>\n</component>"
  },
  {
    "path": ".idea/misc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"EntryPointsManager\">\n    <entry_points version=\"2.0\" />\n  </component>\n  <component name=\"ProjectLevelVcsManager\" settingsEditedManually=\"false\">\n    <OptionsSetting value=\"true\" id=\"Add\" />\n    <OptionsSetting value=\"true\" id=\"Remove\" />\n    <OptionsSetting value=\"true\" id=\"Checkout\" />\n    <OptionsSetting value=\"true\" id=\"Update\" />\n    <OptionsSetting value=\"true\" id=\"Status\" />\n    <OptionsSetting value=\"true\" id=\"Edit\" />\n    <ConfirmationsSetting value=\"0\" id=\"Add\" />\n    <ConfirmationsSetting value=\"0\" id=\"Remove\" />\n  </component>\n  <component name=\"ProjectRootManager\" version=\"2\" languageLevel=\"JDK_1_8\" default=\"true\" assert-keyword=\"true\" jdk-15=\"true\" project-jdk-name=\"1.8\" project-jdk-type=\"JavaSDK\">\n    <output url=\"file://$PROJECT_DIR$/build/classes\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/modules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectModuleManager\">\n    <modules>\n      <module fileurl=\"file://$PROJECT_DIR$/kotlin-nosql.iml\" filepath=\"$PROJECT_DIR$/kotlin-nosql.iml\" />\n      <module fileurl=\"file://$PROJECT_DIR$/.idea/modules/kotlin-nosql.iml\" filepath=\"$PROJECT_DIR$/.idea/modules/kotlin-nosql.iml\" />\n      <module fileurl=\"file://$PROJECT_DIR$/kotlin-nosql-mongodb/kotlin-nosql-mongodb.iml\" filepath=\"$PROJECT_DIR$/kotlin-nosql-mongodb/kotlin-nosql-mongodb.iml\" />\n      <module fileurl=\"file://$PROJECT_DIR$/.idea/modules/kotlin-nosql-mongodb/kotlin-nosql-mongodb.iml\" filepath=\"$PROJECT_DIR$/.idea/modules/kotlin-nosql-mongodb/kotlin-nosql-mongodb.iml\" group=\"kotlin-nosql-mongodb\" />\n      <module fileurl=\"file://$PROJECT_DIR$/.idea/modules/kotlin_nosql_main.iml\" filepath=\"$PROJECT_DIR$/.idea/modules/kotlin_nosql_main.iml\" group=\"kotlin-nosql\" />\n      <module fileurl=\"file://$PROJECT_DIR$/.idea/modules/kotlin-nosql-mongodb/kotlin_nosql_mongodb_main.iml\" filepath=\"$PROJECT_DIR$/.idea/modules/kotlin-nosql-mongodb/kotlin_nosql_mongodb_main.iml\" group=\"kotlin-nosql-mongodb\" />\n      <module fileurl=\"file://$PROJECT_DIR$/.idea/modules/kotlin-nosql-mongodb/kotlin_nosql_mongodb_test.iml\" filepath=\"$PROJECT_DIR$/.idea/modules/kotlin-nosql-mongodb/kotlin_nosql_mongodb_test.iml\" group=\"kotlin-nosql-mongodb\" />\n      <module fileurl=\"file://$PROJECT_DIR$/.idea/modules/kotlin_nosql_test.iml\" filepath=\"$PROJECT_DIR$/.idea/modules/kotlin_nosql_test.iml\" group=\"kotlin-nosql\" />\n    </modules>\n  </component>\n</project>"
  },
  {
    "path": ".idea/vcs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping directory=\"$PROJECT_DIR$\" vcs=\"Git\" />\n  </component>\n</project>"
  },
  {
    "path": "README.md",
    "content": "# Kotlin NoSQL\n\nKotlin NoSQL is a reactive and type-safe DSL for working with NoSQL databases.\n\n## Status\n\nUnder development (POC). The following NoSQL databases are supported now:\n\n- [MongoDB](https://www.mongodb.org/)\n\nFeedback is welcome.\n\n## Download\n\nTo use it with Maven insert the following code in your pom.xml file:\n\n```xml\n<dependency>\n    <groupId>org.jetbrains.kotlin</groupId>\n    <artifactId>kotlin-nosql-mongodb</artifactId>\n    <version>0.1-SNAPSHOT</version>\n </dependency>\n\n <repositories>\n     <repository>\n       <id>kotlin-nosql</id>\n       <url>http://repository.jetbrains.com/kotlin-nosql</url>\n     </repository>\n</repositories>\n```\n\nTo use it with Gradle insert the following code in your build.gradle:\n\n```groovy\nrepositories {\n    maven {\n        url \"http://repository.jetbrains.com/kotlin-nosql\"\n    }\n}\n\ndependencies {\n    compile 'org.jetbrains.kotlin:kotlin-nosql-mongodb:0.1-SNAPSHOT'\n}\n```\n\n## Getting Started\n\nDemo: http://www.youtube.com/watch?v=80xgl3KThvM\n\n### Basics\n\n#### Define a schema\n\n```kotlin\nobject Comments: DocumentSchema<Comment>(\"comments\", Comment::class) {\n    val discussionId = id(\"discussion_id\", Discussions)\n    val slug = string(\"slug\")\n    val fullSlug = string(\"full_slug\")\n    val posted = dateTime(\"posted\")\n    val text = string(\"text\")\n\n    val AuthorInfo = AuthorInfoColumn()\n\n    class AuthorInfoColumn() : Column<AuthorInfo, Comments>(\"author\", AuthorInfo::class) {\n        val authorId = id(\"id\", Authors)\n        val name = string(\"name\")\n    }\n}\n\nclass Comment(val discussionId: Id<String, Discussions>, val slug: String,\n              val fullSlug: String, posted: DateTime, text: String, authorInfo: AuthorInfo) {\n    val id: Id<String, Comments>? = null\n}\n\nclass AuthorInfo(val authorId: Id<String, Authors>, val name: String)\n```\n\n#### Define a database\n\n```kotlin\nval db = MongoDB(database = \"test\", schemas = arrayOf(Comments), action = CreateDrop(onCreate = {\n    // ...\n}))\n\ndb.withSession {\n    // ...\n}\n```\n\n#### Insert a document\n\n```kotlin\nComments.insert(Comment(DiscussionId, slug, fullSlug, posted, text, AuthorInfo(author.id, author.name)))\n```\n\n#### Get a document by id\n\n```kotlin\nval comment = Comments.find { id.equal(commentId) }.single()\n```\n\n#### Get a list of documents by a filter expression\n\n```kotlin\nval comments = Comments.find { authorInfo.id.equal(authorId) }.sortBy { posted }.skip(10).take(5).toList()\n```\n\n#### Get selected fields by document id\n\n```kotlin\nval authorInfo = Comments.find { id.equal(commentId) }.projection { authorInfo }.single()\n```\n\n#### Get selected fields by a filter expression\n\n```kotlin\nComments.find { discussionId.equal(id) }).projection { slug + fullSlug + posted + text + authorInfo }.forEach {\n    val (slug, fullSlug, posted, text, authorInfo) = it\n}\n```\n\n#### Update selected fields by document id\n\n```kotlin\nComments.find { id.equal(commentId) }.projection { posted }.update(newDate)\n```\n\n```kotlin\nComments.find { id.equal(commentId) }.projection { posted + text }.update(newDate, newText)\n```\n\n### Inheritance\n\n#### Define a base schema\n\n```kotlin\nopen class ProductSchema<D, S : DocumentSchema<D>(javaClass: Class<V>, discriminator: String) : DocumentSchema<V>(\"products\",\n            discriminator = Discriminator(string(\"type\"), discriminator)) {\n    val sku = string<S>(\"sku\")\n    val title = string<S>(\"title\")\n    val description = string<S>(\"description\")\n    val asin = string<S>(\"asin\")\n\n    val Shipping = ShippingColumn<S>()\n    val Pricing = PricingColumn<S>()\n\n    inner class ShippingColumn<S : DocumentSchema<D>>() : Column<Shipping, S>(\"shipping\", Shipping::class) {\n        val weight = integer<S>(\"weight\")\n        val dimensions = DimensionsColumn<S>()\n    }\n\n    inner class DimensionsColumn<S : DocumentSchema<D>>() : Column<Dimensions, S>(\"dimensions\", Dimensions::class) {\n        val width = integer<S>(\"width\")\n        val height = integer<S>(\"height\")\n        val depth = integer<S>(\"depth\")\n    }\n\n    inner class PricingColumn<S : DocumentSchema<D>>() : Column<Pricing, S>(\"pricing\", Pricing::class) {\n        val list = integer<S>(\"list\")\n        val retail = integer<S>(\"retail\")\n        val savings = integer<S>(\"savings\")\n        val ptcSavings = integer<S>(\"pct_savings\")\n    }\n}\n\nobject Products : ProductSchema<Product, Products>(Product::class, \"\")\n\nabstract class Product(val id: Id<String, Products>? = null, val sku: String, val title: String, val description: String,\n                       val asin: String, val shipping: Shipping, val pricing: Pricing) {\n    val id: Id<String, Products>? = null\n}\n\nclass Shipping(val weight: Int, val dimensions: Dimensions)\n\nclass Dimensions(val width: Int, val height: Int, val depth: Int)\n\nclass Pricing(val list: Int, val retail: Int, val savings: Int, val pctSavings: Int)\n```\n\n#### Define an inherited schema\n\n```kotlin\nobject Albums : ProductSchema<Album, Albums>(Album::class, discriminator = \"Audio Album\") {\n    val details = DetailsColumn()\n\n    class DetailsColumn() : Column<Details, Albums>(\"details\", Details::class) {\n        val title = string(\"title\")\n        val artistId = id(\"artistId\", Artists)\n        val genre = setOfString(\"genre\")\n\n        val tracks = TracksColumn()\n    }\n\n    class TracksColumn() : ListColumn<Track, Albums>(\"tracks\", Track::class) {\n        val title = string(\"title\")\n        val duration = integer(\"duration\")\n    }\n}\n\nclass Album(sku: String, title: String, description: String, asin: String, shipping: Shipping,\n    pricing: Pricing, val details: Details) : Product(sku, title, description, asin, shipping, pricing)\n\nclass Details(val title: String, val artistId: Id<String, Artists>, val genre: Set<String>, val tracks: List<Track>)\n```\n\n#### Insert a document\n\n```kotlin\nval productId = Products.insert(Album(sku = \"00e8da9b\", title = \"A Love Supreme\", description = \"by John Coltrane\",\n    asin = \"B0000A118M\", shipping = Shipping(weight = 6, dimensions = Dimensions(10, 10, 1)),\n    pricing = Pricing(list = 1200, retail = 1100, savings = 100, pctSavings = 8),\n    details = Details(title = \"A Love Supreme [Original Recording Reissued]\",\n            artistId = artistId, genre = setOf(\"Jazz\", \"General\"),\n            tracks = listOf(Track(\"A Love Supreme Part I: Acknowledgement\", 100),\n                    Track(\"A Love Supreme Part II: Resolution\", 200),\n                    Track(\"A Love Supreme, Part III: Pursuance\", 300)))))\n}\n```\n\n#### Access documents via an abstract schema\n\n```kotlin\nfor (product in Products.find { id.equal(productId) }) {\n    if (product is Album) {\n    }\n}\n```\n\n#### Access documents via an inherited schema\n\n```kotlin\n\nval album = Albums.find { details.artistId.equal(artistId) }.single()\n```\n\n## Examples\n\n- [PetClinic Sample Application](http://kotlin-nosql-mongodb-petclinic.herokuapp.com) ([GitHub](https://github.com/cheptsov/kotlin-nosql-mongodb-petclinic))\n"
  },
  {
    "path": "build.gradle",
    "content": "configurations.all {\n    // check for updates every build\n    resolutionStrategy.cacheChangingModulesFor 0, 'seconds'\n}\n\nbuildscript {\n    repositories {\n        mavenCentral()\n        maven {\n            url \"http://oss.sonatype.org/content/repositories/snapshots\"\n        }\n    }\n    dependencies {\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.0\"\n    }\n}\n\nallprojects {\n    apply plugin: \"kotlin\"\n\n    group = \"org.jetbrains.kotlin\"\n    version = \"0.1-SNAPSHOT\"\n\n    repositories {\n        mavenCentral()\n        maven {\n            url \"http://repository.jetbrains.com/spek\"\n        }\n        maven {\n            url \"http://oss.sonatype.org/content/repositories/snapshots\"\n        }\n    }\n\n    apply plugin: \"maven\"\n\n    dependencies {\n        compile 'joda-time:joda-time:2.3'\n        compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: '1.0.0', changing: true\n        testCompile group: 'org.jetbrains.spek', name: 'spek', version: '0.1.195', changing: true\n    }\n\n    task sourcesJar(type: Jar, dependsOn: classes) {\n        classifier 'sources'\n        from sourceSets.main.allSource\n    }\n\n    artifacts {\n        archives sourcesJar\n    }\n\n/*\n    uploadArchives {\n        repositories {\n            mavenDeployer {\n                repository(url: \"http://repository.jetbrains.com/kotlin-nosql\") {\n                    authentication(userName: deploy_username, password: deploy_password)\n                }\n                pom.groupId = project.group\n                pom.artifactId = project.name\n                pom.version = project.version\n            }\n        }\n    }\n*/\n}\n\nproject(':kotlin-nosql-mongodb') {\n    dependencies {\n        compile project(':')\n        compile 'org.mongodb:mongo-java-driver:3.0.3'\n    }\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Tue Sep 30 10:02:29 PDT 2014\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-2.1-bin.zip\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\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=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched.\nif $cygwin ; then\n    [ -n \"$JAVA_HOME\" ] && JAVA_HOME=`cygpath --unix \"$JAVA_HOME\"`\nfi\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >&-\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >&-\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\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\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "kotlin-nosql-mongodb/build.gradle",
    "content": ""
  },
  {
    "path": "kotlin-nosql-mongodb/kotlin-nosql-mongodb.iml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module external.linked.project.id=\":kotlin-nosql-mongodb\" external.linked.project.path=\"$MODULE_DIR$\" external.root.project.path=\"$MODULE_DIR$/..\" external.system.id=\"GRADLE\" external.system.module.group=\"org.jetbrains.kotlin\" external.system.module.version=\"0.1-SNAPSHOT\" type=\"JAVA_MODULE\" version=\"4\">\n  <component name=\"NewModuleRootManager\" inherit-compiler-output=\"false\">\n    <output url=\"file://$MODULE_DIR$/build/classes/main\" />\n    <output-test url=\"file://$MODULE_DIR$/build/classes/test\" />\n    <exclude-output />\n    <content url=\"file://$MODULE_DIR$\">\n      <sourceFolder url=\"file://$MODULE_DIR$/src/main/java\" isTestSource=\"false\" />\n      <sourceFolder url=\"file://$MODULE_DIR$/src/main/kotlin\" isTestSource=\"false\" />\n      <sourceFolder url=\"file://$MODULE_DIR$/src/test/java\" isTestSource=\"true\" />\n      <sourceFolder url=\"file://$MODULE_DIR$/src/test/kotlin\" isTestSource=\"true\" />\n      <sourceFolder url=\"file://$MODULE_DIR$/src/main/resources\" type=\"java-resource\" />\n      <sourceFolder url=\"file://$MODULE_DIR$/src/test/resources\" type=\"java-test-resource\" />\n      <excludeFolder url=\"file://$MODULE_DIR$/.gradle\" />\n      <excludeFolder url=\"file://$MODULE_DIR$/build\" />\n    </content>\n    <orderEntry type=\"inheritedJdk\" />\n    <orderEntry type=\"sourceFolder\" forTests=\"false\" />\n    <orderEntry type=\"module\" module-name=\"kotlin-nosql\" exported=\"\" />\n    <orderEntry type=\"library\" exported=\"\" name=\"Gradle: joda-time:joda-time:2.3\" level=\"project\" />\n    <orderEntry type=\"library\" exported=\"\" name=\"Gradle: org.mongodb:mongo-java-driver:3.0.3\" level=\"project\" />\n    <orderEntry type=\"library\" scope=\"TEST\" name=\"Gradle: junit:junit:4.11\" level=\"project\" />\n    <orderEntry type=\"library\" scope=\"TEST\" name=\"Gradle: org.hamcrest:hamcrest-core:1.3\" level=\"project\" />\n    <orderEntry type=\"library\" exported=\"\" name=\"Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.0.0\" level=\"project\" />\n    <orderEntry type=\"library\" exported=\"\" name=\"Gradle: org.jetbrains.kotlin:kotlin-runtime:1.0.0\" level=\"project\" />\n    <orderEntry type=\"library\" scope=\"TEST\" name=\"Gradle: org.jetbrains.spek:spek:0.1.195\" level=\"project\" />\n    <orderEntry type=\"library\" scope=\"TEST\" name=\"Gradle: org.jetbrains.kotlin:kotlin-reflect:1.0.0\" level=\"project\" />\n    <orderEntry type=\"library\" scope=\"TEST\" name=\"Gradle: org.jetbrains.kotlin:kotlin-test:1.0.0\" level=\"project\" />\n  </component>\n</module>"
  },
  {
    "path": "kotlin-nosql-mongodb/src/main/kotlin/kotlinx/nosql/mongodb/DocumentSchema.kt",
    "content": "package kotlinx.nosql.mongodb\n\nimport kotlinx.nosql.AbstractColumn\nimport kotlinx.nosql.Discriminator\nimport kotlinx.nosql.string\nimport kotlin.reflect.KClass\n\nabstract class DocumentSchema<D: Any>(name: String, valueClass: KClass<D>, discriminator: Discriminator<out Any, out kotlinx.nosql.DocumentSchema<String, D>>? = null) : kotlinx.nosql.DocumentSchema<String, D>(name, valueClass, string(\"_id\"), discriminator) {\n    fun ensureIndex(name: String = \"\", unique: Boolean = false,\n                             ascending: Array<out AbstractColumn<*, *, *>> = arrayOf<AbstractColumn<*, *, *>>(),\n                             descending: Array<out AbstractColumn<*, *, *>> = arrayOf<AbstractColumn<*, *, *>>(),\n                             text: Array<out AbstractColumn<*, *, String>> = arrayOf<AbstractColumn<*, *, String>>()) {\n        indices.add(MongoDBIndex(name, unique, ascending, descending, text))\n    }\n}"
  },
  {
    "path": "kotlin-nosql-mongodb/src/main/kotlin/kotlinx/nosql/mongodb/MongoDB.kt",
    "content": "package kotlinx.nosql.mongodb\n\nimport kotlinx.nosql.Database\nimport kotlinx.nosql.Session\nimport com.mongodb.MongoClient\nimport kotlinx.nosql.AbstractColumn\nimport kotlinx.nosql.util.*\nimport java.util.concurrent.ConcurrentHashMap\nimport com.mongodb.ServerAddress\nimport com.mongodb.MongoClientOptions\nimport com.mongodb.MongoClientURI\nimport kotlinx.nosql.SchemaGenerationAction\nimport kotlinx.nosql.Create\nimport kotlinx.nosql.CreateDrop\nimport kotlinx.nosql.Validate\nimport kotlinx.nosql.Update\nimport kotlinx.nosql.AbstractSchema\nimport com.mongodb.MongoCredential\n\nfun MongoDB(uri: MongoClientURI, schemas: Array<out AbstractSchema>, initialization: SchemaGenerationAction<MongoDBSession> = Validate()): MongoDB {\n    val seeds: Array<ServerAddress> = uri.getHosts()!!.map { host ->\n        if (host.indexOf(':') > 0) {\n            val tokens = host.split(':')\n            ServerAddress(tokens[0], tokens[1].toInt())\n        } else\n            ServerAddress(host)\n    }.toTypedArray()\n    val database: String = if (uri.getDatabase() != null) uri.getDatabase()!! else \"test\"\n    val options: MongoClientOptions = uri.getOptions()!!\n    val credentials = if (uri.getUsername() != null)\n      arrayOf(MongoCredential.createMongoCRCredential(uri.getUsername(), database, uri.getPassword())!!)\n    else arrayOf()\n  return MongoDB(seeds, database, credentials, options, schemas, initialization)\n}\n\n// TODO: Allow use more than one database\nclass MongoDB(seeds: Array<ServerAddress> = arrayOf(ServerAddress()), val database: String = \"test\",\n              val credentials: Array<MongoCredential> = arrayOf(), val options: MongoClientOptions = MongoClientOptions.Builder().build()!!,\n              schemas: Array<out AbstractSchema>, action: SchemaGenerationAction<MongoDBSession> = Validate()) : Database<MongoDBSession>(schemas, action) {\n    val seeds = seeds\n    val db = MongoClient(seeds.toList(), credentials.toList(), options).getDB(database)!!\n    var session = MongoDBSession(db)\n\n    init {\n        initialize()\n    }\n\n    // TODO: Use session pool\n    override fun <R> withSession(statement: MongoDBSession.() -> R): R {\n        Session.threadLocale.set(session)\n        val r = session.statement()\n        Session.threadLocale.set(null)\n        return r\n    }\n}\n"
  },
  {
    "path": "kotlin-nosql-mongodb/src/main/kotlin/kotlinx/nosql/mongodb/MongoDBIndex.kt",
    "content": "package kotlinx.nosql.mongodb\n\nimport kotlinx.nosql.AbstractColumn\nimport kotlinx.nosql.AbstractIndex\n\nclass MongoDBIndex(name: String = \"\", unique: Boolean = false, val ascending: Array<out AbstractColumn<*, *, *>>,\n                   val descending: Array<out AbstractColumn<*, *, *>>,\n                   val text: Array<out AbstractColumn<*, *, String>>) : AbstractIndex(name)"
  },
  {
    "path": "kotlin-nosql-mongodb/src/main/kotlin/kotlinx/nosql/mongodb/MongoDBSession.kt",
    "content": "package kotlinx.nosql.mongodb\n\nimport com.mongodb.DB\nimport com.mongodb.BasicDBObject\nimport java.lang.reflect.Field\nimport java.util.ArrayList\nimport java.util.HashMap\nimport com.mongodb.DBObject\nimport java.util.Arrays\nimport org.bson.types.ObjectId\nimport com.mongodb.BasicDBList\nimport kotlinx.nosql.*\nimport kotlinx.nosql.util.*\nimport java.util.regex.Pattern\nimport java.util.Date\nimport java.util.concurrent.atomic.AtomicReference\nimport org.joda.time.DateTime\nimport org.joda.time.format.ISODateTimeFormat\nimport org.joda.time.LocalDate\nimport org.joda.time.LocalTime\nimport com.mongodb.DBCollection\nimport com.mongodb.DBCursor\nimport kotlinx.nosql.query.*\nimport kotlin.collections.*\nimport kotlin.text.*\n\nclass MongoDBSession(val db: DB) : Session, DocumentSchemaOperations, TableSchemaOperations, IndexOperations {\n    override fun <T : Number> incr(schema: KeyValueSchema, column: AbstractColumn<out Any?, out AbstractSchema, T>, value: T): T {\n        throw UnsupportedOperationException()\n    }\n    /*override fun <T : Number> incr(schema: AbstractSchema, column: AbstractColumn<out Any?, out AbstractSchema, T>, value: T, op: Query): T {\n        throw UnsupportedOperationException()\n    }*/\n    val dbVersion : String\n    val searchOperatorSupported: Boolean\n\n    init {\n        val results = db.command(\"buildInfo\")\n        dbVersion = results!!.get(\"version\")!!.toString()\n        val versions = dbVersion.split('.')\n        searchOperatorSupported = versions[0].toInt() > 2 || (versions[0].toInt() == 2 && versions[1].toInt() >= 6)\n    }\n\n    override fun createIndex(schema: AbstractSchema, index: AbstractIndex) {\n        val collection = db.getCollection(schema.schemaName)!!\n        val dbObject = BasicDBObject()\n        val i = (index as MongoDBIndex)\n        for (column in i.ascending) {\n            dbObject.append(column.name, 1)\n        }\n        for (column in i.descending) {\n            dbObject.append(column.name, -1)\n        }\n        for (column in i.text) {\n            dbObject.append(column.name, \"text\")\n        }\n        if (i.name.isNotEmpty())\n            collection.createIndex(dbObject, i.name)\n        else\n            collection.createIndex(dbObject)\n    }\n\n    override fun <T : AbstractSchema> T.create() {\n        db.createCollection(this.schemaName, BasicDBObject())\n    }\n\n    override fun <T : AbstractSchema> T.drop() {\n        val collection = db.getCollection(this.schemaName)!!\n        collection.drop()\n    }\n\n    override fun <T : kotlinx.nosql.DocumentSchema<P, V>, P: Any, V: Any> T.insert(v: V): Id<P, T> {\n        val collection = db.getCollection(this.schemaName)!!\n        val doc = getDBObject(v, this)\n        if (discriminator != null) {\n            var dominatorValue: Any? = null\n            for (entry in kotlinx.nosql.DocumentSchema.discriminatorClasses.entries) {\n                if (entry.value.java.equals(v.javaClass)) {\n                    dominatorValue = entry.key.value\n                }\n            }\n            doc.set(this.discriminator!!.column.name, dominatorValue!!)\n        }\n        collection.insert(doc)\n        return Id<P, T>(doc.get(\"_id\").toString() as P)\n    }\n\n    private fun getDBObject(o: Any, schema: Any): BasicDBObject {\n        val doc = BasicDBObject()\n        val javaClass = o.javaClass\n        val fields = getAllFields(javaClass)\n        var sc: Class<out Any?>? = null\n        var s: AbstractSchema? = null\n        if (schema is kotlinx.nosql.DocumentSchema<*, *> && schema.discriminator != null) {\n            for (entry in kotlinx.nosql.DocumentSchema.discriminatorClasses.entries) {\n                if (entry.value.java.equals(o.javaClass)) {\n                    sc = kotlinx.nosql.DocumentSchema.discriminatorSchemaClasses.get(entry.key)!!\n                    s = kotlinx.nosql.DocumentSchema.discriminatorSchemas.get(entry.key)!!\n                }\n            }\n        }\n        val schemaClass: Class<out Any?> = if (schema is kotlinx.nosql.DocumentSchema<*, *> && schema.discriminator != null) sc!! else schema.javaClass\n        val objectSchema: Any = if (schema is kotlinx.nosql.DocumentSchema<*, *> && schema.discriminator != null) s!! else schema\n        val schemaFields = getAllFieldsMap(schemaClass as Class<in Any>, { f -> f.isColumn })\n        for (field in fields) {\n            val schemaField = schemaFields.get(field.getName()!!.toLowerCase())\n            if (schemaField != null && schemaField.isColumn) {\n                field.setAccessible(true)\n                schemaField.setAccessible(true)\n                val column = schemaField.asColumn(objectSchema)\n                val value = field.get(o)\n                if (value != null) {\n                    if (column.columnType.primitive) {\n                        doc.append(column.name, when (value) {\n                            is DateTime, is LocalDate, is LocalTime -> value.toString()\n                            is Id<*, *> -> ObjectId(value.value.toString())\n                            else -> value\n                        })\n                    } else if (column.columnType.iterable) {\n                        val list = BasicDBList()\n                        for (v in (value as Iterable<Any>)) {\n                            list.add(if (column.columnType.custom) getDBObject(v, column) else\n                                (if (v is Id<*, *>) ObjectId(v.toString()) else v))\n                        }\n                        doc.append(column.name, list)\n                    } else doc.append(column.name, getDBObject(value, column))\n                }\n            }\n        }\n        return doc\n    }\n\n    override fun <T : kotlinx.nosql.DocumentSchema<P, C>, P: Any, C: Any> find(params: DocumentSchemaQueryParams<T, P, C>): Iterator<C> {\n        if (params.query != null && !searchOperatorSupported && params.query!!.usesSearch())\n          return params.schema.runCommandText(params.query!!)\n        else\n          return object : Iterator<C> {\n            var cursor: DBCursor? = null\n            var pos = 0\n            override fun next(): C {\n              if (cursor == null) {\n                val collection = db.getCollection(params.schema.schemaName)\n                val query = if (params.query != null) getQuery(params.query!!) else BasicDBObject()\n                cursor = collection!!.find(query)!!\n                if (params.skip != null) {\n                  cursor!!.skip(params.skip!!)\n                }\n              }\n              val value = getObject(cursor!!.next(), params.schema) as C\n              pos++\n              if (!cursor!!.hasNext() || (params.take != null && pos == params.take!!)) {\n                cursor!!.close()\n                pos = -1\n              }\n              return value\n            }\n            override fun hasNext(): Boolean {\n              if (cursor == null) {\n                val collection = db.getCollection(params.schema.schemaName)\n                val query = if (params.query != null) getQuery(params.query!!) else BasicDBObject()\n                cursor = collection!!.find(query)!!\n                if (params.skip != null) {\n                  cursor!!.skip(params.skip!!)\n                }\n              }\n              return pos != -1 && cursor!!.hasNext() && (params.take == null || pos < params.take!!)\n            }\n          }\n    }\n\n    private fun <T : kotlinx.nosql.DocumentSchema<P, C>, P: Any, C: Any> T.runCommandText(op: Query): Iterator<C> {\n      val searchCmd = BasicDBObject()\n      searchCmd.append(\"text\", this.schemaName)\n      // TODO: Only supports text(...) and other condition\n      searchCmd.append(\"search\", when (op) {\n        is TextQuery -> op.search\n        is AndQuery -> if (op.expr1 is TextQuery) (op.expr1 as TextQuery).search else throw UnsupportedOperationException()\n        else -> throw UnsupportedOperationException()\n      })\n      val schema = this\n      if (op is AndQuery) {\n        searchCmd.append(\"filter\", getQuery(op.expr2))\n      }\n      val result = db.command(searchCmd)!!\n\n      val objects = ArrayList<C>()\n      for (doc in result.get(\"results\") as BasicDBList) {\n        objects.add(getObject((doc as DBObject).get(\"obj\") as DBObject, schema))\n      }\n\n      return objects.iterator()\n    }\n\n    override fun <T : TableSchema<P>, P: Any, V: Any> find(params: TableSchemaProjectionQueryParams<T, P, V>): Iterator<V> {\n        return object:Iterator<V> {\n            var cursor: DBCursor? = null\n            var pos = 0\n            override fun next(): V {\n                if (cursor == null) {\n                    val collection = db.getCollection(params.table.schemaName)\n                    val fields = BasicDBObject()\n                    params.projection.forEach {\n                        fields.append(it.fullName, \"1\")\n                    }\n                    val query = if (params.query != null) getQuery(params.query!!) else BasicDBObject()\n                    cursor = collection!!.find(query, fields)!!\n                    if (params.skip != null) {\n                        cursor!!.skip(params.skip!!)\n                    }\n                }\n                val doc = cursor!!.next()\n                val values = ArrayList<Any?>()\n                params.projection.forEach {\n                    values.add(getColumnObject(doc, it))\n                }\n                val value = when (values.size) {\n                    1 -> values[0] as V\n                    2 -> Pair(values[0], values[1]) as V\n                    3 -> Triple(values[0], values[1], values[2]) as V\n                    4 -> Quadruple(values[0], values[1], values[2], values[3]) as V\n                    5 -> Quintuple(values[0], values[1], values[2], values[3], values[4]) as V\n                    6 -> Sextuple(values[0], values[1], values[2], values[3], values[4], values[5]) as V\n                    7 -> Septuple(values[0], values[1], values[2], values[3], values[4], values[5], values[6]) as V\n                    8 -> Octuple(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7]) as V\n                    9 -> Nonuple(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8]) as V\n                    10 -> Decuple(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9]) as V\n                    else -> throw UnsupportedOperationException()\n                }\n                pos++\n                if (!cursor!!.hasNext() || (params.take != null && pos == params.take!!)) {\n                    cursor!!.close()\n                    pos = -1\n                }\n                return value\n            }\n            override fun hasNext(): Boolean {\n                if (cursor == null) {\n                    val collection = db.getCollection(params.table.schemaName)\n                    val fields = BasicDBObject()\n                    params.projection.forEach {\n                        fields.append(it.fullName, \"1\")\n                    }\n                    val query = if (params.query != null) getQuery(params.query!!) else BasicDBObject()\n                    cursor = collection!!.find(query, fields)!!\n                    if (params.skip != null) {\n                        cursor!!.skip(params.skip!!)\n                    }\n                }\n                return pos != -1 && cursor!!.hasNext() && (params.take == null || pos < params.take!!)\n            }\n        }\n    }\n\n    private fun Query.usesSearch(): Boolean {\n        return when (this) {\n            is TextQuery -> true\n            is OrQuery -> this.expr1.usesSearch() || this.expr2.usesSearch()\n            is AndQuery -> this.expr1.usesSearch() || this.expr2.usesSearch()\n            else -> false\n        }\n    }\n\n    protected fun getQuery(op: Query, removePrefix: String = \"\"): BasicDBObject {\n        val query = BasicDBObject()\n        when (op) {\n            is EqualQuery -> {\n                if (op.expr1 is AbstractColumn<*, *, *>) {\n                    if (op.expr2 is LiteralExpression) {\n                        if ((op.expr1 as AbstractColumn<*, *, *>).columnType.primitive) {\n                            if ((op.expr1 as AbstractColumn<*, *, *>).columnType.id) {\n                                query.append((op.expr1 as AbstractColumn<*, *, *>).fullName, ObjectId((op.expr2 as LiteralExpression).value.toString()))\n                            } else {\n                                var columnName = (op.expr1 as AbstractColumn<*, *, *>).fullName\n                                if (removePrefix.isNotEmpty() && columnName.startsWith(removePrefix)) {\n                                    columnName = columnName.substring(removePrefix.length + 1)\n                                }\n                                query.append( columnName, (op.expr2 as LiteralExpression).value)\n                            }\n                        } else {\n                            throw UnsupportedOperationException()\n                        }\n                    } else if (op.expr2 is AbstractColumn<*, *, *>) {\n                        query.append(\"\\$where\", \"this.${(op.expr1 as AbstractColumn<*, *, *>).fullName} == this.${(op.expr2 as AbstractColumn<*, *, *>).fullName}\")\n                    } else {\n                        throw UnsupportedOperationException()\n                    }\n                } else {\n                    throw UnsupportedOperationException()\n                }\n            }\n            is MatchesQuery -> {\n                if (op.expr1 is AbstractColumn<*, *, *>) {\n                    if (op.expr2 is LiteralExpression) {\n                        if ((op.expr2 as LiteralExpression).value is Pattern) {\n                            query.append((op.expr1 as AbstractColumn<*, *, *>).fullName, BasicDBObject().append(\"\\$regex\", (op.expr2 as LiteralExpression).value))\n                        } else {\n                            throw UnsupportedOperationException()\n                        }\n                    } else {\n                        throw UnsupportedOperationException()\n                    }\n                } else {\n                    throw UnsupportedOperationException()\n                }\n            }\n            is NotEqualQuery -> {\n                if (op.expr1 is AbstractColumn<*, *, *>) {\n                    if (op.expr2 is LiteralExpression) {\n                        if ((op.expr2 as LiteralExpression).value is String || (op.expr2 as LiteralExpression).value is Int) {\n                            if ((op.expr1 as AbstractColumn<*, *, *>).columnType.id) {\n                                query.append((op.expr1 as AbstractColumn<*, *, *>).fullName, BasicDBObject().append(\"\\$ne\", ObjectId((op.expr2 as LiteralExpression).value.toString())))\n                            } else {\n                                query.append((op.expr1 as AbstractColumn<*, *, *>).fullName, BasicDBObject().append(\"\\$ne\", (op.expr2 as LiteralExpression).value))\n                            }\n                        } else {\n                            throw UnsupportedOperationException()\n                        }\n                    } else if (op.expr2 is AbstractColumn<*, *, *>) {\n                        query.append(\"\\$where\", \"this.${(op.expr1 as AbstractColumn<*, *, *>).fullName} != this.${(op.expr2 as AbstractColumn<*, *, *>).fullName}\")\n                    } else {\n                        throw UnsupportedOperationException()\n                    }\n                } else {\n                    throw UnsupportedOperationException()\n                }\n            }\n            is GreaterQuery -> {\n                if (op.expr1 is AbstractColumn<*, *, *>) {\n                    if (op.expr2 is LiteralExpression) {\n                        if ((op.expr2 as LiteralExpression).value is String || (op.expr2 as LiteralExpression).value is Int) {\n                            query.append((op.expr1 as AbstractColumn<*, *, *>).fullName, BasicDBObject().append(\"\\$gt\", (op.expr2 as LiteralExpression).value))\n                        } else {\n                            throw UnsupportedOperationException()\n                        }\n                    } else if (op.expr2 is AbstractColumn<*, *, *>) {\n                        query.append(\"\\$where\", \"this.${(op.expr1 as AbstractColumn<*, *, *>).fullName} > this.${(op.expr2 as AbstractColumn<*, *, *>).fullName}\")\n                    } else {\n                        throw UnsupportedOperationException()\n                    }\n                } else {\n                    throw UnsupportedOperationException()\n                }\n            }\n            is LessQuery -> {\n                if (op.expr1 is AbstractColumn<*, *, *>) {\n                    if (op.expr2 is LiteralExpression) {\n                        if ((op.expr2 as LiteralExpression).value is String || (op.expr2 as LiteralExpression).value is Int) {\n                            query.append((op.expr1 as AbstractColumn<*, *, *>).fullName, BasicDBObject().append(\"\\$lt\", (op.expr2 as LiteralExpression).value))\n                        } else {\n                            throw UnsupportedOperationException()\n                        }\n                    } else if (op.expr2 is AbstractColumn<*, *, *>) {\n                        query.append(\"\\$where\", \"this.${(op.expr1 as AbstractColumn<*, *, *>).fullName} < this.${(op.expr2 as AbstractColumn<*, *, *>).fullName}\")\n                    } else {\n                        throw UnsupportedOperationException()\n                    }\n                } else {\n                    throw UnsupportedOperationException()\n                }\n            }\n            is GreaterEqualQuery -> {\n                if (op.expr1 is AbstractColumn<*, *, *>) {\n                    if (op.expr2 is LiteralExpression) {\n                        if ((op.expr2 as LiteralExpression).value is String || (op.expr2 as LiteralExpression).value is Int) {\n                            query.append((op.expr1 as AbstractColumn<*, *, *>).fullName, BasicDBObject().append(\"\\$gte\", (op.expr2 as LiteralExpression).value))\n                        } else {\n                            throw UnsupportedOperationException()\n                        }\n                    } else if (op.expr2 is AbstractColumn<*, *, *>) {\n                        query.append(\"\\$where\", \"this.${(op.expr1 as AbstractColumn<*, *, *>).fullName} >= this.${(op.expr2 as AbstractColumn<*, *, *>).fullName}\")\n                    } else {\n                        throw UnsupportedOperationException()\n                    }\n                } else {\n                    throw UnsupportedOperationException()\n                }\n            }\n            is LessEqualQuery -> {\n                if (op.expr1 is AbstractColumn<*, *, *>) {\n                    if (op.expr2 is LiteralExpression) {\n                        if ((op.expr2 as LiteralExpression).value is String || (op.expr2 as LiteralExpression).value is Int) {\n                            query.append((op.expr1 as AbstractColumn<*, *, *>).fullName, BasicDBObject().append(\"\\$lte\", (op.expr2 as LiteralExpression).value))\n                        } else {\n                            throw UnsupportedOperationException()\n                        }\n                    } else if (op.expr2 is AbstractColumn<*, *, *>) {\n                        query.append(\"\\$where\", \"this.${(op.expr1 as AbstractColumn<*, *, *>).fullName} <= this.${(op.expr2 as AbstractColumn<*, *, *>).fullName}\")\n                    } else {\n                        throw UnsupportedOperationException()\n                    }\n                } else {\n                    throw UnsupportedOperationException()\n                }\n            }\n            is MemberOfQuery -> {\n                if (op.expr1 is AbstractColumn<*, *, *>) {\n                    if (op.expr2 is LiteralExpression) {\n                        if ((op.expr2 as LiteralExpression).value is List<*> || (op.expr2 as LiteralExpression).value is Array<*>) {\n                            query.append((op.expr1 as AbstractColumn<*, *, *>).fullName, BasicDBObject().append(\"\\$in\", (op.expr2 as LiteralExpression).value))\n                        } else {\n                            throw UnsupportedOperationException()\n                        }\n                    } else {\n                        throw UnsupportedOperationException()\n                    }\n                } else {\n                    throw UnsupportedOperationException()\n                }\n            }\n            is NotMemberOfQuery -> {\n                if (op.expr1 is AbstractColumn<*, *, *>) {\n                    if (op.expr2 is LiteralExpression) {\n                        if ((op.expr2 as LiteralExpression).value is List<*> || (op.expr2 as LiteralExpression).value is Array<*>) {\n                            query.append((op.expr1 as AbstractColumn<*, *, *>).fullName, BasicDBObject().append(\"\\$nin\", (op.expr2 as LiteralExpression).value))\n                        } else {\n                            throw UnsupportedOperationException()\n                        }\n                    } else {\n                        throw UnsupportedOperationException()\n                    }\n                } else {\n                    throw UnsupportedOperationException()\n                }\n            }\n            // TODO TODO TODO eq expression and eq expression\n            is AndQuery -> {\n                val query1 = getQuery(op.expr1)\n                val query2 = getQuery(op.expr2)\n                for (entry in query1.entries) {\n                    query.append(entry.key, entry.value)\n                }\n                for (entry in query2.entries) {\n                    query.append(entry.key, entry.value)\n                }\n                return query\n            }\n            is OrQuery -> {\n                query.append(\"\\$or\", Arrays.asList(getQuery(op.expr1), getQuery(op.expr2)))\n            }\n            is TextQuery -> {\n                query.append(\"\\$text\", BasicDBObject().append(\"\\$search\", op.search))\n            }\n            is NoQuery -> {\n                // Do nothing\n            }\n            else -> {\n                throw UnsupportedOperationException()\n            }\n        }\n        return query\n    }\n\n    private fun <T: kotlinx.nosql.DocumentSchema<P, V>, P: Any, V : Any /* not sure */> getObject(doc: DBObject, schema: T): V {\n        var s: AbstractSchema? = null\n        val valueInstance: Any = if (schema is kotlinx.nosql.DocumentSchema<*, *> && schema.discriminator != null) {\n            var instance: Any? = null\n            val discriminatorValue = doc.get(schema.discriminator!!.column.name)\n            for (discriminator in kotlinx.nosql.DocumentSchema.tableDiscriminators.get(schema.schemaName)!!) {\n                if (discriminator.value!!.equals(discriminatorValue)) {\n                    instance = newInstance(kotlinx.nosql.DocumentSchema.discriminatorClasses.get(discriminator)!!.java)\n                    s = kotlinx.nosql.DocumentSchema.discriminatorSchemas.get(discriminator)!!\n                    break\n                }\n            }\n            instance!!\n        } else {\n            s = schema\n            newInstance(schema.valueClass.java)\n        }\n        val schemaClass = s!!.javaClass\n        val schemaFields = getAllFields(schemaClass as Class<in Any?>)\n        val valueFields = getAllFieldsMap(valueInstance.javaClass as Class<in Any?>)\n        for (schemaField in schemaFields) {\n            if (AbstractColumn::class.java.isAssignableFrom(schemaField.getType()!!)) {\n                val valueField = valueFields.get(if (schemaField.getName()!!.equals(\"pk\")) \"id\" else schemaField.getName()!!.toLowerCase())\n                if (valueField != null) {\n                    schemaField.setAccessible(true)\n                    valueField.setAccessible(true)\n                    val column = schemaField.asColumn(s!!)\n                    val value = doc.get(column.name)\n                    val columnValue: Any? = if (value == null) {\n                        null\n                    } else if (column.columnType.id && !column.columnType.iterable)\n                        Id<P, T>(value.toString() as P)\n                    else if (column.columnType.primitive) {\n                        when (column.columnType) {\n                            ColumnType.DATE -> LocalDate(value.toString())\n                            ColumnType.TIME -> LocalTime(value.toString())\n                            ColumnType.DATE_TIME -> DateTime(value.toString())\n                            else -> doc.get(column.name)\n                        }\n                    } else if (column.columnType.list && !column.columnType.custom) {\n                        (doc.get(column.name) as BasicDBList).toList()\n                    } else if (column.columnType.set && !column.columnType.custom && !column.columnType.id) {\n                        (doc.get(column.name) as BasicDBList).toSet()\n                    } else if (column.columnType.id && column.columnType.set) {\n                        val list = doc.get(column.name) as BasicDBList\n                        list.map { Id<String, TableSchema<String>>(it.toString()) }.toSet()\n                    } else if (column.columnType.custom && column.columnType.set) {\n                        val list = doc.get(column.name) as BasicDBList\n                        list.map { getObject(it as DBObject, column as ListColumn<*, out AbstractSchema>) }.toSet()\n                    } else if (column.columnType.custom && column.columnType.list) {\n                        val list = doc.get(column.name) as BasicDBList\n                        list.map { getObject(it as DBObject, column as ListColumn<*, out AbstractSchema>) }.toList()\n                    } else {\n                        getObject(doc.get(column.name) as DBObject, column as Column<Any, T>)\n                    }\n                    if (columnValue != null || column is AbstractNullableColumn) {\n                        valueField.set(valueInstance, columnValue)\n                    } else {\n                        throw NullPointerException()\n                    }\n                }\n            }\n        }\n        return valueInstance as V\n    }\n\n    private fun getObject(doc: DBObject, column: AbstractColumn<*, *, *>): Any? {\n        val valueInstance = newInstance(column.valueClass.java)\n        val schemaClass = column.javaClass\n        val columnFields = schemaClass.getDeclaredFields()!!\n        val valueFields = getAllFieldsMap(valueInstance.javaClass as Class<in Any?>)\n        for (columnField in columnFields) {\n            if (columnField.isColumn) {\n                val valueField = valueFields.get(columnField.getName()!!.toLowerCase())\n                if (valueField != null) {\n                    columnField.setAccessible(true)\n                    valueField.setAccessible(true)\n                    val column = columnField.asColumn(column)\n                    val columnValue: Any? = if (column.columnType.id && !column.columnType.iterable) Id<String, TableSchema<String>>(doc.get(column.name).toString())\n                    else if (column.columnType.primitive) doc.get(column.name)\n                    else if (column.columnType.list && !column.columnType.custom) (doc.get(column.name) as BasicDBList).toList()\n                    else if (column.columnType.set && !column.columnType.custom && !column.columnType.id) (doc.get(column.name) as BasicDBList).toSet()\n                    else if (column.columnType.custom && column.columnType.list) {\n                        val list = doc.get(column.name) as BasicDBList\n                        list.map { getObject(it as DBObject, column as ListColumn<*, out AbstractSchema>) }.toList()\n                    } else if (column.columnType.id && column.columnType.set) {\n                        val list = doc.get(column.name) as BasicDBList\n                        list.map { Id<String, TableSchema<String>>(it.toString()) }.toSet()\n                    } else if (column.columnType.custom && column.columnType.set) {\n                        val list = doc.get(column.name) as BasicDBList\n                        list.map { getObject(it as DBObject, column as ListColumn<*, out AbstractSchema>) }.toSet()\n                    } else {\n                        getObject(doc.get(column.name) as DBObject, column as Column<*, out AbstractSchema>)\n                    }\n                    if (columnValue != null || column is AbstractNullableColumn) {\n                        valueField.set(valueInstance, columnValue)\n                    } else {\n                        throw NullPointerException()\n                    }\n                }\n            }\n        }\n        return valueInstance\n    }\n\n    override fun <T : AbstractSchema> insert(columns: Array<Pair<AbstractColumn<out Any?, T, out Any>, Any?>>) {\n        throw UnsupportedOperationException()\n    }\n\n    override fun <T : AbstractSchema> delete(table: T, op: Query): Int {\n        val collection = db.getCollection(table.schemaName)!!\n        val query = getQuery(op)\n        return collection.remove(query)!!.getN()\n    }\n\n    override fun update(schema: AbstractSchema, columnValues: Array<Pair<AbstractColumn<*, *, *>, *>>, op: Query): Int {\n        val collection = db.getCollection(schema.schemaName)!!\n        val statement = BasicDBObject()\n        val doc = BasicDBObject().append(\"\\$set\", statement)\n        for ((column, value) in columnValues) {\n            statement.append(column.fullName, getDBValue(value, column))\n        }\n        return collection.update(getQuery(op), doc)!!.getN()\n    }\n\n    override fun <T> addAll(schema: AbstractSchema, column: AbstractColumn<Collection<T>, *, *>, values: Collection<T>, op: Query): Int {\n        val collection = db.getCollection(schema.schemaName)!!\n        val statement = BasicDBObject()\n        val doc = BasicDBObject().append(\"\\$pushAll\", statement)\n        statement.append(column.fullName, getDBValue(values, column))\n        return collection.update(getQuery(op), doc)!!.getN()\n    }\n\n    override fun <T> removeAll(schema: AbstractSchema, column: AbstractColumn<Collection<T>, *, *>, values: Collection<T>, op: Query): Int {\n        val collection = db.getCollection(schema.schemaName)!!\n        val statement = BasicDBObject()\n        val doc = BasicDBObject().append(\"\\$pullAll\", statement)\n        statement.append(column.fullName, getDBValue(values, column))\n        return collection.update(getQuery(op), doc)!!.getN()\n    }\n\n    override fun <T> removeAll(schema: AbstractSchema, column: AbstractColumn<Collection<T>, *, *>, removeOp: Query, op: Query): Int {\n        val collection = db.getCollection(schema.schemaName)!!\n        val statement = BasicDBObject()\n        val doc = BasicDBObject().append(\"\\$pull\", statement)\n        statement.append(column.fullName, getQuery(removeOp, column.fullName))\n        return collection.update(getQuery(op), doc)!!.getN()\n    }\n\n    private fun getDBValue(value: Any?, column: AbstractColumn<*, *, *>, withinIterable: Boolean = false): Any? {\n        return if (!column.columnType.custom && (!column.columnType.iterable || withinIterable )) {\n            when (value) {\n                is DateTime, is LocalDate, is LocalTime -> value.toString()\n                is Id<*, *> -> ObjectId(value.value.toString())\n                else -> value\n            }\n        } else if (column.columnType.custom && !column.columnType.iterable)\n            if (value != null) getDBObject(value, column) else null\n        else if (column.columnType.list && column.columnType.custom)\n            (value as List<*>).map { getDBObject(it!!, column) }\n        else if (column.columnType.set && column.columnType.custom)\n            (value as Set<*>).map { getDBObject(it!!, column) }.toSet()\n        else if (column.columnType.list && !column.columnType.custom)\n            (value as List<*>).map { getDBValue(it!!, column, true) }\n        else if (column.columnType.set && !column.columnType.custom)\n            (value as Set<*>).map { getDBValue(it!!, column, true) }.toSet()\n        else throw UnsupportedOperationException()\n    }\n\n    private fun getColumnObject(doc: DBObject, column: AbstractColumn<*, *, *>): Any? {\n        val columnObject = parse(doc, column.fullName.split(\".\").toTypedArray())\n        return if (column.columnType.id && !column.columnType.iterable) {\n            Id<String, TableSchema<String>>(columnObject.toString())\n        } else if (column.columnType.primitive && !column.columnType.iterable) when (column.columnType) {\n            ColumnType.DATE -> LocalDate.parse(columnObject.toString())\n            ColumnType.TIME -> LocalTime.parse(columnObject.toString())\n            ColumnType.DATE_TIME -> DateTime.parse(columnObject.toString())\n            else -> columnObject\n        } else if (column.columnType == ColumnType.STRING_SET) {\n            (columnObject as BasicDBList).toSet()\n        } else if (column.columnType == ColumnType.STRING_LIST) {\n            (columnObject as BasicDBList).toList()\n        } else if (column.columnType.id && column.columnType.set) {\n            (columnObject as BasicDBList).map { Id<String, TableSchema<String>>(it.toString()) }.toSet()\n        } else if (column.columnType.id && column.columnType.list) {\n            (columnObject as BasicDBList).map { Id<String, TableSchema<String>>(it.toString()) }\n        } else if (column.columnType.custom && column.columnType.list) {\n            (columnObject as BasicDBList).map { getObject(it as DBObject, column as ListColumn<Any, out AbstractSchema>) }\n        } else if (column.columnType.custom && column.columnType.set) {\n            (columnObject as BasicDBList).map { getObject(it as DBObject, column as ListColumn<Any, out AbstractSchema>) }.toSet()\n        } else if (column.columnType.custom) {\n            getObject(columnObject as DBObject, column)\n        } else {\n            UnsupportedOperationException()\n        }\n    }\n\n    private fun parse(doc: DBObject, path: Array<String>, position: Int = 0): Any? {\n        val value = doc.get(path[position])\n        if (position < path.size - 1) {\n            return parse(value as DBObject, path, position + 1)\n        } else {\n            return value\n        }\n    }\n\n    override fun <T: kotlinx.nosql.DocumentSchema<P, C>, P: Any, C: Any> T.find(query: T.() -> Query): DocumentSchemaQueryWrapper<T, P, C> {\n        val params = DocumentSchemaQueryParams<T, P, C>(this, query())\n        return DocumentSchemaQueryWrapper(params)\n    }\n}\n"
  },
  {
    "path": "kotlin-nosql-mongodb/src/test/kotlin/kotlinx/nosql/mongodb/test/MongoDBSpek.kt",
    "content": "package kotlinx.nosql.mongodb.test\n\nimport kotlin.test.assertEquals\nimport kotlinx.nosql.*\nimport kotlinx.nosql.mongodb.*\nimport kotlinx.nosql.mongodb.DocumentSchema\nimport org.joda.time.LocalDate\nimport org.jetbrains.spek.api.Spek\nimport java.util.regex.Pattern\nimport kotlin.reflect.KClass\nimport kotlin.test.assertTrue\n\nclass MongoDBSpek : Spek() {\n    open class ProductSchema<D: Any, S : DocumentSchema<D>>(klass: KClass<D>, discriminator: String) : DocumentSchema<D>(\"products\",\n            klass, discriminator = Discriminator(string(\"type\"), discriminator)) {\n        val sku = string<S>(\"sku\")\n        val title = string<S>(\"title\")\n        val description = string<S>(\"description\")\n        val asin = string<S>(\"asin\")\n        val available = boolean<S>(\"available\")\n        val createdAtDate = date<S>(\"createdAtDate\")\n        val nullableBooleanNoValue = nullableBoolean<S>(\"nullableBooleanNoValue\")\n        val nullableBooleanWithValue = nullableBoolean<S>(\"nullableBooleanWithValue\")\n        val nullableDateNoValue = nullableDate<S>(\"nullableDateNoValue\")\n        val nullableDateWithValue = nullableDate<S>(\"nullableDateWithValue\")\n        val cost = double<S>(\"cost\")\n        val nullableDoubleNoValue = nullableDouble<S>(\"nullableDoubleNoValue\")\n        val nullableDoubleWithValue = nullableDouble<S>(\"nullableDoubleWithValue\")\n        val setOfStrings = setOfString<S>(\"setOfStrings\")\n\n        val shipping = ShippingColumn<S>()\n        val pricing = PricingColumn<S>()\n\n        inner class ShippingColumn<S : DocumentSchema<D>>() : Column<Shipping, S>(\"shipping\", Shipping::class) {\n            val weight = integer<S>(\"weight\")\n            val dimensions = DimensionsColumn<S>()\n        }\n\n        inner class DimensionsColumn<S : DocumentSchema<D>>() : Column<Dimensions, S>(\"dimensions\", Dimensions::class) {\n            val width = integer<S>(\"width\")\n            val height = integer<S>(\"height\")\n            val depth = integer<S>(\"depth\")\n        }\n\n        inner class PricingColumn<T : DocumentSchema<D>>() : Column<Pricing, T>(\"pricing\", Pricing::class) {\n            val list = integer<T>(\"list\")\n            val retail = integer<T>(\"retail\")\n            val savings = integer<T>(\"savings\")\n            val pctSavings = integer<T>(\"pct_savings\")\n        }\n\n        init {\n            ensureIndex(text = arrayOf(title, description))\n            ensureIndex(name = \"asinIndex\", unique = true, ascending = arrayOf(asin))\n        }\n    }\n\n    object Artists : DocumentSchema<Artist>(\"artists\", Artist::class) {\n        val name = string(\"name\")\n    }\n\n    object Products : ProductSchema<Product, Products>(Product::class, \"\") {\n    }\n\n    object Albums : ProductSchema<Album, Albums>(Album::class, discriminator = \"Audio Album\") {\n        val details = DetailsColumn()\n\n        class DetailsColumn() : Column<Details, Albums>(\"details\", Details::class) {\n            val title: AbstractColumn<String, Albums, String> = string(\"title\")\n            val artistId = id(\"artistId\", Artists)\n            val artistIds = setOfId(\"artistIds\", Artists)\n            val genre = setOfString(\"genre\")\n\n            val tracks = TracksColumn()\n        }\n\n        class TracksColumn() : ListColumn<Track, Albums>(\"tracks\", Track::class) {\n            val title = string(\"title\")\n            val duration = integer(\"duration\")\n        }\n    }\n\n    abstract class Product(val sku: String, val title: String, val description: String,\n                           val asin: String, val available: Boolean, val cost: Double,\n                           val createdAtDate: LocalDate, val nullableBooleanNoValue: Boolean?,\n                           val nullableBooleanWithValue: Boolean?,\n                           val nullableDateNoValue: org.joda.time.LocalDate?, val nullableDateWithValue: LocalDate?,\n                           val nullableDoubleNoValue: Double?, val nullableDoubleWithValue: Double?,\n                           val setOfStrings: Set<String>, val shipping: Shipping, val pricing: Pricing) {\n        val id: Id<String, Products>? = null // How to define id for implementation classes?\n    }\n\n    class Shipping(val weight: Int, val dimensions: Dimensions) {\n    }\n\n    class Dimensions(val width: Int, val height: Int, val depth: Int) {\n    }\n\n    class Pricing(val list: Int, val retail: Int, val savings: Int, val pctSavings: Int) {\n    }\n\n    class Album(sku: String, title: String, description: String, asin: String, available: Boolean,\n                cost: Double, createdAtDate: org.joda.time.LocalDate,\n                nullableBooleanNoValue: Boolean?, nullableBooleanWithValue: Boolean?,\n                nullableDateNoValue: LocalDate?, nullableDateWithValue: LocalDate?,\n                nullableDoubleNoValue: Double?, nullableDoubleWithValue: Double?,\n                setOfStrings: Set<String>, shipping: Shipping, pricing: Pricing,\n                val details: Details) : Product(sku, title, description, asin, available, cost, createdAtDate,\n            nullableBooleanNoValue, nullableBooleanWithValue, nullableDateNoValue, nullableDateWithValue,\n            nullableDoubleNoValue, nullableDoubleWithValue, setOfStrings, shipping, pricing) {\n    }\n\n    class Artist(val name: String) {\n        val id: Id<String, Artists>? = null\n    }\n\n    class Details(val title: String, val artistId: Id<String, Artists>, val artistIds: Set<Id<String, Artists>>,\n                  val genre: Set<String>, val tracks: List<Track>) {\n    }\n\n    class Track(val title: String, val duration: Int) {\n    }\n\n    init {\n        given(\"a polymorhpic schema\") {\n            var artistId: Id<String, Artists>? = null\n            var artistId2: Id<String, Artists>? = null\n            var artistId3: Id<String, Artists>? = null\n            var albumId: Id<String, Albums>? = null\n\n            val db = MongoDB(schemas = arrayOf(Artists, Products, Albums), action = CreateDrop(onCreate = {\n                val arId: Id<String, Artists> = Artists.insert(Artist(name = \"John Coltrane\"))\n                val arId2: Id<String, Artists> = Artists.insert(Artist(name = \"Andrey Cheptsov\"))\n                val arId3: Id<String, Artists> = Artists.insert(Artist(name = \"Daft Punk\"))\n                assert(arId.value.length > 0)\n                val aId = Albums.insert(Album(sku = \"00e8da9b\", title = \"A Love Supreme\", description = \"by John Coltrane\",\n                        asin = \"B0000A118M\", available = true, cost = 1.23, createdAtDate = LocalDate(2014, 3, 8), nullableBooleanNoValue = null,\n                        nullableBooleanWithValue = false, nullableDateNoValue = null, nullableDateWithValue = LocalDate(2014, 3, 7),\n                        nullableDoubleNoValue = null, nullableDoubleWithValue = 1.24,\n                        setOfStrings = setOf(\"Something\"), shipping = Shipping(weight = 6, dimensions = Dimensions(10, 10, 1)),\n                        pricing = Pricing(list = 1200, retail = 1100, savings = 100, pctSavings = 8),\n                        details = Details(title = \"A Love Supreme [Original Recording Reissued]\",\n                                artistId = arId, artistIds = setOf(arId, arId2),\n                                genre = setOf(\"Jazz\", \"General\"), tracks = listOf(Track(\"A Love Supreme Part I: Acknowledgement\", 100),\n                                Track(\"A Love Supreme Part II - Resolution\", 200),\n                                Track(\"A Love Supreme, Part III: Pursuance\", 300)))))\n                assert(aId.value.length > 0)\n                albumId = aId\n                artistId = arId\n                artistId2 = arId2\n                artistId3 = arId3\n            }))\n\n            on(\"filtering a non-inherited schema\") {\n                val a = db.withSession {\n                    val artists = Artists.find { name.equal(\"John Coltrane\") }.toList()\n                    it(\"should return a generated id for artist\") {\n                        assert(artists.size == 1)\n                    }\n                    \"a\"\n                }\n                kotlin.test.assertEquals(\"a\", a)\n            }\n\n            fun validate(results: List<Product>) {\n                assert(results.size == 1)\n                assert(results[0] is Album)\n                val album = results[0] as Album\n                assertEquals(\"00e8da9b\", results[0].sku)\n                assertEquals(true, results[0].available)\n                assertEquals(1.23, results[0].cost)\n                kotlin.test.assertEquals(LocalDate(2014, 3, 8), results[0].createdAtDate)\n                assert(results[0].nullableDateNoValue == null)\n                assertEquals(LocalDate(2014, 3, 7), results[0].nullableDateWithValue)\n                assert(results[0].nullableDoubleNoValue == null)\n                assertEquals(1.24, results[0].nullableDoubleWithValue)\n                assert(results[0].nullableBooleanNoValue == null)\n                assertEquals(false, results[0].nullableBooleanWithValue)\n                kotlin.test.assertEquals(\"A Love Supreme\", results[0].title)\n                assertEquals(\"by John Coltrane\", results[0].description)\n                assertEquals(\"B0000A118M\", results[0].asin)\n                assert(album.setOfStrings.contains(\"Something\"))\n                kotlin.test.assertEquals(6, results[0].shipping.weight)\n                kotlin.test.assertEquals(10, results[0].shipping.dimensions.width)\n                kotlin.test.assertEquals(10, results[0].shipping.dimensions.height)\n                kotlin.test.assertEquals(1, results[0].shipping.dimensions.depth)\n                assertEquals(1200, results[0].pricing.list)\n                kotlin.test.assertEquals(1100, results[0].pricing.retail)\n                assertEquals(100, results[0].pricing.savings)\n                kotlin.test.assertEquals(8, results[0].pricing.pctSavings)\n                kotlin.test.assertEquals(\"A Love Supreme [Original Recording Reissued]\", album.details.title)\n                assertEquals(artistId!!, album.details.artistId)\n                assert(album.details.artistIds.size == 2)\n                assert(album.details.artistIds.contains(artistId as Id<String, Artists>))\n                assert(album.details.artistIds.contains(artistId2))\n                assert(album.details.genre.size == 2)\n                assert(album.details.genre.contains(\"Jazz\"))\n                assert(album.details.genre.contains(\"General\"))\n                assert(album.details.tracks.size == 3)\n                assertEquals(album.details.tracks[0].title, \"A Love Supreme Part I: Acknowledgement\")\n                assertEquals(album.details.tracks[0].duration, 100)\n                assertEquals(album.details.tracks[1].title, \"A Love Supreme Part II - Resolution\")\n                assertEquals(album.details.tracks[1].duration, 200)\n                assertEquals(album.details.tracks[2].title, \"A Love Supreme, Part III: Pursuance\")\n                kotlin.test.assertEquals(album.details.tracks[2].duration, 300)\n            }\n\n            /**\n             * Remove Rxjava\n             * Replace Observable with Iterable\n             */\n\n            on(\"filtering an abstract schema\") {\n                db.withSession {\n                    val results = Products.find { (sku.equal(\"00e8da9b\")).or(shipping.weight.equal(6)) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering a non-abstract schema\") {\n                db.withSession {\n                    val results: List<Album> = Albums.find { details.artistId.equal(artistId!!) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering a non-abstract schema drop take\") {\n                db.withSession {\n                    val results = Products.find { (sku.equal(\"00e8da9b\")).or(shipping.weight.equal(6)) }.skip(1).take(1).toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"getting all elements from a non-abstract schema\") {\n                db.withSession {\n                    val results = Products.find().toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"getting a document by id\") {\n                db.withSession {\n                    val album = Albums.find { id.equal(albumId!!) }.single()\n                    it(\"should return a correct object\") {\n                        validate(listOf(album))\n                    }\n                }\n            }\n\n            on(\"getting one column by id\") {\n                db.withSession {\n                    val title = Albums.find { id.equal(albumId!!) }.projection { details.title }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"A Love Supreme [Original Recording Reissued]\", title)\n                    }\n                }\n            }\n\n            on(\"getting two columns by id\") {\n                db.withSession {\n                    val (title, pricing) = Albums.find { id.equal(albumId!!) }.projection { details.title + pricing }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"A Love Supreme [Original Recording Reissued]\", title)\n                        assertEquals(1200, pricing.list)\n                        assertEquals(1100, pricing.retail)\n                        assertEquals(100, pricing.savings)\n                        assertEquals(8, pricing.pctSavings)\n                    }\n                }\n            }\n\n            on(\"getting three columns by id\") {\n                db.withSession {\n                    val (sku, title, pricing) = Albums.find { id.equal(albumId!!) }.projection { sku + details.title + pricing }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme [Original Recording Reissued]\", title)\n                        assertEquals(1200, pricing.list)\n                        assertEquals(1100, pricing.retail)\n                        assertEquals(100, pricing.savings)\n                        assertEquals(8, pricing.pctSavings)\n                    }\n                }\n            }\n\n            on(\"getting four columns by id\") {\n                db.withSession {\n                    val (sku, title, description, pricing) = Albums.find{ id.equal(albumId!!) }.projection { sku + title + description + pricing }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(1200, pricing.list)\n                        assertEquals(1100, pricing.retail)\n                        assertEquals(100, pricing.savings)\n                        assertEquals(8, pricing.pctSavings)\n                    }\n                }\n            }\n\n            on(\"getting five columns by id\") {\n                db.withSession {\n                    val (sku, title, description, asin, pricing) = Albums.find{ id.equal(albumId!!) }.projection { sku + title + description + asin + pricing }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(\"B0000A118M\", asin)\n                        assertEquals(1200, pricing.list)\n                        assertEquals(1100, pricing.retail)\n                        assertEquals(100, pricing.savings)\n                        assertEquals(8, pricing.pctSavings)\n                    }\n                }\n            }\n\n            on(\"getting six columns by id\") {\n                db.withSession {\n                    val (sku, title, description, asin, list, retail) = Albums.find { id.equal(albumId!!) }. projection { sku + title + description + asin + pricing.list + pricing.retail }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(\"B0000A118M\", asin)\n                        assertEquals(1200, list)\n                        assertEquals(1100, retail)\n                    }\n                }\n            }\n\n            on(\"getting seven columns by id\") {\n                db.withSession {\n                    val (sku, title, description, asin, list, retail, savings) = Albums.find { id.equal(albumId!!) }.projection { sku + title + description + asin + pricing.list + pricing.retail + pricing.savings}.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(\"B0000A118M\", asin)\n                        assertEquals(1200, list)\n                        assertEquals(1100, retail)\n                        assertEquals(100, savings)\n                    }\n                }\n            }\n\n            on(\"getting eight columns by id\") {\n                db.withSession {\n                    val (sku, title, description, asin, list, retail, savings, pctSavings) = Albums.find { id.equal(albumId!!) }.projection { sku + title + description + asin + pricing.list + pricing.retail + pricing.savings + pricing.pctSavings }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(\"B0000A118M\", asin)\n                        assertEquals(1200, list)\n                        assertEquals(1100, retail)\n                        assertEquals(100, savings)\n                        assertEquals(8, pctSavings)\n                    }\n                }\n            }\n\n            on(\"getting nine columns by id\") {\n                db.withSession {\n                    val (sku, title, description, asin, list, retail, savings, pctSavings, shipping) = Albums.find { id.equal(albumId!!) }.projection { sku + title + description + asin + pricing.list + pricing.retail + pricing.savings + pricing.pctSavings + shipping }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(\"B0000A118M\", asin)\n                        assertEquals(1200, list)\n                        assertEquals(1100, retail)\n                        assertEquals(100, savings)\n                        assertEquals(8, pctSavings)\n                        assertEquals(6, shipping.weight)\n                        assertEquals(10, shipping.dimensions.width)\n                        assertEquals(10, shipping.dimensions.height)\n                        assertEquals(1, shipping.dimensions.depth)\n                    }\n                }\n            }\n\n            on(\"getting ten columns by id\") {\n                db.withSession {\n                    val a = with (Albums) { sku + title + description + asin + pricing.list + pricing.retail + pricing.savings + pricing.pctSavings + shipping.weight + shipping.dimensions }\n                    val (sku, title, description, asin, list, retail, savings, pctSavings, weight, dimensions) = Albums.find { id.equal(albumId!!) }.projection { a }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(\"B0000A118M\", asin)\n                        assertEquals(1200, list)\n                        assertEquals(1100, retail)\n                        assertEquals(100, savings)\n                        assertEquals(8, pctSavings)\n                        assertEquals(6, weight)\n                        assertEquals(10, dimensions.width)\n                        assertEquals(10, dimensions.height)\n                        assertEquals(1, dimensions.depth)\n                    }\n                }\n            }\n\n            on(\"getting one id-column by another id\") {\n                db.withSession {\n                    val aId = Albums.find { id.equal(albumId!!) }.projection { details.artistId }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(artistId, aId)\n                    }\n                }\n            }\n\n            on(\"getting one column by filter expression\") {\n                db.withSession {\n                    val title = Albums.find { sku.equal(\"00e8da9b\") }.projection { details.title }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"A Love Supreme [Original Recording Reissued]\", title)\n                    }\n                }\n            }\n\n            on(\"getting two columns by a filter expression\") {\n                db.withSession {\n                    val (title, pricing) = Albums.find { sku.equal(\"00e8da9b\") }.projection { details.title + pricing }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"A Love Supreme [Original Recording Reissued]\", title)\n                        assertEquals(1200, pricing.list)\n                        assertEquals(1100, pricing.retail)\n                        assertEquals(100, pricing.savings)\n                        assertEquals(8, pricing.pctSavings)\n                    }\n                }\n            }\n\n            on(\"getting three columns by a filter expression\") {\n                db.withSession {\n                    val (sku, title, pricing) = Albums.find { sku.equal(\"00e8da9b\") }.projection { sku + details.title + pricing }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme [Original Recording Reissued]\", title)\n                        assertEquals(1200, pricing.list)\n                        assertEquals(1100, pricing.retail)\n                        assertEquals(100, pricing.savings)\n                        assertEquals(8, pricing.pctSavings)\n                    }\n                }\n            }\n\n            on(\"getting four columns by a filter expression\") {\n                db.withSession {\n                    val (sku, title, description, pricing) = Products.find { sku.equal(\"00e8da9b\") }.projection { sku + title + description + pricing }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(1200, pricing.list)\n                        assertEquals(1100, pricing.retail)\n                        assertEquals(100, pricing.savings)\n                        assertEquals(8, pricing.pctSavings)\n                    }\n                }\n            }\n\n            on(\"getting five columns by a filter expression\") {\n                db.withSession {\n                    val (sku, title, description, asin, pricing) = Products.find { sku.equal(\"00e8da9b\") }.projection { sku + title + description + asin + pricing }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(\"B0000A118M\", asin)\n                        assertEquals(1200, pricing.list)\n                        assertEquals(1100, pricing.retail)\n                        assertEquals(100, pricing.savings)\n                        assertEquals(8, pricing.pctSavings)\n                    }\n                }\n            }\n\n            on(\"getting six columns by a filter expression\") {\n                db.withSession {\n                    val (sku, title, description, asin, list, retail) = Products.find { sku.equal(\"00e8da9b\") }.projection { sku + title + description + asin + pricing.list + pricing.retail }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(\"B0000A118M\", asin)\n                        assertEquals(1200, list)\n                        assertEquals(1100, retail)\n                    }\n                }\n            }\n\n            on(\"getting seven columns by a filter expression\") {\n                db.withSession {\n                    val (sku, title, description, asin, list, retail, savings) = Products.find { sku.equal(\"00e8da9b\") }.projection { sku + title + description + asin + pricing.list + pricing.retail + pricing.savings }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(\"B0000A118M\", asin)\n                        assertEquals(1200, list)\n                        assertEquals(1100, retail)\n                        assertEquals(100, savings)\n                    }\n                }\n            }\n\n            on(\"getting eight columns by a filter expression\") {\n                db.withSession {\n                    val (sku, title, description, asin, list, retail, savings, pctSavings) = Products.find { sku.equal(\"00e8da9b\") }.projection { sku + title + description + asin + pricing.list + pricing.retail + pricing.savings + pricing.pctSavings }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(\"B0000A118M\", asin)\n                        assertEquals(1200, list)\n                        assertEquals(1100, retail)\n                        assertEquals(100, savings)\n                        assertEquals(8, pctSavings)\n                    }\n                }\n            }\n\n            on(\"getting nine columns by a filter expression\") {\n                db.withSession {\n                    val (sku, title, description, asin, list, retail, savings, pctSavings, shipping) = Products.find { sku.equal(\"00e8da9b\") }.projection { sku + title + description + asin + pricing.list + pricing.retail + pricing.savings + pricing.pctSavings + shipping}.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(\"B0000A118M\", asin)\n                        assertEquals(1200, list)\n                        assertEquals(1100, retail)\n                        assertEquals(100, savings)\n                        assertEquals(8, pctSavings)\n                        assertEquals(6, shipping.weight)\n                        assertEquals(10, shipping.dimensions.width)\n                        assertEquals(10, shipping.dimensions.height)\n                        assertEquals(1, shipping.dimensions.depth)\n                    }\n                }\n            }\n\n            on(\"getting ten columns by a filter expression\") {\n                db.withSession {\n                    val (sku, title, description, asin, list, retail, savings, pctSavings, weight, dimensions) = Products.find { sku.equal(\"00e8da9b\") }.projection { sku + title + description + asin + pricing.list + pricing.retail + pricing.savings + pricing.pctSavings + shipping.weight + shipping.dimensions }.single()\n                    it(\"returns correct values\") {\n                        assertEquals(\"00e8da9b\", sku)\n                        assertEquals(\"A Love Supreme\", title)\n                        assertEquals(\"by John Coltrane\", description)\n                        assertEquals(\"B0000A118M\", asin)\n                        assertEquals(1200, list)\n                        assertEquals(1100, retail)\n                        assertEquals(100, savings)\n                        assertEquals(8, pctSavings)\n                        assertEquals(6, weight)\n                        assertEquals(10, dimensions.width)\n                        assertEquals(10, dimensions.height)\n                        assertEquals(1, dimensions.depth)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by search expression\") {\n                db.withSession {\n                    val results = Products.find { text(\"Love\") }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by search expression\") {\n                db.withSession {\n                    val results = Products.find { text(\"Love\") and shipping.weight.equal(16) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by search expression (returns nothing)\") {\n                db.withSession {\n                    val results = Products.find { text(\"Love1\") }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by equal expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.equal(6) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by equal expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.equal(7) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by notEqual expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.notEqual(7) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by notEqual expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.notEqual(6) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by gt expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.gt(5) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by gt expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.gt(6) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by lt expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.lt(7) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by lt expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.lt(6) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by ge expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.ge(6) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by ge expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.ge(5) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by ge expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.ge(7) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by le expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.le(6) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by le expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.le(7) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by le expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.le(5) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by mb expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.memberOf( arrayOf(5, 6)) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by mb expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.memberOf( arrayOf(5, 7)) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by nm expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.notMemberOf( arrayOf(5, 7)) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by nm expression\") {\n                db.withSession {\n                    val results = Products.find { shipping.weight.notMemberOf( arrayOf(5, 6)) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by equal expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { with (shipping.dimensions) { width.equal(height) } }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by equal expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { with (shipping.dimensions) { width.equal(depth) } }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by equal expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { with (shipping.dimensions) { width.notEqual(depth) } }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by equal expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { with (shipping.dimensions) { width.notEqual(height) } }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            //\n\n            on(\"filtering an abstract schema by gt expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { shipping.dimensions.width.gt(shipping.dimensions.depth) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by gt expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { shipping.dimensions.depth.gt(shipping.dimensions.width) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by lt expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { shipping.dimensions.depth.lt(shipping.dimensions.width) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by lt expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { shipping.dimensions.width.lt(shipping.dimensions.depth) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by ge expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { shipping.dimensions.width.ge(shipping.dimensions.height) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by ge expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { shipping.dimensions.width.ge(shipping.dimensions.depth) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by ge expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { shipping.dimensions.depth.ge(shipping.dimensions.width) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by le expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { shipping.dimensions.depth.le(shipping.dimensions.width) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by le expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { shipping.dimensions.width.le(shipping.dimensions.height) }.toList()\n                    it(\"should return a correct object\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"filtering an abstract schema by le expression - compare to a column\") {\n                db.withSession {\n                    val results = Products.find { shipping.dimensions.width.le(shipping.dimensions.depth) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"getting one column by regex filter expression\") {\n                db.withSession {\n                    val results = Albums.find { details.title.matches(Pattern.compile(\"Love Supreme\")) }.toList()\n                    it(\"returns correct values\") {\n                        validate(results)\n                    }\n                }\n            }\n\n            on(\"getting one column by regex filter expression\") {\n                db.withSession {\n                    val results = Albums.find { details.title.matches(Pattern.compile(\"Love Supremex\")) }.toList()\n                    it(\"should return nothing\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n\n            on(\"setting a new value to a string column on a non-abstract schema by id\") {\n                db.withSession {\n                    Albums.find { id.equal(albumId!!) }.projection { details.title }.update(\"A Love Supreme. Original Recording Reissued\")\n                    val title = Albums.find { id.equal(albumId!!) }.projection { details.title }.single()\n                    it(\"takes effect\") {\n                        assertEquals(\"A Love Supreme. Original Recording Reissued\", title)\n                    }\n                }\n            }\n\n            on(\"setting a new value for a string column on a non-abstract schema by id\") {\n                db.withSession {\n                    Albums.find { id.equal(albumId!!) }.projection { details.title }.update(\"A Love Supreme. Original Recording Reissued\")\n                    val title = Albums.find { id.equal(albumId!!) }.projection { details.title }.single()\n                    it(\"takes effect\") {\n                        assertEquals(\"A Love Supreme. Original Recording Reissued\", title)\n                    }\n                }\n            }\n\n            on(\"setting values for two integer columns on an abstract schema by a filter expression\") {\n                db.withSession {\n                    Products.find { sku.equal(\"00e8da9b\") }.projection { pricing.retail + pricing.savings }.update(1150, 50)\n                    val (retail, savings) = Albums.find { id.equal(albumId!!) }.projection { pricing.retail + pricing.savings }.single()\n                    it(\"takes effect\") {\n                        assertEquals(1150, retail)\n                        assertEquals(50, savings)\n                    }\n                }\n            }\n\n            on(\"setting values for three columns on an abstract schema by a filter expression\") {\n                db.withSession {\n                    Products.find { sku.equal(\"00e8da9b\") }.projection { pricing.retail + pricing.savings + pricing.list }.update(1150, 50, 1250)\n                    val (retail, savings, list) = Albums.find { id.equal(albumId!!) }.projection { pricing.retail + pricing.savings + pricing.list }.single()\n                    it(\"takes effect\") {\n                        assertEquals(1150, retail)\n                        assertEquals(50, savings)\n                        assertEquals(1250, list)\n                    }\n                }\n            }\n\n            on(\"setting values for four columns on an abstract schema by a filter expression\") {\n                db.withSession {\n                    Products.find { sku.equal(\"00e8da9b\") }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width }.update(1150, 50, 1250, 11)\n                    val (retail, savings, list, width) = Albums.find { id.equal(albumId!!) }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width }.single()\n                    it(\"takes effect\") {\n                        assertEquals(1150, retail)\n                        assertEquals(50, savings)\n                        assertEquals(1250, list)\n                        assertEquals(11, width)\n                    }\n                }\n            }\n\n            on(\"setting values for five columns on an abstract schema by a filter expression\") {\n                db.withSession {\n                    Products.find { sku.equal(\"00e8da9b\") }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width + shipping.dimensions.height }.update(1150, 50, 1250, 11, 13)\n                    val (retail, savings, list, width, height) = Albums.find { id.equal(albumId!!) }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width + shipping.dimensions.height }.single()\n                    it(\"takes effect\") {\n                        assertEquals(1150, retail)\n                        assertEquals(50, savings)\n                        assertEquals(1250, list)\n                        assertEquals(11, width)\n                        assertEquals(13, height)\n                    }\n                }\n            }\n\n            on(\"setting values for six columns on an abstract schema by a filter expression\") {\n                db.withSession {\n                    Products.find { sku.equal(\"00e8da9b\") }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width + shipping.dimensions.height + shipping.dimensions.depth }.update(1150, 50, 1250, 11, 13, 2)\n                    val (retail, savings, list, width, height, depth) = Albums.find { id.equal(albumId!!) }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width + shipping.dimensions.height + shipping.dimensions.depth }.single()\n                    it(\"takes effect\") {\n                        assertEquals(1150, retail)\n                        assertEquals(50, savings)\n                        assertEquals(1250, list)\n                        assertEquals(11, width)\n                        assertEquals(13, height)\n                        assertEquals(2, depth)\n                    }\n                }\n            }\n\n            on(\"setting values for seven columns on an abstract schema by a filter expression\") {\n                db.withSession {\n                    Products.find { sku.equal(\"00e8da9b\") }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width + shipping.dimensions.height + shipping.dimensions.depth + shipping.weight }.update(1150, 50, 1250, 11, 13, 2, 7)\n                    val (retail, savings, list, width, height, depth, weight) = Albums.find { id.equal(albumId!!) }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width + shipping.dimensions.height + shipping.dimensions.depth + shipping.weight }.single()\n                    it(\"takes effect\") {\n                        assertEquals(1150, retail)\n                        assertEquals(50, savings)\n                        assertEquals(1250, list)\n                        assertEquals(11, width)\n                        assertEquals(13, height)\n                        assertEquals(2, depth)\n                        assertEquals(7, weight)\n                    }\n                }\n            }\n\n            on(\"setting values for eight columns on an abstract schema by a filter expression\") {\n                db.withSession {\n                    Products.find { sku.equal(\"00e8da9b\") }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width + shipping.dimensions.height + shipping.dimensions.depth + shipping.weight + cost }.update(1150, 50, 1250, 11, 13, 2, 7, 1.25)\n                    val (retail, savings, list, width, height, depth, weight, cost) = Albums.find { id.equal(albumId!!) }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width + shipping.dimensions.height + shipping.dimensions.depth + shipping.weight + cost }.single()\n                    it(\"takes effect\") {\n                        assertEquals(1150, retail)\n                        assertEquals(50, savings)\n                        assertEquals(1250, list)\n                        assertEquals(11, width)\n                        assertEquals(13, height)\n                        assertEquals(2, depth)\n                        assertEquals(7, weight)\n                        assertEquals(1.25, cost)\n                    }\n                }\n            }\n\n            on(\"setting values for nine columns on an abstract schema by a filter expression\") {\n                db.withSession {\n                    Products.find { sku.equal(\"00e8da9b\") }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width + shipping.dimensions.height + shipping.dimensions.depth + shipping.weight + cost + available }.update(1150, 50, 1250, 11, 13, 2, 7, 1.25, false)\n                    val (retail, savings, list, width, height, depth, weight, cost, available) = Albums.find { id.equal(albumId!!) }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width + shipping.dimensions.height + shipping.dimensions.depth + shipping.weight + cost + available }.single()\n                    it(\"takes effect\") {\n                        assertEquals(1150, retail)\n                        assertEquals(50, savings)\n                        assertEquals(1250, list)\n                        assertEquals(11, width)\n                        assertEquals(13, height)\n                        assertEquals(2, depth)\n                        assertEquals(7, weight)\n                        assertEquals(1.25, cost)\n                        assertEquals(false, available)\n                    }\n                }\n            }\n\n            on(\"setting values for ten columns on an abstract schema by a filter expression\") {\n                db.withSession {\n                    Products.find { sku.equal(\"00e8da9b\") }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width + shipping.dimensions.height + shipping.dimensions.depth + shipping.weight + cost + available + nullableDoubleWithValue }.update(1150, 50, 1250, 11, 13, 2, 7, 1.25, false, 10.1)\n                    val (retail, savings, list, width, height, depth, weight, cost, available, nullableDoubleWithValue) = Albums.find { id.equal(albumId!!) }.projection { pricing.retail + pricing.savings + pricing.list + shipping.dimensions.width + shipping.dimensions.height + shipping.dimensions.depth + shipping.weight + cost + available + nullableDoubleWithValue }.single()\n                    it(\"takes effect\") {\n                        assertEquals(1150, retail)\n                        assertEquals(50, savings)\n                        assertEquals(1250, list)\n                        assertEquals(11, width)\n                        assertEquals(13, height)\n                        assertEquals(2, depth)\n                        assertEquals(7, weight)\n                        assertEquals(1.25, cost)\n                        assertEquals(false, available)\n                        assertEquals(10.1, nullableDoubleWithValue)\n                    }\n                }\n            }\n\n            on(\"setting a new value to a date column on a non-abstract schema by id\") {\n                db.withSession {\n                    Albums.find { id.equal(albumId!!) }.projection { nullableDateNoValue }.update(LocalDate(2014, 3, 20))\n                    // TODO: single is nullable here\n                    val nullableDateNoValue = Albums.find { id.equal(albumId!!) }.projection { nullableDateNoValue }.single()\n                    it(\"takes effect\") {\n                        assertEquals(LocalDate(2014, 3, 20), nullableDateNoValue!!)\n                    }\n                }\n            }\n\n            on(\"adding a new element to a list column on a non-abstract schema by id\") {\n                db.withSession {\n                    Albums.find { id.equal(albumId!!) }.projection { details.tracks }.add(Track(\"A Love Supreme, Part IV-Psalm\", 400))\n                    val tracks = Albums.find { id.equal(albumId!!) }.projection { Albums.details.tracks }.single()!!\n                    it(\"takes effect\") {\n                        assertEquals(4, tracks.size)\n                        assertEquals(\"A Love Supreme, Part IV-Psalm\", tracks[3].title)\n                        assertEquals(400, tracks[3].duration)\n                    }\n                }\n            }\n\n            on(\"adding a new id to an id set column on a non-abstract schema by id\") {\n                db.withSession {\n                    Albums.find { id.equal(albumId!!) }.projection { details.artistIds }.add(artistId3)\n                    val artistIds = Albums.find { id.equal(albumId!!) }.projection { details.artistIds }.single()\n                    it(\"takes effect\") {\n                        assertEquals(3, artistIds.size)\n                        assertTrue(artistIds.contains(artistId3))\n                    }\n                }\n            }\n\n            on(\"removing sn element from a collection column on a non-abstract schema by id\") {\n                db.withSession {\n                    Albums.find { id.equal(albumId!!) }.projection { details.tracks }.remove { duration.equal(100) }\n                    val tracks = Albums.find { id.equal(albumId!!) }.projection { details.tracks }.single()\n                    it(\"takes effect\") {\n                        assertEquals(3, tracks.size)\n                    }\n                }\n            }\n\n            on(\"removing an element from a collection column on a non-abstract schema by a filter expression\") {\n                db.withSession {\n                    Albums.find { sku.equal(\"00e8da9b\") }.projection { details.tracks }.remove { duration.equal(200) }\n                    val tracks = Albums.find { id.equal(albumId!!) }.projection { Albums.details.tracks }.single()\n                    it(\"takes effect\") {\n                        assertEquals(2, tracks.size)\n                    }\n                }\n            }\n\n            on(\"removing an element from a set column on a non-abstract schema by id\") {\n                db.withSession {\n                    Albums.find { id.equal(albumId!!) }.projection { details.genre }.remove(\"General\")\n                    val genre = Albums.find { id.equal(albumId!!) }.projection { Albums.details.genre }.single()\n                    it(\"takes effect\") {\n                        assertEquals(1, genre.size)\n                    }\n                }\n            }\n\n            on(\"deleting a document\") {\n                db.withSession {\n                    Albums.find { id.equal(albumId!!) }.remove()\n                    val results =  Albums.find { id.equal(albumId!!) }.toList()\n                    it(\"deletes the document from database\") {\n                        assert(results.isEmpty())\n                    }\n                }\n            }\n        }\n    }\n}\n\nfun main(args: Array<String>) {\n    MongoDBSpek()\n}"
  },
  {
    "path": "kotlin-nosql.iml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module external.linked.project.id=\"kotlin-nosql\" external.linked.project.path=\"$MODULE_DIR$\" external.root.project.path=\"$MODULE_DIR$\" external.system.id=\"GRADLE\" external.system.module.group=\"org.jetbrains.kotlin\" external.system.module.version=\"0.1-SNAPSHOT\" type=\"JAVA_MODULE\" version=\"4\">\n  <component name=\"NewModuleRootManager\" inherit-compiler-output=\"false\">\n    <output url=\"file://$MODULE_DIR$/build/classes/main\" />\n    <output-test url=\"file://$MODULE_DIR$/build/classes/test\" />\n    <exclude-output />\n    <content url=\"file://$MODULE_DIR$\">\n      <sourceFolder url=\"file://$MODULE_DIR$/src/main/java\" isTestSource=\"false\" />\n      <sourceFolder url=\"file://$MODULE_DIR$/src/main/kotlin\" isTestSource=\"false\" />\n      <sourceFolder url=\"file://$MODULE_DIR$/src/test/java\" isTestSource=\"true\" />\n      <sourceFolder url=\"file://$MODULE_DIR$/src/test/kotlin\" isTestSource=\"true\" />\n      <sourceFolder url=\"file://$MODULE_DIR$/src/main/resources\" type=\"java-resource\" />\n      <sourceFolder url=\"file://$MODULE_DIR$/src/test/resources\" type=\"java-test-resource\" />\n      <excludeFolder url=\"file://$MODULE_DIR$/.gradle\" />\n      <excludeFolder url=\"file://$MODULE_DIR$/build\" />\n    </content>\n    <orderEntry type=\"inheritedJdk\" />\n    <orderEntry type=\"sourceFolder\" forTests=\"false\" />\n    <orderEntry type=\"library\" exported=\"\" name=\"Gradle: joda-time:joda-time:2.3\" level=\"project\" />\n    <orderEntry type=\"library\" scope=\"TEST\" name=\"Gradle: junit:junit:4.11\" level=\"project\" />\n    <orderEntry type=\"library\" scope=\"TEST\" name=\"Gradle: org.hamcrest:hamcrest-core:1.3\" level=\"project\" />\n    <orderEntry type=\"library\" exported=\"\" name=\"Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.0.0\" level=\"project\" />\n    <orderEntry type=\"library\" exported=\"\" name=\"Gradle: org.jetbrains.kotlin:kotlin-runtime:1.0.0\" level=\"project\" />\n    <orderEntry type=\"library\" scope=\"TEST\" name=\"Gradle: org.jetbrains.spek:spek:0.1.195\" level=\"project\" />\n    <orderEntry type=\"library\" scope=\"TEST\" name=\"Gradle: org.jetbrains.kotlin:kotlin-reflect:1.0.0\" level=\"project\" />\n    <orderEntry type=\"library\" scope=\"TEST\" name=\"Gradle: org.jetbrains.kotlin:kotlin-test:1.0.0\" level=\"project\" />\n  </component>\n</module>"
  },
  {
    "path": "settings.gradle",
    "content": "include 'kotlin-nosql-mongodb'\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/AbstractColumn.kt",
    "content": "package kotlinx.nosql\n\nimport java.util.ArrayList\nimport java.util.regex.Pattern\nimport kotlinx.nosql.query.*\nimport kotlin.collections.listOf\nimport kotlin.collections.setOf\nimport kotlin.reflect.KClass\n\nopen class AbstractColumn<C, T : AbstractSchema, S: Any>(val name: String, val valueClass: KClass<S>, val columnType: ColumnType) : ColumnQueryWrapper<C>(), Expression<C> {\n    internal var _schema: AbstractSchema? = null\n\n    val schema: T\n        get() {\n            return _schema!! as T\n        }\n\n    fun matches(other: Pattern): Query {\n        return MatchesQuery(this, LiteralExpression(other))\n    }\n\n    override fun toString(): String {\n        return \"$name\"\n    }\n\n    operator fun <C2> plus(c: AbstractColumn<C2, T, *>): ColumnPair<T, C, C2> {\n        return ColumnPair(this, c) as ColumnPair<T, C, C2>\n    }\n}\n\n/*\nfun<C, T: AbstractSchema> AbstractColumn<C, T, *>.get(): C {\n    throw UnsupportedOperationException()\n}\n*/\n\nfun <C, T: AbstractSchema> AbstractColumn<C, T, *>.update(value: C): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    return Session.current<Session>().update(wrapper.params.table, arrayOf(wrapper.params.projection.get(0) to value),\n            wrapper.params.query!!)\n}\n\nfun <C, S: Collection<C>> AbstractColumn<S, *, *>.addAll(values: S): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    return Session.current<Session>().addAll(wrapper.params.table,\n            wrapper.params.projection.get(0)\n                    as AbstractColumn<Collection<C>, out AbstractSchema, out Any>, values,\n            wrapper.params.query!!)\n}\n\nfun <C, S: Collection<C>> AbstractColumn<S, *, *>.add(value: C): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    val values: Collection<C> = if (wrapper.params.projection.get(0).columnType.list) listOf(value) else setOf(value)\n    return Session.current<Session>().addAll(wrapper.params.table,\n                    wrapper.params.projection.get(0)\n                            as AbstractColumn<Collection<C>, out AbstractSchema, out Any>, values,\n                    wrapper.params.query!!)\n}\n\nfun <C, S: Collection<C>> AbstractColumn<S, *, *>.removeAll(values: S): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    return Session.current<Session>().removeAll(wrapper.params.table,\n            wrapper.params.projection.get(0)\n                    as AbstractColumn<Collection<C>, out AbstractSchema, out Any>, values,\n            wrapper.params.query!!)\n}\n\nfun <C> AbstractColumn<out Collection<C>, *, *>.remove(value: C): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    val values: Collection<C> = if (wrapper.params.projection.get(0).columnType.list) listOf(value) else setOf(value)\n    return Session.current<Session>().removeAll(wrapper.params.table,\n            wrapper.params.projection.get(0)\n                    as AbstractColumn<Collection<C>, out AbstractSchema, out Any>, values,\n            wrapper.params.query!!)\n}\n\nfun <C: AbstractColumn<out Collection<*>, *, *>> C.remove(removeOp: C.() -> Query): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n        val removeOpValue = with (wrapper.params.projection.get(0)) {\n            removeOp()\n        }\n    return Session.current<Session>().removeAll(wrapper.params.table,\n            wrapper.params.projection.get(0)\n                    as AbstractColumn<Collection<C>, out AbstractSchema, out Any>, removeOpValue,\n            wrapper.params.query!!)\n}\n\nfun <T : AbstractSchema, C: Any> AbstractColumn<C?, T, C>.isNull(): Query {\n    return IsNullQuery(this)\n}\n\nfun <T : AbstractSchema, C: Any> AbstractColumn<C?, T, C>.notNull(): Query {\n    return IsNotNullQuery(this)\n}\n\nfun <T : AbstractSchema, C> AbstractColumn<out C?, T, *>.equal(other: C): Query {\n    return EqualQuery(this, LiteralExpression(other))\n}\n\nfun <T : AbstractSchema, C> AbstractColumn<out C?, T, *>.notEqual(other: C): Query {\n    return NotEqualQuery(this, LiteralExpression(other))\n}\n\nfun <T : AbstractSchema, C> AbstractColumn<out C?, T, *>.memberOf(other: Iterable<C>): Query {\n    return MemberOfQuery(this, LiteralExpression(other))\n}\n\nfun <T : AbstractSchema, C> AbstractColumn<out C?, T, *>.memberOf(other: Array<C>): Query {\n    return MemberOfQuery(this, LiteralExpression(other))\n}\n\n// TODO TODO TODO: Expression should be typed\nfun <T : AbstractSchema, C> AbstractColumn<out C?, T, *>.memberOf(other: Expression<out Iterable<C>>): Query {\n    return MemberOfQuery(this, LiteralExpression(other))\n}\n\nfun <T : AbstractSchema, C> AbstractColumn<out C?, T, *>.notMemberOf(other: Iterable<C>): Query {\n    return NotMemberOfQuery(this, LiteralExpression(other))\n}\n\nfun <T : AbstractSchema, C> AbstractColumn<out C?, T, *>.notMemberOf(other: Array<C>): Query {\n    return NotMemberOfQuery(this, LiteralExpression(other))\n}\n\nfun <T : AbstractSchema, C> AbstractColumn<out C?, T, *>.notMemberOf(other: Expression<out Iterable<C>>): Query {\n    return NotMemberOfQuery(this, LiteralExpression(other))\n}\n\nfun <T : AbstractSchema, C: Any> AbstractColumn<out C?, T, C>.equal(other: Expression<out C?>): Query {\n    return EqualQuery(this, other)\n}\n\nfun <T : AbstractSchema, C: Any> AbstractColumn<out C?, T, C>.notEqual(other: Expression<out C?>): Query {\n    return NotEqualQuery(this, other)\n}\n\nfun <T : AbstractSchema> AbstractColumn<out Int?, T, Int>.gt(other: Expression<out Int?>): Query {\n    return GreaterQuery(this, other)\n}\n\nfun <T : AbstractSchema> AbstractColumn<out Int?, T, Int>.gt(other: Int): Query {\n    return GreaterQuery(this, LiteralExpression(other))\n}\n\nfun <T : AbstractSchema> AbstractColumn<out Int?, T, Int>.ge(other: Expression<out Int?>): Query {\n    return GreaterEqualQuery(this, other)\n}\n\nfun <T : AbstractSchema> AbstractColumn<out Int?, T, Int>.ge(other: Int): Query {\n    return GreaterEqualQuery(this, LiteralExpression(other))\n}\n\nfun <T : AbstractSchema> AbstractColumn<out Int?, T, Int>.le(other: Expression<out Int?>): Query {\n    return LessEqualQuery(this, other)\n}\n\nfun <T : AbstractSchema> AbstractColumn<out Int?, T, Int>.le(other: Int): Query {\n    return LessEqualQuery(this, LiteralExpression(other))\n}\n\nfun <T : AbstractSchema> AbstractColumn<out Int?, T, Int>.lt(other: Expression<out Int?>): Query {\n    return LessQuery(this, other)\n}\n\nfun <T : AbstractSchema> AbstractColumn<out Int?, T, Int>.lt(other: Int): Query {\n    return LessQuery(this, LiteralExpression(other))\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/AbstractIndex.kt",
    "content": "package kotlinx.nosql\n\nabstract class AbstractIndex(val name: String)"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/AbstractNullableColumn.kt",
    "content": "package kotlinx.nosql\n\ninterface AbstractNullableColumn {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/AbstractSchema.kt",
    "content": "package kotlinx.nosql\n\nimport java.util.ArrayList\nimport java.util.concurrent.ConcurrentHashMap\nimport java.util.concurrent.CopyOnWriteArrayList\nimport org.joda.time.LocalDate\nimport org.joda.time.LocalTime\nimport org.joda.time.DateTime\nimport kotlinx.nosql.query.TextQuery\n\nabstract class AbstractSchema(val schemaName: String) {\n    // TODO TODO TODO\n    val indices = ArrayList<AbstractIndex>()\n\n    // TODO TODO TODO\n    // val columns = ArrayList<AbstractColumn<*, *, *>>()\n\n    // TODO TODO TODO\n    companion object {\n        val threadLocale = ThreadLocal<AbstractSchema>()\n\n        fun <T: AbstractSchema> current(): T {\n            return threadLocale.get() as T\n        }\n\n        fun set(schema: AbstractSchema) {\n            return threadLocale.set(schema)\n        }\n    }\n}\n\n// TODO\nfun text(search: String): Query {\n    return TextQuery(search)\n}\n\n// Extension functions\n\nfun <S : AbstractSchema> string(name: String): AbstractColumn<String, S, String> = AbstractColumn(name, String::class, ColumnType.STRING)\nfun <S : AbstractSchema> S.string(name: String): AbstractColumn<String, S, String> = AbstractColumn(name, String::class, ColumnType.STRING)\n\nfun <S : AbstractSchema> boolean(name: String): AbstractColumn<Boolean, S, Boolean> = AbstractColumn(name, Boolean::class, ColumnType.BOOLEAN)\nfun <S : AbstractSchema> S.boolean(name: String): AbstractColumn<Boolean, S, Boolean> = AbstractColumn(name, Boolean::class, ColumnType.BOOLEAN)\n\nfun <S : AbstractSchema> date(name: String): AbstractColumn<LocalDate, S, LocalDate> = AbstractColumn(name, LocalDate::class, ColumnType.DATE)\nfun <S : AbstractSchema> S.date(name: String): AbstractColumn<LocalDate, S, LocalDate> = AbstractColumn(name, LocalDate::class, ColumnType.DATE)\n\nfun <S : AbstractSchema> time(name: String): AbstractColumn<LocalTime, S, LocalTime> = AbstractColumn(name, LocalTime::class, ColumnType.TIME)\nfun <S : AbstractSchema> S.time(name: String): AbstractColumn<LocalTime, S, LocalTime> = AbstractColumn(name, LocalTime::class, ColumnType.TIME)\n\nfun <S : AbstractSchema> dateTime(name: String): AbstractColumn<DateTime, S, DateTime> = AbstractColumn(name, DateTime::class, ColumnType.DATE_TIME)\nfun <S : AbstractSchema> S.dateTime(name: String): AbstractColumn<DateTime, S, DateTime> = AbstractColumn(name, DateTime::class, ColumnType.DATE_TIME)\n\nfun <S : AbstractSchema> double(name: String): AbstractColumn<Double, S, Double> = AbstractColumn(name, Double::class, ColumnType.DOUBLE)\nfun <S : AbstractSchema> S.double(name: String): AbstractColumn<Double, S, Double> = AbstractColumn(name, Double::class, ColumnType.DOUBLE)\n\nfun <S : AbstractSchema> integer(name: String): AbstractColumn<Int, S, Int> = AbstractColumn(name, Int::class, ColumnType.INTEGER)\nfun <S : AbstractSchema> S.integer(name: String): AbstractColumn<Int, S, Int> = AbstractColumn(name, Int::class, ColumnType.INTEGER)\n\nfun <S : AbstractSchema> float(name: String): AbstractColumn<Float, S, Float> = AbstractColumn(name, Float::class, ColumnType.FLOAT)\nfun <S : AbstractSchema> S.float(name: String): AbstractColumn<Float, S, Float> = AbstractColumn(name, Float::class, ColumnType.FLOAT)\n\nfun <S : AbstractSchema> long(name: String): AbstractColumn<Long, S, Long> = AbstractColumn(name, Long::class, ColumnType.LONG)\nfun <S : AbstractSchema> S.long(name: String): AbstractColumn<Long, S, Long> = AbstractColumn(name, Long::class, ColumnType.LONG)\n\nfun <S : AbstractSchema> short(name: String): AbstractColumn<Short, S, Short> = AbstractColumn(name, Short::class, ColumnType.SHORT)\nfun <S : AbstractSchema> S.short(name: String): AbstractColumn<Short, S, Short> = AbstractColumn(name, Short::class, ColumnType.SHORT)\n\nfun <S : AbstractSchema> byte(name: String): AbstractColumn<Byte, S, Byte> = AbstractColumn(name, Byte::class, ColumnType.BYTE)\nfun <S : AbstractSchema> S.byte(name: String): AbstractColumn<Byte, S, Byte> = AbstractColumn(name, Byte::class, ColumnType.BYTE)\n\nfun <S : AbstractSchema> nullableString(name: String): NullableColumn<String, S> = NullableColumn(name, String::class, ColumnType.STRING)\nfun <S : AbstractSchema> S.nullableString(name: String): NullableColumn<String, S> = NullableColumn(name, String::class, ColumnType.STRING)\n\nfun <S : AbstractSchema> nullableInteger(name: String): NullableColumn<Int, S> = NullableColumn(name, Int::class, ColumnType.INTEGER)\nfun <S : AbstractSchema> S.nullableInteger(name: String): NullableColumn<Int, S> = NullableColumn(name, Int::class, ColumnType.INTEGER)\n\nfun <S : AbstractSchema> nullableBoolean(name: String): NullableColumn<Boolean, S> = NullableColumn(name, Boolean::class, ColumnType.BOOLEAN)\nfun <S : AbstractSchema> S.nullableBoolean(name: String): NullableColumn<Boolean, S> = NullableColumn(name, Boolean::class, ColumnType.BOOLEAN)\n\nfun <S : AbstractSchema> nullableDate(name: String): NullableColumn<LocalDate, S> = NullableColumn(name, LocalDate::class, ColumnType.DATE)\nfun <S : AbstractSchema> S.nullableDate(name: String): NullableColumn<LocalDate, S> = NullableColumn(name, LocalDate::class, ColumnType.DATE)\n\nfun <S : AbstractSchema> nullableTime(name: String): NullableColumn<LocalTime, S> = NullableColumn(name, LocalTime::class, ColumnType.TIME)\nfun <S : AbstractSchema> S.nullableTime(name: String): NullableColumn<LocalTime, S> = NullableColumn(name, LocalTime::class, ColumnType.TIME)\n\nfun <S : AbstractSchema> nullableDateTime(name: String): NullableColumn<DateTime, S> = NullableColumn(name, DateTime::class, ColumnType.DATE_TIME)\nfun <S : AbstractSchema> S.nullableDateTime(name: String): NullableColumn<DateTime, S> = NullableColumn(name, DateTime::class, ColumnType.DATE_TIME)\n\nfun <S : AbstractSchema> nullableDouble(name: String): NullableColumn<Double, S> = NullableColumn(name, Double::class, ColumnType.DOUBLE)\nfun <S : AbstractSchema> S.nullableDouble(name: String): NullableColumn<Double, S> = NullableColumn(name, Double::class, ColumnType.DOUBLE)\n\nfun <S : AbstractSchema> nullableFloat(name: String): NullableColumn<Float, S> = NullableColumn(name, Float::class, ColumnType.FLOAT)\nfun <S : AbstractSchema> S.nullableFloat(name: String): NullableColumn<Float, S> = NullableColumn(name, Float::class, ColumnType.FLOAT)\n\nfun <S : AbstractSchema> nullableLong(name: String): NullableColumn<Long, S> = NullableColumn(name, Long::class, ColumnType.LONG)\nfun <S : AbstractSchema> S.nullableLong(name: String): NullableColumn<Long, S> = NullableColumn(name, Long::class, ColumnType.LONG)\n\nfun <S : AbstractSchema> nullableShort(name: String): NullableColumn<Short, S> = NullableColumn(name, Short::class, ColumnType.SHORT)\nfun <S : AbstractSchema> S.nullableShort(name: String): NullableColumn<Short, S> = NullableColumn(name, Short::class, ColumnType.SHORT)\n\nfun <S : AbstractSchema> nullableByte(name: String): NullableColumn<Byte, S> = NullableColumn(name, Byte::class, ColumnType.BYTE)\nfun <S : AbstractSchema> S.nullableByte(name: String): NullableColumn<Byte, S> = NullableColumn(name, Byte::class, ColumnType.BYTE)\n\nfun <S : AbstractSchema> setOfString(name: String): AbstractColumn<Set<String>, S, String> = AbstractColumn<Set<String>, S, String>(name, String::class, ColumnType.STRING_SET)\nfun <S : AbstractSchema> S.setOfString(name: String): AbstractColumn<Set<String>, S, String> = AbstractColumn<Set<String>, S, String>(name, String::class, ColumnType.STRING_SET)\n\nfun <S : AbstractSchema> setOfInteger(name: String): AbstractColumn<Set<Int>, S, Int> = AbstractColumn<Set<Int>, S, Int>(name, Int::class, ColumnType.INTEGER_SET)\nfun <S : AbstractSchema> S.setOfInteger(name: String): AbstractColumn<Set<Int>, S, Int> = AbstractColumn<Set<Int>, S, Int>(name, Int::class, ColumnType.INTEGER_SET)\n\nfun <S : AbstractSchema> listOfString(name: String): AbstractColumn<List<String>, S, String> = AbstractColumn<List<String>, S, String>(name, String::class, ColumnType.STRING_LIST)\nfun <S : AbstractSchema> S.listOfString(name: String): AbstractColumn<List<String>, S, String> = AbstractColumn<List<String>, S, String>(name, String::class, ColumnType.STRING_LIST)\n\nfun <S : AbstractSchema> listOfInteger(name: String): AbstractColumn<List<Int>, S, Int> = AbstractColumn<List<Int>, S, Int>(name, Int::class, ColumnType.INTEGER_LIST)\nfun <S : AbstractSchema> S.listOfInteger(name: String): AbstractColumn<List<Int>, S, Int> = AbstractColumn<List<Int>, S, Int>(name, Int::class, ColumnType.INTEGER_LIST)\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/AbstractTableSchema.kt",
    "content": "package kotlinx.nosql\n\nabstract class AbstractTableSchema(name: String): AbstractSchema(name) {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/AndQuery.kt",
    "content": "package kotlinx.nosql\n\nclass AndQuery(val expr1: kotlinx.nosql.Query, val expr2: kotlinx.nosql.Query): Query() {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Column.kt",
    "content": "package kotlinx.nosql\n\nimport kotlin.reflect.KClass\n\nabstract class Column<C: Any, S : AbstractSchema>(name: String, valueClass: KClass<C>, columnType: ColumnType = ColumnType.CUSTOM_CLASS) : AbstractColumn<C, S, C>(name, valueClass, columnType) {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/ColumnDecuple.kt",
    "content": "package kotlinx.nosql\n\nclass ColumnDecuple<S : AbstractSchema, A, B, C, D, E, F, G, H, J, K>(val a: AbstractColumn<A, S, *>, val b: AbstractColumn<B, S, *>,\n                                                                   val c: AbstractColumn<C, S, *>, val d: AbstractColumn<D, S, *>,\n                                                                   val e: AbstractColumn<E, S, *>, val f: AbstractColumn<F, S, *>,\n                                                                   val g: AbstractColumn<G, S, *>, val h: AbstractColumn<H, S, *>,\n                                                                   val i: AbstractColumn<J, S, *>, val j: AbstractColumn<K, S, *>): ColumnQueryWrapper<Decuple<A, B, C, D, E, F, G, H, J, K>>() {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/ColumnNonuple.kt",
    "content": "package kotlinx.nosql\n\nclass ColumnNonuple<S : AbstractSchema, A, B, C, D, E, F, G, H, J>(val a: AbstractColumn<A, S, *>, val b: AbstractColumn<B, S, *>,\n                                                               val c: AbstractColumn<C, S, *>, val d: AbstractColumn<D, S, *>,\n                                                               val e: AbstractColumn<E, S, *>, val f: AbstractColumn<F, S, *>,\n                                                               val g: AbstractColumn<G, S, *>, val h: AbstractColumn<H, S, *>,\n                                                               val j: AbstractColumn<J, S, *>): ColumnQueryWrapper<Nonuple<A, B, C, D, E, F, G, H, J>>() {\n    operator fun <K> plus(k: AbstractColumn<K, S, *>): ColumnDecuple<S, A, B, C, D, E, F, G, H, J, K> {\n        return ColumnDecuple(a, b, c, d, e, f, g, h, j, k)\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/ColumnOctuple.kt",
    "content": "package kotlinx.nosql\n\nclass ColumnOctuple<S : AbstractSchema, A, B, C, D, E, F, G, H>(val a: AbstractColumn<A, S, *>, val b: AbstractColumn<B, S, *>,\n                                                            val c: AbstractColumn<C, S, *>, val d: AbstractColumn<D, S, *>,\n                                                            val e: AbstractColumn<E, S, *>, val f: AbstractColumn<F, S, *>,\n                                                            val g: AbstractColumn<G, S, *>, val h: AbstractColumn<H, S, *>): ColumnQueryWrapper<Octuple<A, B, C, D, E, F, G, H>>() {\n    operator fun <J> plus(j: AbstractColumn<J, S, *>): ColumnNonuple<S, A, B, C, D, E, F, G, H, J> {\n        return ColumnNonuple(a, b, c, d, e, f, g, h, j)\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/ColumnPair.kt",
    "content": "package kotlinx.nosql\n\nclass ColumnPair<S : AbstractSchema, A, B>(val a: AbstractColumn<A, S, *>, val b: AbstractColumn<B, S, *>): ColumnQueryWrapper<Pair<A, B>>() {\n    operator fun <C> plus(c: AbstractColumn<C, S, *>): ColumnTriple<S, A, B, C> {\n        return ColumnTriple(a, b, c)\n    }\n}\n\n/*\nfun <S : KeyValueSchema, A, B> ColumnPair<S, A, B>.get(): Pair<A, B> {\n    throw UnsupportedOperationException()\n}*/\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/ColumnQuadruple.kt",
    "content": "package kotlinx.nosql\n\nclass ColumnQuadruple<S : AbstractSchema, A, B, C, D>(val a: AbstractColumn<A, S, *>, val b: AbstractColumn<B, S, *>, val c: AbstractColumn<C, S, *>, val d: AbstractColumn<D, S, *>): ColumnQueryWrapper<Quadruple<A, B, C, D>>() {\n    operator fun <E> plus(e: AbstractColumn<E, S, *>): ColumnQuintuple<S, A, B, C, D, E> {\n        return ColumnQuintuple(a, b, c, d, e)\n    }\n\n    fun insert(statement: () -> Quadruple<A, B, C, D>) {\n        val tt = statement()\n        Session.current<Session>().insert(arrayOf(Pair(a, tt.component1()), Pair(b, tt.component2()), Pair(c, tt.component3()), Pair(d, tt.component4())))\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/ColumnQueryWrapper.kt",
    "content": "package kotlinx.nosql\n\nabstract class ColumnQueryWrapper<C> : Iterable<C> {\n    override fun iterator(): Iterator<C> {\n        val wrapper = TableSchemaProjectionQueryWrapper.get()\n        return wrapper.iterator() as Iterator<C>\n    }\n}\n\nfun <A, B> ColumnQueryWrapper<Pair<A, B>>.update(a: A, b: B): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    return Session.current<Session>().update(wrapper.params.table, arrayOf(wrapper.params.projection.get(0) to a,\n            wrapper.params.projection.get(1) to b),\n            wrapper.params.query!!)\n}\n\nfun <A, B, C> ColumnQueryWrapper<Triple<A, B, C>>.update(a: A, b: B, c: C): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    return Session.current<Session>().update(wrapper.params.table, arrayOf(wrapper.params.projection.get(0) to a,\n            wrapper.params.projection.get(1) to b,\n            wrapper.params.projection.get(2) to c),\n            wrapper.params.query!!)\n}\n\nfun <A, B, C, D> ColumnQueryWrapper<Quadruple<A, B, C, D>>.update(a: A, b: B, c: C, d: D): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    return Session.current<Session>().update(wrapper.params.table, arrayOf(wrapper.params.projection.get(0) to a,\n            wrapper.params.projection.get(1) to b,\n            wrapper.params.projection.get(2) to c,\n            wrapper.params.projection.get(3) to d),\n            wrapper.params.query!!)\n}\n\nfun <A, B, C, D, E> ColumnQueryWrapper<Quintuple<A, B, C, D, E>>.update(a: A, b: B, c: C, d: D, e: E): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    return Session.current<Session>().update(wrapper.params.table, arrayOf(wrapper.params.projection.get(0) to a,\n            wrapper.params.projection.get(1) to b,\n            wrapper.params.projection.get(2) to c,\n            wrapper.params.projection.get(3) to d,\n            wrapper.params.projection.get(4) to e),\n            wrapper.params.query!!)\n}\n\nfun <A, B, C, D, E, F> ColumnQueryWrapper<Sextuple<A, B, C, D, E, F>>.update(a: A, b: B, c: C, d: D, e: E, f: F): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    return Session.current<Session>().update(wrapper.params.table, arrayOf(wrapper.params.projection.get(0) to a,\n            wrapper.params.projection.get(1) to b,\n            wrapper.params.projection.get(2) to c,\n            wrapper.params.projection.get(3) to d,\n            wrapper.params.projection.get(4) to e,\n            wrapper.params.projection.get(5) to f),\n            wrapper.params.query!!)\n}\n\nfun <A, B, C, D, E, F, G> ColumnQueryWrapper<Septuple<A, B, C, D, E, F, G>>.update(a: A, b: B, c: C, d: D, e: E, f: F, g: G): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    return Session.current<Session>().update(wrapper.params.table, arrayOf(wrapper.params.projection.get(0) to a,\n            wrapper.params.projection.get(1) to b,\n            wrapper.params.projection.get(2) to c,\n            wrapper.params.projection.get(3) to d,\n            wrapper.params.projection.get(4) to e,\n            wrapper.params.projection.get(5) to f,\n            wrapper.params.projection.get(6) to g),\n            wrapper.params.query!!)\n}\n\nfun <A, B, C, D, E, F, G, H> ColumnQueryWrapper<Octuple<A, B, C, D, E, F, G, H>>.update(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    return Session.current<Session>().update(wrapper.params.table, arrayOf(wrapper.params.projection.get(0) to a,\n            wrapper.params.projection.get(1) to b,\n            wrapper.params.projection.get(2) to c,\n            wrapper.params.projection.get(3) to d,\n            wrapper.params.projection.get(4) to e,\n            wrapper.params.projection.get(5) to f,\n            wrapper.params.projection.get(6) to g,\n            wrapper.params.projection.get(7) to h),\n            wrapper.params.query!!)\n}\n\nfun <A, B, C, D, E, F, G, H, J> ColumnQueryWrapper<Nonuple<A, B, C, D, E, F, G, H, J>>.update(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, j: J): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    return Session.current<Session>().update(wrapper.params.table, arrayOf(wrapper.params.projection.get(0) to a,\n            wrapper.params.projection.get(1) to b,\n            wrapper.params.projection.get(2) to c,\n            wrapper.params.projection.get(3) to d,\n            wrapper.params.projection.get(4) to e,\n            wrapper.params.projection.get(5) to f,\n            wrapper.params.projection.get(6) to g,\n            wrapper.params.projection.get(7) to h,\n            wrapper.params.projection.get(8) to j),\n            wrapper.params.query!!)\n}\n\nfun <A, B, C, D, E, F, G, H, J, K> ColumnQueryWrapper<Decuple<A, B, C, D, E, F, G, H, J, K>>.update(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, j: J, k: K): Int {\n    val wrapper = TableSchemaProjectionQueryWrapper.get()\n    return Session.current<Session>().update(wrapper.params.table, arrayOf(wrapper.params.projection.get(0) to a,\n            wrapper.params.projection.get(1) to b,\n            wrapper.params.projection.get(2) to c,\n            wrapper.params.projection.get(3) to d,\n            wrapper.params.projection.get(4) to e,\n            wrapper.params.projection.get(5) to f,\n            wrapper.params.projection.get(6) to g,\n            wrapper.params.projection.get(7) to h,\n            wrapper.params.projection.get(8) to j,\n            wrapper.params.projection.get(9) to k),\n            wrapper.params.query!!)\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/ColumnQuintuple.kt",
    "content": "package kotlinx.nosql\n\nclass ColumnQuintuple<S : AbstractSchema, A, B, C, D, E>(val a: AbstractColumn<A, S, *>, val b: AbstractColumn<B, S, *>,\n                                                   val c: AbstractColumn<C, S, *>, val d: AbstractColumn<D, S, *>,\n                                                   val e: AbstractColumn<E, S, *>): ColumnQueryWrapper<Quintuple<A, B, C, D, E>>() {\n    operator fun <F> plus(f: AbstractColumn<F, S, *>): ColumnSextuple<S, A, B, C, D, E, F> {\n        return ColumnSextuple(a, b, c, d, e, f)\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/ColumnSeptuple.kt",
    "content": "package kotlinx.nosql\n\nclass ColumnSeptuple<S : AbstractSchema, A, B, C, D, E, F, G>(val a: AbstractColumn<A, S, *>, val b: AbstractColumn<B, S, *>,\n                                                         val c: AbstractColumn<C, S, *>, val d: AbstractColumn<D, S, *>,\n                                                         val e: AbstractColumn<E, S, *>, val f: AbstractColumn<F, S, *>,\n                                                         val g: AbstractColumn<G, S, *>): ColumnQueryWrapper<Septuple<A, B, C, D, E, F, G>>() {\n    operator fun <H> plus(h: AbstractColumn<H, S, *>): ColumnOctuple<S, A, B, C, D, E, F, G, H> {\n        return ColumnOctuple(a, b, c, d, e, f, g, h)\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/ColumnSextuple.kt",
    "content": "package kotlinx.nosql\n\nclass ColumnSextuple<S : AbstractSchema, A, B, C, D, E, F>(val a: AbstractColumn<A, S, *>, val b: AbstractColumn<B, S, *>,\n                                                      val c: AbstractColumn<C, S, *>, val d: AbstractColumn<D, S, *>,\n                                                      val e: AbstractColumn<E, S, *>, val f: AbstractColumn<F, S, *>): ColumnQueryWrapper<Sextuple<A, B, C, D, E, F>>() {\n    operator fun <G> plus(g: AbstractColumn<G, S, *>): ColumnSeptuple<S, A, B, C, D, E, F, G> {\n        return ColumnSeptuple(a, b, c, d, e, f, g)\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/ColumnTriple.kt",
    "content": "package kotlinx.nosql\n\nclass ColumnTriple<S : AbstractSchema, A, B, C>(val a: AbstractColumn<A, S, *>, val b: AbstractColumn<B, S, *>, val c: AbstractColumn<C, S, *>): ColumnQueryWrapper<Triple<A, B, C>>() {\n    operator fun <D> plus(d: AbstractColumn<D, S, *>): ColumnQuadruple<S, A, B, C, D> {\n        return ColumnQuadruple(a, b, c, d)\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/ColumnType.kt",
    "content": "package kotlinx.nosql\n\nenum class ColumnType(val primitive: Boolean = false,\n                      val iterable: Boolean = false,\n                      val list: Boolean = false,\n                      val set: Boolean = false,\n                      val custom: Boolean = false,\n                      val id: Boolean = false) {\n    INTEGER(primitive = true),\n    PRIMARY_ID(primitive = true, id = true),\n    FOREIGN_ID(primitive = true, id = true),\n    STRING(primitive = true),\n    BOOLEAN(primitive = true),\n    DATE(primitive = true),\n    TIME(primitive = true),\n    DATE_TIME(primitive = true),\n    DOUBLE(primitive = true),\n    FLOAT(primitive = true),\n    LONG(primitive = true),\n    SHORT(primitive = true),\n    BYTE(primitive = true),\n    INTEGER_SET(iterable = true, set = true),\n    ID_SET(iterable = true, set = true, id = true),\n    ID_LIST(iterable = true, list = true, id = true),\n    STRING_SET(iterable = true, set = true),\n    INTEGER_LIST(iterable = true, list = true),\n    STRING_LIST(iterable = true, list = true),\n    CUSTOM_CLASS(custom = true),\n    CUSTOM_CLASS_LIST(iterable = true, custom = true, list = true),\n    CUSTOM_CLASS_SET(iterable = true, custom = true, set = true)\n}\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Database.kt",
    "content": "package kotlinx.nosql\n\nimport java.util.concurrent.ConcurrentHashMap\nimport kotlinx.nosql.util.getAllFields\nimport kotlinx.nosql.util.isColumn\nimport kotlinx.nosql.util.asColumn\nimport kotlin.text.isNotEmpty\n\nabstract class Database<S: Session>(val schemas: Array<out AbstractSchema>, val action: SchemaGenerationAction<S>) {\n    abstract fun <R> withSession(statement: S.() -> R): R\n\n    fun initialize() {\n        for (schema in schemas) {\n            buildFullColumnNames(schema)\n            when (action) {\n            // TODO: implement validation\n                is Create, is CreateDrop -> {\n                    withSession {\n                        schema.drop()\n                        schema.create()\n                        if (this is IndexOperations)\n                            for (index in schema.indices)\n                                createIndex(schema, index)\n                    }\n                }\n                is Update -> {\n                    withSession {\n                        if (this is IndexOperations)\n                            for (index in schema.indices)\n                                createIndex(schema, index)\n                    }\n                }\n            // TODO: implement drop after exit\n            }\n        }\n        withSession {\n            if (action is Create) {\n                action.onCreate(this)\n            } else if (action is CreateDrop) {\n                action.onCreate(this)\n            }\n        }\n    }\n\n    private fun buildFullColumnNames(root: AbstractSchema, path: String = \"\",  schema: Any = root) {\n        val fields = getAllFields(schema.javaClass)\n        for (field in fields) {\n            if (field.isColumn) {\n                val column = field.asColumn(schema)\n                column._schema = root\n                val columnFullName = path + (if (path.isNotEmpty()) \".\" else \"\") + column.name\n                fullColumnNames.put(column, columnFullName)\n                buildFullColumnNames(root, columnFullName, column)\n            }\n        }\n    }\n\n    companion object {\n        val fullColumnNames = ConcurrentHashMap<AbstractColumn<*, *, *>, String>()\n    }\n}\n\nval AbstractColumn<*, *, *>.fullName: String\n    get() {\n        return Database.fullColumnNames.get(this)!!\n    }\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Decuple.kt",
    "content": "package kotlinx.nosql\n\nclass Decuple<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>(val a1: A1, val a2: A2, val a3: A3, val a4: A4, val a5: A5, val a6: A6, val a7: A7, val a8: A8, val a9: A9, val a10: A10) {\n    operator public fun component1(): A1 = a1\n    operator public fun component2(): A2 = a2\n    operator public fun component3(): A3 = a3\n    operator public fun component4(): A4 = a4\n    operator public fun component5(): A5 = a5\n    operator public fun component6(): A6 = a6\n    operator public fun component7(): A7 = a7\n    operator public fun component8(): A8 = a8\n    operator public fun component9(): A9 = a9\n    operator public fun component10(): A10 = a10\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Discriminator.kt",
    "content": "package kotlinx.nosql\n\nclass Discriminator<D: Any, S : DocumentSchema<out Any, out Any>>(val column: AbstractColumn<D, S, D>, val value: D) {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/DocumentSchema.kt",
    "content": "package kotlinx.nosql\n\nimport java.util.concurrent.CopyOnWriteArrayList\nimport java.util.concurrent.ConcurrentHashMap\nimport kotlin.reflect.KClass\n\nabstract class DocumentSchema<I: Any, D: Any>(name: String, val valueClass: KClass<D>, primaryKey: AbstractColumn<I,\n        out DocumentSchema<I, D>, I>, val discriminator: Discriminator<out Any, out DocumentSchema<out Any, out Any>>? = null) : TableSchema<I>(name, primaryKey) {\n    init {\n        if (discriminator != null) {\n            val emptyDiscriminators = CopyOnWriteArrayList<Discriminator<*, *>>()\n            val discriminators = tableDiscriminators.putIfAbsent(name, emptyDiscriminators)\n            if (discriminators != null)\n                discriminators.add(discriminator)\n            else\n                emptyDiscriminators.add(discriminator)\n            // TODO TODO TODO\n            discriminatorClasses.put(discriminator, this.valueClass)\n            discriminatorSchemaClasses.put(discriminator, this.javaClass)\n            discriminatorSchemas.put(discriminator, this)\n        }\n    }\n\n    companion object {\n        val tableDiscriminators = ConcurrentHashMap<String, MutableList<Discriminator<*, *>>>()\n        val discriminatorClasses = ConcurrentHashMap<Discriminator<*, *>, KClass<*>>()\n        val discriminatorSchemaClasses = ConcurrentHashMap<Discriminator<*, *>, Class<*>>()\n        val discriminatorSchemas = ConcurrentHashMap<Discriminator<*, *>, AbstractSchema>()\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/DocumentSchemaIdQueryWrapper.kt",
    "content": "package kotlinx.nosql\n\nimport java.util.ArrayList\nimport kotlin.collections.single\n\nclass DocumentSchemaIdQueryWrapper<T : DocumentSchema<P, C>, P: Any, C: Any>(val schema: T, val id: Id<P, T>): DocumentSchemaQueryWrapper<T, P, C>(DocumentSchemaQueryParams(schema,\n        schema.id.equal(id))\n) {\n    fun get(): C {\n        return single()\n    }\n\n    override fun iterator(): Iterator<C> {\n        val list = ArrayList<C>()\n        val value = with (Session.current<KeyValueDocumentSchemaOperations>()) { schema.get(id) }\n        if (value != null) {\n            list.add(value)\n        }\n        return list.iterator()\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/DocumentSchemaOperations.kt",
    "content": "package kotlinx.nosql\n\nimport kotlinx.nosql.query.NoQuery\n\ninterface DocumentSchemaOperations {\n    fun <T : DocumentSchema<P, V>, P: Any, V: Any> T.insert(v: V): Id<P, T>\n    fun <T: DocumentSchema<P, C>, P: Any, C: Any> T.find(query: T.() -> Query = { NoQuery }): DocumentSchemaQueryWrapper<T, P, C>\n    // TODO: Implement find(id) -> Wrapper\n    /*fun <T: DocumentSchema<P, C>, P, C> T.find(id: Id<P, T>): C? {\n        val w = find { this.id.equal(id) }\n        return if (w.count() > 0) w.single() else null\n    }*/\n\n    fun <T : DocumentSchema<P, C>, P: Any, C: Any> find(params: DocumentSchemaQueryParams<T, P, C>): Iterator<C>\n}\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/DocumentSchemaQueryParams.kt",
    "content": "package kotlinx.nosql\n\nclass DocumentSchemaQueryParams<T : DocumentSchema<P, C>, P: Any, C: Any>(val schema: T, val query: Query? = null,\n                                                                var skip: Int? = null, var take: Int? = null, var subscribed: Boolean = false)\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/DocumentSchemaQueryWrapper.kt",
    "content": "package kotlinx.nosql\n\nimport kotlin.collections.listOf\n\nopen class DocumentSchemaQueryWrapper<T : DocumentSchema<P, C>, P: Any, C: Any>(val params: kotlinx.nosql.DocumentSchemaQueryParams<T, P, C>): Iterable<C> {\n    override fun iterator(): Iterator<C> {\n        return Session.current<DocumentSchemaOperations>().find(params)\n    }\n\n    fun skip(num: Int): kotlinx.nosql.DocumentSchemaQueryWrapper<T, P, C> {\n        params.skip = num\n        return this\n    }\n\n    fun take(num: Int): DocumentSchemaQueryWrapper<T, P, C> {\n        params.take = num\n        return this\n    }\n\n    fun remove(): Int {\n        return Session.current<Session>().delete(params.schema, params.query!!)\n    }\n\n    fun <X> projection(x: T.() -> X): X {\n        val xx = params.schema.x()\n        val projectionParams = kotlinx.nosql.TableSchemaProjectionQueryParams<TableSchema<Any>, Any, Any>(params.schema as TableSchema<Any>,\n                when (xx) {\n                    is AbstractColumn<*, *, *> -> listOf(xx) as List<AbstractColumn<*, *, *>>\n                    is ColumnPair<*, *, *> -> listOf(xx.a, xx.b)\n                    is ColumnTriple<*, *, *, *> -> listOf(xx.a, xx.b, xx.c)\n                    is kotlinx.nosql.ColumnQuadruple<*, *, *, *, *> -> listOf(xx.a, xx.b, xx.c, xx.d)\n                    is ColumnQuintuple<*, *, *, *, *, *> -> listOf(xx.a, xx.b, xx.c, xx.d, xx.e)\n                    is ColumnSextuple<*, *, *, *, *, *, *> -> listOf(xx.a, xx.b, xx.c, xx.d, xx.e, xx.f)\n                    is ColumnSeptuple<*, *, *, *, *, *, *, *> -> listOf(xx.a, xx.b, xx.c, xx.d, xx.e, xx.f, xx.g)\n                    is ColumnOctuple<*, *, *, *, *, *, *, *, *> -> listOf(xx.a, xx.b, xx.c, xx.d, xx.e, xx.f, xx.g, xx.h)\n                    is ColumnNonuple<*, *, *, *, *, *, *, *, *, *> -> listOf(xx.a, xx.b, xx.c, xx.d, xx.e, xx.f, xx.g, xx.h, xx.j)\n                    is kotlinx.nosql.ColumnDecuple<*, *, *, *, *, *, *, *, *, *, *> -> listOf(xx.a, xx.b, xx.c, xx.d, xx.e, xx.f, xx.g, xx.h, xx.i, xx.j)\n                    else -> throw UnsupportedOperationException()\n                }, params.query)\n        TableSchemaProjectionQueryWrapper.set(TableSchemaProjectionQueryWrapper(projectionParams))\n        return params.schema.x()\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Expression.kt",
    "content": "package kotlinx.nosql\n\ninterface Expression<T> {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Id.kt",
    "content": "package kotlinx.nosql\n\nclass Id<I: Any, R: TableSchema<I>>(val value: I) {\n    override fun toString() = value.toString()\n\n    override fun equals(other: Any?): Boolean {\n        return if (other is Id<*, *>) value.equals(other.value) else false\n    }\n    override fun hashCode(): Int {\n        return value.hashCode()\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/IdListColumn.kt",
    "content": "package kotlinx.nosql\n\nimport kotlin.reflect.KClass\n\nopen class IdListColumn<S : TableSchema<P>, R: TableSchema<P>, P: Any>  (name: String, val refSchema: R) : AbstractColumn<List<Id<P, R>>, S, Id<P, R>>(name, Id::class as KClass<Id<P, R>>, ColumnType.ID_LIST) {\n}\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/IdSetColumn.kt",
    "content": "package kotlinx.nosql\n\nimport kotlin.reflect.KClass\n\nopen class IdSetColumn<S : TableSchema<P>, R: TableSchema<P>, P: Any>  (name: String, val refSchema: R) : AbstractColumn<Set<Id<P, R>>, S, Id<P, R>>(name, Id::class as KClass<Id<P, R>>, ColumnType.ID_SET) {\n}\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/IndexOperations.kt",
    "content": "package kotlinx.nosql\n\ninterface IndexOperations {\n    fun createIndex(schema: AbstractSchema, index: AbstractIndex)\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/KeyValueDocumentSchemaOperations.kt",
    "content": "package kotlinx.nosql\n\nimport kotlinx.nosql.query.NoQuery\n\ninterface KeyValueDocumentSchemaOperations {\n  fun <T : DocumentSchema<P, V>, P: Any, V: Any> T.insert(v: V): Id<P, T>\n  operator fun <T: DocumentSchema<P, C>, P: Any, C: Any> T.get(id: Id<P, T>): C?\n  fun <T: DocumentSchema<P, C>, P: Any, C: Any> T.find(id: Id<P, T>): DocumentSchemaIdQueryWrapper<T, P, C> {\n      return DocumentSchemaIdQueryWrapper(this, id)\n  }\n}\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/KeyValueSchema.kt",
    "content": "package kotlinx.nosql\n\nabstract class KeyValueSchema(name: String): AbstractSchema(name) {\n\n}\n\nfun <T: KeyValueSchema, X> T.projection(x: T.() -> X): X {\n    return x()\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/KeyValueSchemaOperations.kt",
    "content": "package kotlinx.nosql\n\ninterface KeyValueSchemaOperations {\n    operator fun <T : KeyValueSchema, C: Any> T.get(c: T.() -> AbstractColumn<C, T, *>): C?\n    operator fun <T : KeyValueSchema, C> T.set(c: () -> AbstractColumn<C, T, *>, v: C)\n\n    fun <X, S: Number, T: KeyValueSchema> AbstractColumn<X, T, S>.incr(value: S = 1 as S): X {\n        val value = Session.current<Session>().incr(schema, this, value)\n        if (columnType.id) {\n            return Id<Any, TableSchema<Any>>(value) as X\n        } else {\n            return value as X\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/ListColumn.kt",
    "content": "package kotlinx.nosql\n\nimport kotlin.reflect.KClass\n\nopen class ListColumn<C: Any, S : AbstractSchema> (name: String, valueClass: KClass<C>) : AbstractColumn<List<C>, S, C>(name, valueClass, ColumnType.CUSTOM_CLASS_LIST) {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/LiteralExpression.kt",
    "content": "package kotlinx.nosql\n\nclass LiteralExpression(val value: Any?): Expression<Any?> {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Nonuple.kt",
    "content": "package kotlinx.nosql\n\nclass Nonuple<A1, A2, A3, A4, A5, A6, A7, A8, A9>(val a1: A1, val a2: A2, val a3: A3, val a4: A4, val a5: A5, val a6: A6, val a7: A7, val a8: A8, val a9: A9) {\n    operator public fun component1(): A1 = a1\n    operator public fun component2(): A2 = a2\n    operator public fun component3(): A3 = a3\n    operator public fun component4(): A4 = a4\n    operator public fun component5(): A5 = a5\n    operator public fun component6(): A6 = a6\n    operator public fun component7(): A7 = a7\n    operator public fun component8(): A8 = a8\n    operator public fun component9(): A9 = a9\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/NotEqualQuery.kt",
    "content": "package kotlinx.nosql\n\nclass NotEqualQuery(val expr1: Expression<*>, val expr2: Expression<*>): Query() {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/NotMemberOfQuery.kt",
    "content": "package kotlinx.nosql\n\nclass NotMemberOfQuery(val expr1: Expression<*>, val expr2: Expression<*>): Query() {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/NullableColumn.kt",
    "content": "package kotlinx.nosql\n\nimport kotlin.reflect.KClass\n\nopen class NullableColumn<C: Any, S : AbstractSchema> (name: String, valueClass: KClass<C>,\n                                                  columnType: ColumnType) : AbstractColumn<C?, S, C>(name, valueClass, columnType), AbstractNullableColumn {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/NullableIdColumn.kt",
    "content": "package kotlinx.nosql\n\nimport kotlin.reflect.KClass\n\nopen class NullableIdColumn<I: Any, S : TableSchema<I>, R: TableSchema<I>> (name: String, valueClass: KClass<I>,\n                                                                            columnType: ColumnType) : AbstractColumn<Id<I, R>?, S, I>(name, valueClass, columnType), AbstractNullableColumn {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Octuple.kt",
    "content": "package kotlinx.nosql\n\nclass Octuple<A1, A2, A3, A4, A5, A6, A7, A8>(val a1: A1, val a2: A2, val a3: A3, val a4: A4, val a5: A5, val a6: A6, val a7: A7, val a8: A8) {\n    operator public fun component1(): A1 = a1\n    operator public fun component2(): A2 = a2\n    operator public fun component3(): A3 = a3\n    operator public fun component4(): A4 = a4\n    operator public fun component5(): A5 = a5\n    operator public fun component6(): A6 = a6\n    operator public fun component7(): A7 = a7\n    operator public fun component8(): A8 = a8\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/PrimaryKey.kt",
    "content": "package kotlinx.nosql\n\nopen class PrimaryKey<I>(val name: String, val javaClass: Class<I>, val columnType: ColumnType) {\n    companion object {\n        fun string(name: String) = PrimaryKey<String>(name, String::class.java, ColumnType.STRING)\n        fun integer(name: String) = PrimaryKey<Int>(name, Int::class.java, ColumnType.INTEGER)\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Quadruple.kt",
    "content": "package kotlinx.nosql\n\nclass Quadruple<A1, A2, A3, A4>(val a1: A1, val a2: A2, val a3: A3, val a4: A4) {\n    operator public fun component1(): A1 = a1\n    operator public fun component2(): A2 = a2\n    operator public fun component3(): A3 = a3\n    operator public fun component4(): A4 = a4\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Query.kt",
    "content": "package kotlinx.nosql\n\nimport kotlinx.nosql.query.OrQuery\n\nabstract class Query() {\n    infix fun and(op: Query): Query {\n        return AndQuery(this, op)\n    }\n\n    infix fun or(op: Query): Query {\n        return OrQuery(this, op)\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Quintuple.kt",
    "content": "package kotlinx.nosql\n\nclass Quintuple<A1, A2, A3, A4, A5>(val a1: A1, val a2: A2, val a3: A3, val a4: A4, val a5: A5) {\n    operator public fun component1(): A1 = a1\n    operator public fun component2(): A2 = a2\n    operator public fun component3(): A3 = a3\n    operator public fun component4(): A4 = a4\n    operator public fun component5(): A5 = a5\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/SchemaGenerationAction.kt",
    "content": "package kotlinx.nosql\n\nabstract class SchemaGenerationAction<S : Session>() {\n}\n\nclass Create<S: Session>(val onCreate: S.() -> Unit = { }) : SchemaGenerationAction<S>()\n\nclass CreateDrop<S: Session>(val onCreate: S.() -> Unit = { },\n             onDrop: S.() -> Unit = { }) : SchemaGenerationAction<S>()\n\nclass Update<S: Session>() : SchemaGenerationAction<S>()\n\nclass Validate<S: Session>() : SchemaGenerationAction<S>()\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Septuple.kt",
    "content": "package kotlinx.nosql\n\nclass Septuple<A1, A2, A3, A4, A5, A6, A7>(val a1: A1, val a2: A2, val a3: A3, val a4: A4, val a5: A5, val a6: A6, val a7: A7) {\n    operator public fun component1(): A1 = a1\n    operator public fun component2(): A2 = a2\n    operator public fun component3(): A3 = a3\n    operator public fun component4(): A4 = a4\n    operator public fun component5(): A5 = a5\n    operator public fun component6(): A6 = a6\n    operator public fun component7(): A7 = a7\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Session.kt",
    "content": "package kotlinx.nosql\n\nimport java.util.ArrayList\n\ninterface Session {\n    fun <T : AbstractSchema>T.create()\n\n    fun <T : AbstractSchema>T.drop()\n\n    // TODO: Refactor\n    fun <T : AbstractSchema> insert(columns: Array<Pair<AbstractColumn<*, T, *>, *>>)\n\n    // TODO: Refactor\n    fun <T : AbstractSchema> delete(table: T, op: Query): Int\n\n    fun update(schema: AbstractSchema, columnValues: Array<Pair<AbstractColumn<*, *, *>, *>>, op: Query): Int\n\n    fun <T> addAll(schema: AbstractSchema, column: AbstractColumn<Collection<T>, *, *>, values: Collection<T>, op: Query): Int\n    fun <T: Number> incr(schema: KeyValueSchema, column: AbstractColumn<*, *, T>, value: T): T\n    //internal fun <T: Number> incr(schema: AbstractSchema, column: AbstractColumn<*, *, T>, value: T, op: Query): T\n\n    fun <T> removeAll(schema: AbstractSchema, column: AbstractColumn<Collection<T>, *, *>, values: Collection<T>, op: Query): Int\n\n    fun <T> removeAll(schema: AbstractSchema, column: AbstractColumn<Collection<T>, *, *>, removeOp: Query, op: Query): Int\n\n    companion object {\n        val threadLocale = ThreadLocal<Session>()\n\n        fun <T> current(): T {\n            return threadLocale.get()!! as T\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/SetColumn.kt",
    "content": "package kotlinx.nosql\n\nimport kotlin.reflect.KClass\n\nopen class SetColumn<C: Any, S : AbstractSchema> (name: String, valueClass: KClass<C>) : AbstractColumn<Set<C>, S, C>(name, valueClass, ColumnType.CUSTOM_CLASS_SET) {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/Sextuple.kt",
    "content": "package kotlinx.nosql\n\nclass Sextuple<A1, A2, A3, A4, A5, A6>(val a1: A1, val a2: A2, val a3: A3, val a4: A4, val a5: A5, val a6: A6) {\n    operator public fun component1(): A1 = a1\n    operator public fun component2(): A2 = a2\n    operator public fun component3(): A3 = a3\n    operator public fun component4(): A4 = a4\n    operator public fun component5(): A5 = a5\n    operator public fun component6(): A6 = a6\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/TableSchema.kt",
    "content": "package kotlinx.nosql\n\nabstract class TableSchema<I: Any>(tableName: String, primaryKey: AbstractColumn<I, out TableSchema<I>, I>): AbstractTableSchema(tableName) {\n    val pk = AbstractColumn<Id<I, TableSchema<I>>, TableSchema<I>, I>(primaryKey.name, primaryKey.valueClass, ColumnType.PRIMARY_ID)\n}\n\n// Extension functions\n\nval <C: Any, T : TableSchema<C>> T.id: AbstractColumn<Id<C, T>, T, C>\n    get () {\n        return pk as AbstractColumn<Id<C, T>, T, C>\n    }\n\nfun <S : AbstractSchema, R: TableSchema<P>, P: Any> id(name: String, refSchema: R): AbstractColumn<Id<P, R>, S, P> = AbstractColumn(name, refSchema.id.valueClass, ColumnType.FOREIGN_ID)\nfun <S : AbstractSchema, R: TableSchema<P>, P: Any> S.id(name: String, refSchema: R): AbstractColumn<Id<P, R>, S, P> = AbstractColumn(name, refSchema.id.valueClass, ColumnType.FOREIGN_ID)\n\nfun <S : TableSchema<P>, R: TableSchema<P>, P: Any>  listOfId(name: String, refSchema: R): IdListColumn<S, R, P> = IdListColumn(name, refSchema)\nfun <S : TableSchema<P>, R: TableSchema<P>, P: Any> S.listOfId(name: String, refSchema: R): IdListColumn<S, R, P> = IdListColumn(name, refSchema)\n\nfun <S : TableSchema<P>, R: TableSchema<P>, P: Any>  setOfId(name: String, refSchema: R): IdSetColumn<S, R, P> = IdSetColumn(name, refSchema)\nfun <S : TableSchema<P>, R: TableSchema<P>, P: Any> S.setOfId(name: String, refSchema: R): IdSetColumn<S, R, P> = IdSetColumn(name, refSchema)\n\nfun <S : TableSchema<P>, R: TableSchema<P>, P: Any> nullableId(name: String, refSchema: R): NullableIdColumn<P, S, R> = NullableIdColumn(name, refSchema.id.valueClass, ColumnType.FOREIGN_ID)\nfun <S : TableSchema<P>, R: TableSchema<P>, P: Any> S.nullableId(name: String, refSchema: R): NullableIdColumn<P, S, R> = NullableIdColumn(name, refSchema.id.valueClass, ColumnType.FOREIGN_ID)\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/TableSchemaOperations.kt",
    "content": "package kotlinx.nosql\n\ninterface TableSchemaOperations {\n    fun <T : TableSchema<P>, P: Any, V: Any> find(params: TableSchemaProjectionQueryParams<T, P, V>): Iterator<V>\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/TableSchemaProjectionQueryParams.kt",
    "content": "package kotlinx.nosql\n\nclass TableSchemaProjectionQueryParams<T : TableSchema<P>, P: Any, V>(val table: T, val projection: List<AbstractColumn<*, *, *>>, val query: Query? = null,\n                                                                 var skip: Int? = null, var take: Int? = null) {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/TableSchemaProjectionQueryWrapper.kt",
    "content": "package kotlinx.nosql\n\nclass TableSchemaProjectionQueryWrapper<T : TableSchema<P>, P: Any, V: Any>(val params: TableSchemaProjectionQueryParams<T, P, V>): Iterable<V> {\n    override fun iterator(): Iterator<V> {\n        return Session.current<TableSchemaOperations>().find(params)\n    }\n\n    fun skip(num: Int): TableSchemaProjectionQueryWrapper<T, P, V> {\n        params.skip = num\n        return this\n    }\n\n    fun take(num: Int): TableSchemaProjectionQueryWrapper<T, P, V> {\n        params.take = num\n        return this\n    }\n\n    companion object {\n        val threadLocal = ThreadLocal<TableSchemaProjectionQueryWrapper<out TableSchema<*>, *, *>>()\n\n        fun get(): TableSchemaProjectionQueryWrapper<out TableSchema<*>, *, *> {\n            return threadLocal.get()!! as TableSchemaProjectionQueryWrapper<out TableSchema<*>, *, *>\n        }\n\n        fun set(value: TableSchemaProjectionQueryWrapper<out TableSchema<*>, *, *>) {\n            threadLocal.set(value)\n        }\n    }\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/query/EqualQuery.kt",
    "content": "package kotlinx.nosql.query\n\nimport kotlinx.nosql.Expression\nimport kotlinx.nosql.Query\n\nclass EqualQuery(val expr1: Expression<*>, val expr2: Expression<*>): Query() {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/query/GreateQuery.kt",
    "content": "package kotlinx.nosql.query\n\nimport kotlinx.nosql.Query\nimport kotlinx.nosql.Expression\n\nclass GreaterQuery(val expr1: Expression<*>, val expr2: Expression<*>): Query() {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/query/GreaterEqualQuery.kt",
    "content": "package kotlinx.nosql.query\n\nimport kotlinx.nosql.Expression\nimport kotlinx.nosql.Query\n\nclass GreaterEqualQuery(val expr1: Expression<*>, val expr2: Expression<*>): Query() {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/query/IsNotNullQuery.kt",
    "content": "package kotlinx.nosql.query\n\nimport kotlinx.nosql.AbstractColumn\nimport kotlinx.nosql.Query\n\nclass IsNotNullQuery(val column: AbstractColumn<*, *, *>): Query() {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/query/IsNullQuery.kt",
    "content": "package kotlinx.nosql.query\n\nimport kotlinx.nosql.AbstractColumn\nimport kotlinx.nosql.Query\n\nclass IsNullQuery(val column: AbstractColumn<*, *, *>): Query() {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/query/LessEqualQuery.kt",
    "content": "package kotlinx.nosql.query\n\nimport kotlinx.nosql.Expression\nimport kotlinx.nosql.Query\n\nclass LessEqualQuery(val expr1: Expression<*>, val expr2: Expression<*>): Query() {\n}\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/query/LessQuery.kt",
    "content": "package kotlinx.nosql.query\n\nimport kotlinx.nosql.Expression\nimport kotlinx.nosql.Query\n\nclass LessQuery(val expr1: Expression<*>, val expr2: Expression<*>): Query() {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/query/MatchesQuery.kt",
    "content": "package kotlinx.nosql.query\n\nimport kotlinx.nosql.Expression\nimport kotlinx.nosql.Query\n\nclass MatchesQuery(val expr1: Expression<*>, val expr2: Expression<*>): Query() {\n}\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/query/MemberOfQuery.kt",
    "content": "package kotlinx.nosql.query\n\nimport kotlinx.nosql.Query\nimport kotlinx.nosql.Expression\n\nclass MemberOfQuery(val expr1: Expression<*>, val expr2: Expression<*>): Query() {\n}\n"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/query/NoQuery.kt",
    "content": "package kotlinx.nosql.query\n\nimport kotlinx.nosql.Query\n\nobject NoQuery : Query() {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/query/OrQuery.kt",
    "content": "package kotlinx.nosql.query\n\nimport kotlinx.nosql.Query\n\nclass OrQuery(val expr1: Query, val expr2: Query): Query() {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/query/TextQuery.kt",
    "content": "package kotlinx.nosql.query\n\nimport kotlinx.nosql.Query\n\nclass TextQuery(val search: String): Query() {\n}"
  },
  {
    "path": "src/main/kotlin/kotlinx/nosql/util/SchemaUtils.kt",
    "content": "package kotlinx.nosql.util\n\nimport java.lang.reflect.Field\nimport java.util.ArrayList\nimport java.util.HashMap\nimport kotlinx.nosql.AbstractColumn\nimport kotlinx.nosql.AbstractSchema\nimport org.joda.time.LocalDate\nimport org.joda.time.LocalTime\nimport org.joda.time.DateTime\nimport kotlin.collections.listOf\nimport kotlin.collections.setOf\nimport kotlin.text.toLowerCase\n\nfun getAllFields(_type: Class<in Any>, condition: (Field) -> Boolean = { f -> true },\n                 fields: MutableList<Field> = ArrayList()): MutableList<Field> {\n    for (field in _type.declaredFields!!) {\n        if (condition(field)) fields.add(field)\n    }\n    if (_type.superclass != null) {\n        getAllFields(_type.superclass!!, condition, fields)\n    }\n    return fields\n}\n\nfun getAllFieldsMap(_type: Class<in Any>, condition: (Field) -> Boolean = { f -> true },\n                    fields: MutableMap<String, Field> = HashMap()): MutableMap<String, Field> {\n    for (field in _type.declaredFields!!) {\n        if (condition(field)) fields.put(field.name!!.toLowerCase(), field)\n    }\n    if (_type.superclass != null) {\n        getAllFieldsMap(_type.superclass, condition, fields)\n    }\n    return fields\n}\n\nval Field.isColumn: Boolean\n    get() {\n        return AbstractColumn::class.java.isAssignableFrom(this.type!!)\n    }\n\nfun Field.asColumn(schema: Any): AbstractColumn<*, *, *> {\n    this.isAccessible = true\n    return this.get(schema) as AbstractColumn<*, *, *>\n}\n\nfun newInstance(clazz: Class<out Any?>): Any {\n  val constructor = clazz.constructors!![0]\n  val constructorParamTypes = constructor.parameterTypes!!\n  val constructorParamValues = Array<Any?>(constructor.parameterTypes!!.size, { index: Int ->\n    when (constructorParamTypes[index].name) {\n      \"int\" -> 0\n      \"java.lang.String\" -> \"\"\n      \"org.joda.time.LocalDate\" -> LocalDate()\n      \"org.joda.time.LocalTime\" -> LocalTime()\n      \"org.joda.time.DateTime\" -> DateTime()\n      \"double\" -> 0.toDouble()\n      \"float\" -> 0.toFloat()\n      \"long\" -> 0.toLong()\n      \"short\" -> 0.toShort()\n      \"byte\" -> 0.toByte()\n      \"boolean\" -> false\n      \"java.util.List\" -> listOf<Any>()\n      \"java.util.Set\" -> setOf<Any>()\n      else -> newInstance(constructorParamTypes[index])\n    }\n  })\n  return constructor.newInstance(*constructorParamValues)!!\n}\n"
  }
]