diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..8a7945ee6 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,93 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + workflow_dispatch: + push: + branches: + - master + paths-ignore: + - '.github/**' + - 'docker/**' + - 'docs/**' + - 'tutorial/**' + - 'ChangeLog.md' + - 'README.md' + pull_request: + types: [ opened, synchronize, reopened ] + branches: + - master + - main + - v7 + - v6 + schedule: + - cron: '0 0 * * *' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: 17 + distribution: 'adopt' + cache: maven + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/maven-deploy.yml b/.github/workflows/maven-deploy.yml new file mode 100644 index 000000000..f7532d404 --- /dev/null +++ b/.github/workflows/maven-deploy.yml @@ -0,0 +1,34 @@ +name: Deploy + +on: + workflow_dispatch: + push: + tags: [ deploy** ] + +jobs: + deploy: + timeout-minutes: 20 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'adopt' + cache: 'maven' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_CENTRAL_TOKEN + gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE + - name: Publish to Apache Maven Central + run: mvn --no-transfer-progress -Ddeploy -Dmaven.test.skip=true deploy + env: + MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} + MAVEN_CENTRAL_TOKEN: ${{ secrets.OSSRH_PASSWORD }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} diff --git a/.github/workflows/maven-release.yml b/.github/workflows/maven-release.yml new file mode 100644 index 000000000..61217e1b3 --- /dev/null +++ b/.github/workflows/maven-release.yml @@ -0,0 +1,40 @@ +name: Release + +on: + workflow_dispatch: + push: + tags: [ release** ] + +jobs: + release: + timeout-minutes: 20 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'adopt' + cache: 'maven' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_CENTRAL_TOKEN + gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE + - name: Publish to Apache Maven Central + run: mvn --no-transfer-progress -Ddeploy -Dmaven.test.skip=true deploy + env: + MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} + MAVEN_CENTRAL_TOKEN: ${{ secrets.OSSRH_PASSWORD }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} + - name: Release to Apache Maven Central + run: mvn --no-transfer-progress -Ddeploy -Dmaven.test.skip=true nexus-staging:release + env: + MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} + MAVEN_CENTRAL_TOKEN: ${{ secrets.OSSRH_PASSWORD }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml deleted file mode 100644 index 388a156d5..000000000 --- a/.github/workflows/maven.yml +++ /dev/null @@ -1,130 +0,0 @@ -name: Java CI - -on: - push: - branches: - - master - pull_request: - types: [ opened, synchronize, reopened ] - branches: - - master - -jobs: - - test: - timeout-minutes: 20 - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - docker-img: - - docker.io/arangodb/arangodb:3.7.17 - - docker.io/arangodb/arangodb:3.8.6 - - docker.io/arangodb/arangodb:3.9.1 - - docker.io/arangodb/enterprise:3.7.17 - - docker.io/arangodb/enterprise:3.8.6 - - docker.io/arangodb/enterprise:3.9.1 - topology: - - single - - cluster - - activefailover - db-ext-names: - - false - java-version: - - 8 - user-language: - - en - include: - - docker-img: docker.io/arangodb/arangodb:3.9.1 - topology: single - db-ext-names: true - java-version: 11 - user-language: tr - - docker-img: docker.io/arangodb/enterprise:3.9.1 - topology: cluster - db-ext-names: true - java-version: 17 - user-language: tr - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK - uses: actions/setup-java@v2 - with: - java-version: ${{matrix.java-version}} - distribution: 'adopt' - cache: maven - - name: Start Database - run: ./docker/start_db.sh - env: - ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} - STARTER_MODE: ${{matrix.topology}} - DOCKER_IMAGE: ${{matrix.docker-img}} - DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} - - name: Info - run: mvn -version - - name: Test - run: mvn --no-transfer-progress test -DargLine="-Duser.language=${{matrix.user-language}}" - - # test encodeURIComponent() and normalize('NFC') comparing to Javascript behavior - test-graalvm: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: graalvm/setup-graalvm@v1 - with: - version: 'latest' - java-version: '11' - github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Info - run: mvn -version - - name: Test - run: mvn -e --no-transfer-progress test -Dtest=com.arangodb.util.UnicodeUtilsTest - - test-jwt: - timeout-minutes: 20 - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - docker-img: - - docker.io/arangodb/enterprise:3.9.1 - topology: - - single - - cluster - - activefailover - db-ext-names: - - false - java-version: - - 17 - user-language: - - en - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK - uses: actions/setup-java@v2 - with: - java-version: ${{matrix.java-version}} - distribution: 'adopt' - cache: maven - - name: Start Database - run: ./docker/start_db.sh - env: - ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} - STARTER_MODE: ${{matrix.topology}} - DOCKER_IMAGE: ${{matrix.docker-img}} - DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} - - name: Set JWT - run: | - ENDPOINT=$(./docker/find_active_endpoint.sh) - echo "Active endpoint: $ENDPOINT" - JWT=$(curl "http://$ENDPOINT/_db/_system/_open/auth" -X POST -d '{"username":"root","password":"test"}' | jq ".jwt" | xargs) - echo "Setting JWT: $JWT" - sed -i "/arangodb.password/c\arangodb.jwt=$JWT" src/test/resources/arangodb.properties - - name: Info - run: mvn -version - - name: Test - run: mvn --no-transfer-progress test -DargLine="-Duser.language=${{matrix.user-language}}" diff --git a/.github/workflows/native.yml b/.github/workflows/native.yml index 2649ed0de..9df54ccf5 100644 --- a/.github/workflows/native.yml +++ b/.github/workflows/native.yml @@ -14,13 +14,14 @@ jobs: fail-fast: false matrix: docker-img: - - docker.io/arangodb/enterprise:3.9.1 + - docker.io/arangodb/enterprise:3.10.1 topology: - cluster - db-ext-names: - - false java-version: - 17 + module: + - driver + - shaded-integration-tests steps: - uses: actions/checkout@v2 @@ -29,15 +30,57 @@ jobs: version: 'latest' java-version: ${{matrix.java-version}} github-token: ${{ secrets.GITHUB_TOKEN }} - components: 'native-image' + components: 'native-image,js' - name: Start Database run: ./docker/start_db.sh env: ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} STARTER_MODE: ${{matrix.topology}} DOCKER_IMAGE: ${{matrix.docker-img}} - DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} - name: Info run: mvn -version + - name: Install + run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true - name: Test Native - run: mvn -Pnative --no-transfer-progress test + working-directory: ${{matrix.module}} + run: mvn --no-transfer-progress -Pnative test + + test-native-ssl: + timeout-minutes: 20 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + docker-img: + - docker.io/arangodb/enterprise:3.10.1 + topology: + - single + java-version: + - 17 + module: + - driver + - shaded-integration-tests + + steps: + - uses: actions/checkout@v2 + - uses: graalvm/setup-graalvm@v1 + with: + version: 'latest' + java-version: ${{matrix.java-version}} + github-token: ${{ secrets.GITHUB_TOKEN }} + components: 'native-image,js' + - name: Start Database + run: ./docker/start_db.sh + env: + ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} + STARTER_MODE: ${{matrix.topology}} + DOCKER_IMAGE: ${{matrix.docker-img}} + SSL: true + - name: Info + run: mvn -version + - name: Install + run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true + - name: Test Native + working-directory: ${{matrix.module}} + run: mvn --no-transfer-progress -Pnative -Dgroups=ssl -DSslTest=true test diff --git a/.github/workflows/resilience.yml b/.github/workflows/resilience.yml new file mode 100644 index 000000000..cfba2570c --- /dev/null +++ b/.github/workflows/resilience.yml @@ -0,0 +1,38 @@ +name: Resilience Tests + +on: + workflow_dispatch: + push: + tags: [ v** ] + +jobs: + test: + timeout-minutes: 20 + runs-on: ubuntu-latest + + env: + TOXIPROXY_VERSION: v2.5.0 + + strategy: + fail-fast: false + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: 19 + distribution: 'adopt' + cache: maven + - name: Start Database + run: ./docker/start_db.sh + - name: Info + run: mvn -version + - name: Start Toxiproxy + working-directory: resilience-tests + run: ./bin/startProxy.sh + - name: Install + run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true + - name: Test + working-directory: resilience-tests + run: mvn --no-transfer-progress test diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..d4bef6589 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,312 @@ +name: Test + +on: + workflow_dispatch: + push: + branches: + - master + - main + - v7 + - v6 + paths-ignore: + - '.github/**' + - 'docker/**' + - 'docs/**' + - 'tutorial/**' + - 'ChangeLog.md' + - 'README.md' + pull_request: + types: [ opened, synchronize, reopened ] + branches: + - master + - main + - v7 + - v6 + +jobs: + + test: + timeout-minutes: 20 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + docker-img: + - docker.io/arangodb/arangodb:3.8.8 + - docker.io/arangodb/arangodb:3.9.5 + - docker.io/arangodb/arangodb:3.10.1 + - docker.io/arangodb/enterprise:3.8.8 + - docker.io/arangodb/enterprise:3.9.5 + - docker.io/arangodb/enterprise:3.10.1 + topology: + - single + - cluster + - activefailover + db-ext-names: + - false + java-version: + - 8 + user-language: + - en + include: + - docker-img: docker.io/arangodb/arangodb:3.10.1 + topology: single + db-ext-names: true + java-version: 11 + user-language: tr + - docker-img: docker.io/arangodb/enterprise:3.10.1 + topology: cluster + db-ext-names: true + java-version: 17 + user-language: tr + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: ${{matrix.java-version}} + distribution: 'adopt' + cache: maven + - name: Start Database + run: ./docker/start_db.sh + env: + ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} + STARTER_MODE: ${{matrix.topology}} + DOCKER_IMAGE: ${{matrix.docker-img}} + DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} + - name: Info + run: mvn -version + - name: Test + run: mvn --no-transfer-progress -am -pl driver test -DargLine="-Duser.language=${{matrix.user-language}}" + + test-ssl: + timeout-minutes: 10 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + docker-img: + - docker.io/arangodb/arangodb:3.10.1 + topology: + - single + java-version: + - 17 + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: ${{matrix.java-version}} + distribution: 'adopt' + cache: maven + - name: Start Database + run: ./docker/start_db.sh + env: + ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} + STARTER_MODE: ${{matrix.topology}} + DOCKER_IMAGE: ${{matrix.docker-img}} + SSL: true + - name: Info + run: mvn -version + - name: Test + run: mvn --no-transfer-progress -Dgroups=ssl -DSslTest=true -am -pl driver test + + # test encodeURIComponent() and normalize('NFC') comparing to Javascript behavior + test-graalvm: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: graalvm/setup-graalvm@v1 + with: + version: 'latest' + java-version: '11' + github-token: ${{ secrets.GITHUB_TOKEN }} + components: 'js' + - name: Info + run: mvn -version + - name: Test + run: mvn -e --no-transfer-progress -am -pl driver test -Dtest=graalvm.UnicodeUtilsTest -Dsurefire.failIfNoSpecifiedTests=false + + test-jwt: + timeout-minutes: 20 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + docker-img: + - docker.io/arangodb/enterprise:3.10.1 + topology: + - single + - cluster + - activefailover + db-ext-names: + - false + java-version: + - 17 + user-language: + - en + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: ${{matrix.java-version}} + distribution: 'adopt' + cache: maven + - name: Start Database + run: ./docker/start_db.sh + env: + ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} + STARTER_MODE: ${{matrix.topology}} + DOCKER_IMAGE: ${{matrix.docker-img}} + DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} + - name: Set JWT + run: | + ENDPOINT=$(./docker/find_active_endpoint.sh) + echo "Active endpoint: $ENDPOINT" + JWT=$(curl "http://$ENDPOINT/_db/_system/_open/auth" -X POST -d '{"username":"root","password":"test"}' | jq ".jwt" | xargs) + echo "Setting JWT: $JWT" + sed -i "/arangodb.password/c\arangodb.jwt=$JWT" driver/src/test/resources/arangodb.properties + - name: Info + run: mvn -version + - name: Test + run: mvn --no-transfer-progress -am -pl driver test -DargLine="-Duser.language=${{matrix.user-language}}" + + jackson-test: + timeout-minutes: 20 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + jackson-version: + - 2.14.1 + - 2.13.3 + - 2.12.7 + - 2.11.4 + - 2.10.5 + docker-img: + - docker.io/arangodb/arangodb:3.10.1 + topology: + - single + db-ext-names: + - false + java-version: + - 17 + user-language: + - en + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: ${{matrix.java-version}} + distribution: 'adopt' + cache: maven + - name: Start Database + run: ./docker/start_db.sh + env: + ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} + STARTER_MODE: ${{matrix.topology}} + DOCKER_IMAGE: ${{matrix.docker-img}} + DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} + - name: Info + run: mvn -version + - name: Test + run: mvn --no-transfer-progress -am -pl driver test -Dadb.jackson.version=${{matrix.jackson-version}} + + shaded-integration-tests: + timeout-minutes: 20 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + docker-img: + - docker.io/arangodb/arangodb:3.10.1 + topology: + - single + - cluster + java-version: + - 17 + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: ${{matrix.java-version}} + distribution: 'adopt' + cache: maven + - name: Start Database + run: ./docker/start_db.sh + env: + STARTER_MODE: ${{matrix.topology}} + DOCKER_IMAGE: ${{matrix.docker-img}} + - name: Info + run: mvn -version + - name: Install + run: mvn --no-transfer-progress install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true + - name: Test internal-serde + working-directory: shaded-integration-tests + run: mvn --no-transfer-progress -Pinternal-serde test + - name: Test jackson-serde + working-directory: shaded-integration-tests + run: mvn --no-transfer-progress -Pjackson-serde test + - name: Test jsonb-serde + working-directory: shaded-integration-tests + run: mvn --no-transfer-progress -Pjsonb-serde test + + sonar: + timeout-minutes: 10 + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + docker-img: + - docker.io/arangodb/enterprise:3.10.1 + topology: + - cluster + db-ext-names: + - false + java-version: + - 11 + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + java-version: ${{matrix.java-version}} + distribution: 'adopt' + cache: maven + - name: Start Database + run: ./docker/start_db.sh + env: + ARANGO_LICENSE_KEY: ${{ secrets.ARANGO_LICENSE_KEY }} + STARTER_MODE: ${{matrix.topology}} + DOCKER_IMAGE: ${{matrix.docker-img}} + DATABASE_EXTENDED_NAMES: ${{matrix.db-ext-names}} + - name: Info + run: mvn -version + - name: Cache SonarCloud packages + uses: actions/cache@v1 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Build and analyze + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: mvn --no-transfer-progress -Pstatic-code-analysis -B -Dgpg.skip=true -am -pl driver verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=arangodb_arangodb-java-driver diff --git a/.gitignore b/.gitignore index 04451cf5c..11ee1822e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,17 @@ -/.classpath -/.project -/.settings -/target -/.idea -/*.iml -/bin +.classpath +.project +.settings +target +.idea +*.iml +.directory /docker/jwtHeader /docker/jwtSecret - /docker/data -/test-results-native/ + +test-results-native +.flattened-pom.xml +/resilience-tests/bin/toxiproxy-server-linux-amd64 + +dependency-reduced-pom.xml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b1ec09396..000000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: java - -before_script: - - chmod 777 ./tests/travis/setup_arangodb.sh - - ./tests/travis/setup_arangodb.sh - -after_script: - - killall -9 arangod_x86_64 - -install: mvn install -DskipTests=true -Dgpg.skip=true -Dmaven.javadoc.skip=true -B -V - -jdk: - - oraclejdk8 - -sudo: false diff --git a/ChangeLog.md b/ChangeLog.md index c65303ea8..09a65730a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -6,6 +6,101 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [Unreleased] +## [7.0.0-ALPHA.2] + +### Changed + +- configuration properties from local files are not loaded automatically anymore +- `ArangoDB.execute()` accepts now target deserialization type +- `Request` and `Response` support now generic body type +- removed default host configuration (`127.0.0.1:8529`) +- changed http client library to Vert.x WebClient +- changed default communication protocol from `VST` to `HTTP/2` +- changed default content-type format from `VPACK` to `JSON` +- changed internal serialization, now based on Jackson API +- `VPACK` support is now provided by `JacksonSerde` including the optional dependency + `com.arangodb:jackson-dataformat-velocypack` (`VPACK` dataformat backend for Jackson) +- data objects passed as arguments to API methods are treated as immutable and the related metadata fields are not + updated in place anymore (updated metadata can be found in the returned object) +- changed some API signatures which were using unnecessary generics from `ArangoCollection`, `ArangoVertexCollection` and `ArangoEdgeCollection` +- changed `ArangoCursor#getStats()` to return untyped map +- replication factor is now represented by a new interface (`ReplicationFactor`) with + implementations: `NumericReplicationFactor` and `SatelliteReplicationFactor` +- all data definition classes are now `final` (packages `com.arangodb.entity` and `com.arangodb.model`) +- `BaseDocument` and `BaseEdgeDocument` are now `final` +- `BaseDocument#getProperties()` and `BaseEdgeDocument#getProperties()` return now an unmodifiable map +- removed `throws ArangoDBException` from API method signatures (unchecked exception) +- removed passwords from debug level requests logs (#410) +- JPMS: explicit automatic module name + +### Added + +- added `ArangoDB.Builder.loadProperties(ArangoConfigProperties)` to register custom configuration suppliers +- added `ArangoConfigProperties.fromFile()` to load properties from local files +- added support to `HTTP/2` communication protocol +- added optional transitive dependency on `io.vertx:vertx-web-client` (can be excluded if using VST only) +- added transitive dependency on Jackson Core, Databind and Annotations +- added wrapper class for raw JSON content (`RawJson`) +- added wrapper class for content already encoded as byte array (`RawBytes`) +- added support for Jackson types (`JsonNode`, `ArrayNode`, `ObjectNode`, ...) +- added support for Jackson annotations in data types +- added new user data custom serializer API based on `ArangoSerde` +- added new user data custom serializer implementation based on Jackson (`JacksonSerde`), supporting both `JSON` and `VPACK`) +- added methods and parameters targets to meta binding annotations +- added overloaded methods for CRUD operations allowing specifying the return type +- added API to support CRUD operations from raw data (`RawBytes` and `RawJson`) containing multiple documents +- added `BaseDocument#removeAttribute(String)` and `BaseEdgeDocument#removeAttribute(String)` +- added request id to `ArangoDBException` +- shaded version of the driver (`com.arangodb:arangodb-java-driver-shaded`) + +### Fixed + +- removed `--allow-incomplete-classpath` from native image configuration (#397) +- ability to control whether `null` values are included in the serialization (#389) +- added support to `DocumentCreateOptions#keepNull` (#374) +- allow specifying the return type on insertDocuments (#373) +- credentials logging (#410) + +### Removed + +- removed user data custom serializer API based on `ArangoSerialization` (in favor of `ArangoSerde`) +- removed user data custom serializer implementation `ArangoJack` (in favor of `JacksonSerde`) +- removed support for interpreting raw strings as JSON (in favor of `RawJson`) +- removed support of data type `VPackSlice` (in favor of Jackson types: `JsonNode`, `ArrayNode`, `ObjectNode`, ...) +- removed client APIs already deprecated in Java Driver version `6` +- removed deprecated server APIs: + - `MMFiles` related APIs + - `ArangoDatabase.executeTraversal()` + - `ArangoDB.getLogs()` + - `minReplicationFactor` in collections and graphs + - `overwrite` flag in `DocumentCreateOptions` +- removed `ArangoCursorInitializer` + +## [6.20.0] - 2022-11-29 + +- ArangoSearch cache (#472) +- support for `enterprise-hex-smart-vertex` shardingStrategy +- deprecated `com.arangodb.Function` + +## [6.19.0] - 2022-10-04 + +- added support for `search-alias` views (ArangoDB 3.10 #461) +- added support for nested search (ArangoDB 3.10, #460) +- added support for `classification`, `nearest_neighbors` and `minhash` search analyzers (ArangoDB 3.10, #458) +- added support for inverted indexes (ArangoDB 3.10, #457) +- added support for cluster dirty reads (ArangoDB 3.10, #455) +- added support for index stored values (ArangoDB 3.10) +- added support for geo index legacy polygons (ArangoDB 3.10) +- added support for getting query optimizer rules (ArangoDB 3.10) +- added support for enhanced cursor stats (ArangoDB 3.10) +- added support for computed values (ArangoDB 3.10) +- added support for index cache (ArangoDB 3.10) +- deprecated fulltext indexes (ArangoDB 3.10, #454) +- fixed `ConsolidationPolicy` API +- deprecated MMFiles collection attributes (#442) +- deprecated for removal `ArangoCursorInitializer` and `GraphDocumentReadOptions#isCatchException()` +- documented thead safe classes (#445) + ## [6.18.0] - 2022-06-07 - deprecated usage of deprecated server API (#440) diff --git a/README.md b/README.md index b3f6600df..843d4e3e1 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ The official [ArangoDB](https://www.arangodb.com/) Java Driver. ## Learn more - [ChangeLog](ChangeLog.md) -- [Examples](src/test/java/com/arangodb/example) -- [Examples Async](src/test/java/com/arangodb/async/example) +- [Examples](driver/src/test/java/com/arangodb/example) +- [Examples Async](driver/src/test/java/com/arangodb/async/example) - [Tutorial](https://www.arangodb.com/docs/stable/drivers/java-tutorial.html) - [Documentation](https://www.arangodb.com/docs/stable/drivers/java.html) - [JavaDoc](http://arangodb.github.io/arangodb-java-driver/) diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 000000000..2ea81eb5c --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,91 @@ + + + 4.0.0 + + com.arangodb + arangodb-java-driver-parent + 7.0.0-ALPHA.2 + + + core + core + Core module for ArangoDB Java Driver + + + com.arangodb.core + + + + + org.slf4j + slf4j-api + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + + + com.google.code.findbugs + jsr305 + 3.0.2 + provided + + + + + + + com.google.code.maven-replacer-plugin + replacer + 1.5.3 + + + generate-sources + + replace + + + + + ${project.basedir}/src/main/java/com/arangodb/PackageVersion.java.in + ${project.build.directory}/generated-sources/replacer/com/arangodb/PackageVersion.java + + + + @project.version@ + ${project.version} + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.3.0 + + + generate-sources + + add-source + + + + ${project.build.directory}/generated-sources/replacer + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/arangodb/ArangoCollection.java b/core/src/main/java/com/arangodb/ArangoCollection.java similarity index 58% rename from src/main/java/com/arangodb/ArangoCollection.java rename to core/src/main/java/com/arangodb/ArangoCollection.java index 40a5cdfd7..79e3daf2c 100644 --- a/src/main/java/com/arangodb/ArangoCollection.java +++ b/core/src/main/java/com/arangodb/ArangoCollection.java @@ -22,7 +22,9 @@ import com.arangodb.entity.*; import com.arangodb.model.*; +import com.arangodb.util.RawData; +import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; /** @@ -34,8 +36,8 @@ * @see Collection API Documentation * @see Documents API Documentation */ -@SuppressWarnings("UnusedReturnValue") -public interface ArangoCollection extends ArangoSerializationAccessor { +@ThreadSafe +public interface ArangoCollection extends ArangoSerdeAccessor { /** * The the handler of the database the collection is within @@ -55,215 +57,284 @@ public interface ArangoCollection extends ArangoSerializationAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData} * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ - DocumentCreateEntity insertDocument(T value) throws ArangoDBException; + DocumentCreateEntity insertDocument(Object value); /** * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) - * @param options Additional options, can be null + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ - DocumentCreateEntity insertDocument(T value, DocumentCreateOptions options) throws ArangoDBException; + DocumentCreateEntity insertDocument(T value, DocumentCreateOptions options); + + /** + * Creates a new document from the given document, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options + * @param type Deserialization target type for the returned documents. + * @return information about the document + * @see API + * Documentation + */ + DocumentCreateEntity insertDocument(T value, DocumentCreateOptions options, Class type); /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * - * @param values A List of documents (POJO, VPackSlice or String for JSON) + * @param values Raw data representing a collection of documents * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ - MultiDocumentEntity> insertDocuments(Collection values) throws ArangoDBException; + MultiDocumentEntity> insertDocuments(RawData values); /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * - * @param values A List of documents (POJO, VPackSlice or String for JSON) - * @param options Additional options, can be null + * @param values Raw data representing a collection of documents + * @param options Additional options + * @return information about the documents + * @see API + * Documentation + */ + MultiDocumentEntity> insertDocuments( + RawData values, DocumentCreateOptions options); + + /** + * Creates new documents from the given documents, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param values A List of documents + * @return information about the documents + * @see API + * Documentation + */ + MultiDocumentEntity> insertDocuments(Collection values); + + /** + * Creates new documents from the given documents, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ MultiDocumentEntity> insertDocuments( - Collection values, DocumentCreateOptions options) throws ArangoDBException; + Collection values, DocumentCreateOptions options); + + /** + * Creates new documents from the given documents, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options + * @param type Deserialization target type for the returned documents. + * @return information about the documents + * @see API + * Documentation + */ + MultiDocumentEntity> insertDocuments( + Collection values, DocumentCreateOptions options, Class type); /** * Bulk imports the given values into the collection. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * - * @param values a list of Objects that will be stored as documents + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @return information about the import - * @throws ArangoDBException */ - DocumentImportEntity importDocuments(Collection values) throws ArangoDBException; + DocumentImportEntity importDocuments(Collection values); /** * Bulk imports the given values into the collection. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * - * @param values a list of Objects that will be stored as documents + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the import - * @throws ArangoDBException */ - DocumentImportEntity importDocuments(Collection values, DocumentImportOptions options) throws ArangoDBException; + DocumentImportEntity importDocuments(Collection values, DocumentImportOptions options); /** * Bulk imports the given values into the collection. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * - * @param values JSON-encoded array of objects that will be stored as documents + * @param values Raw data representing a collection of documents * @return information about the import - * @throws ArangoDBException */ - DocumentImportEntity importDocuments(String values) throws ArangoDBException; + DocumentImportEntity importDocuments(RawData values); /** * Bulk imports the given values into the collection. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * - * @param values JSON-encoded array of objects that will be stored as documents + * @param values Raw data representing a collection of documents * @param options Additional options, can be null * @return information about the import - * @throws ArangoDBException */ - DocumentImportEntity importDocuments(String values, DocumentImportOptions options) throws ArangoDBException; + DocumentImportEntity importDocuments(RawData values, DocumentImportOptions options); /** * Retrieves the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO class, VPackSlice or String for JSON) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @return the document identified by the key - * @throws ArangoDBException * @see API * Documentation */ - T getDocument(String key, Class type) throws ArangoDBException; + T getDocument(String key, Class type); /** * Retrieves the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO class, VPackSlice or String for JSON) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the document identified by the key - * @throws ArangoDBException * @see API * Documentation */ - T getDocument(String key, Class type, DocumentReadOptions options) throws ArangoDBException; + T getDocument(String key, Class type, DocumentReadOptions options); /** * Retrieves multiple documents with the given {@code _key} from the collection. * * @param keys The keys of the documents - * @param type The type of the documents (POJO class, VPackSlice or String for JSON) + * @param type The type of the documents (POJO or {@link com.arangodb.util.RawData}) * @return the documents and possible errors - * @throws ArangoDBException */ - MultiDocumentEntity getDocuments(Collection keys, Class type) throws ArangoDBException; + MultiDocumentEntity getDocuments(Collection keys, Class type); /** * Retrieves multiple documents with the given {@code _key} from the collection. * * @param keys The keys of the documents - * @param type The type of the documents (POJO class, VPackSlice or String for JSON) + * @param type The type of the documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the documents and possible errors - * @throws ArangoDBException */ - MultiDocumentEntity getDocuments(Collection keys, Class type, DocumentReadOptions options) - throws ArangoDBException; + MultiDocumentEntity getDocuments(Collection keys, Class type, DocumentReadOptions options); /** * Replaces the document with {@code key} with the one in the body, provided there is such a document and no * precondition is violated * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @return information about the document - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - DocumentUpdateEntity replaceDocument(String key, T value) throws ArangoDBException; + DocumentUpdateEntity replaceDocument(String key, Object value); /** * Replaces the document with {@code key} with the one in the body, provided there is such a document and no * precondition is violated * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) - * @param options Additional options, can be null + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options + * @return information about the document + * @see + * API + * Documentation + */ + DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options); + + /** + * Replaces the document with {@code key} with the one in the body, provided there is such a document and no + * precondition is violated + * + * @param key The key of the document + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options + * @param type Deserialization target type for the returned documents. * @return information about the document - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options) - throws ArangoDBException; + DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, Class type); /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * - * @param values A List of documents (POJO, VPackSlice or String for JSON) + * @param values Raw data representing a collection of documents * @return information about the documents - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - MultiDocumentEntity> replaceDocuments(Collection values) throws ArangoDBException; + MultiDocumentEntity> replaceDocuments(RawData values); /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. - *

- * Limitations: - * - the fields having {@code null} value are always removed during serialization * - * @param values A List of documents (POJO, VPackSlice or String for JSON) - * @param options Additional options, can be null + * @param values Raw data representing a collection of documents + * @param options Additional options + * @return information about the documents + * @see + * API + * Documentation + */ + MultiDocumentEntity> replaceDocuments( + RawData values, DocumentReplaceOptions options); + + /** + * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are + * specified by the _key attributes in the documents in values. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @return information about the documents - * @throws ArangoDBException - * @see API + * @see + * API + * Documentation + */ + MultiDocumentEntity> replaceDocuments(Collection values); + + /** + * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are + * specified by the _key attributes in the documents in values. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options + * @return information about the documents + * @see + * API * Documentation */ MultiDocumentEntity> replaceDocuments( - Collection values, DocumentReplaceOptions options) throws ArangoDBException; + Collection values, DocumentReplaceOptions options); + + /** + * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are + * specified by the _key attributes in the documents in values. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options + * @param type Deserialization target type for the returned documents. + * @return information about the documents + * @see + * API + * Documentation + */ + MultiDocumentEntity> replaceDocuments( + Collection values, DocumentReplaceOptions options, Class type); /** * Partially updates the document identified by document-key. The value must contain a document with the attributes @@ -271,13 +342,12 @@ MultiDocumentEntity> replaceDocuments( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ - DocumentUpdateEntity updateDocument(String key, T value) throws ArangoDBException; + DocumentUpdateEntity updateDocument(String key, Object value); /** * Partially updates the document identified by document-key. The value must contain a document with the attributes @@ -285,15 +355,13 @@ MultiDocumentEntity> replaceDocuments( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) - * @param options Additional options, can be null + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ - DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOptions options) - throws ArangoDBException; + DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOptions options); /** * Partially updates the document identified by document-key. The value must contain a document with the attributes @@ -301,16 +369,15 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOp * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for JSON) - * @param options Additional options, can be null + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the document - * @throws ArangoDBException * @see API * Documentation */ - DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdateOptions options, Class returnType) - throws ArangoDBException; + DocumentUpdateEntity updateDocument(String key, Object value, DocumentUpdateOptions options, + Class returnType); /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on @@ -318,13 +385,13 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdat * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, VPackSlice or String for JSON) + * @param values Raw data representing a collection of documents * @return information about the documents - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - MultiDocumentEntity> updateDocuments(Collection values) throws ArangoDBException; + MultiDocumentEntity> updateDocuments(RawData values); /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on @@ -332,15 +399,45 @@ DocumentUpdateEntity updateDocument(String key, T value, DocumentUpdat * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, VPackSlice or String for JSON) - * @param options Additional options, can be null + * @param values Raw data representing a collection of documents + * @param options Additional options * @return information about the documents - * @throws ArangoDBException - * @see API + * @see + * API + * Documentation + */ + MultiDocumentEntity> updateDocuments( + RawData values, DocumentUpdateOptions options); + + /** + * Partially updates documents, the documents to update are specified by the _key attributes in the objects on + * values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All + * attributes from the patch documents will be added to the existing documents if they do not yet exist, and + * overwritten in the existing documents if they do exist there. + * + * @param values A list of documents (POJO or {@link com.arangodb.util.RawData}) + * @return information about the documents + * @see + * API + * Documentation + */ + MultiDocumentEntity> updateDocuments(Collection values); + + /** + * Partially updates documents, the documents to update are specified by the _key attributes in the objects on + * values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All + * attributes from the patch documents will be added to the existing documents if they do not yet exist, and + * overwritten in the existing documents if they do exist there. + * + * @param values A list of documents (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options + * @return information about the documents + * @see + * API * Documentation */ MultiDocumentEntity> updateDocuments( - Collection values, DocumentUpdateOptions options) throws ArangoDBException; + Collection values, DocumentUpdateOptions options); /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on @@ -348,70 +445,114 @@ MultiDocumentEntity> updateDocuments( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, VPackSlice or String for JSON) - * @param options Additional options, can be null + * @param values A list of documents (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the documents - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - MultiDocumentEntity> updateDocuments( - Collection values, DocumentUpdateOptions options, Class returnType) throws ArangoDBException; + MultiDocumentEntity> updateDocuments( + Collection values, DocumentUpdateOptions options, Class returnType); /** * Deletes the document with the given {@code key} from the collection. * * @param key The key of the document * @return information about the document - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - DocumentDeleteEntity deleteDocument(String key) throws ArangoDBException; + DocumentDeleteEntity deleteDocument(String key); /** * Deletes the document with the given {@code key} from the collection. * * @param key The key of the document - * @param type The type of the document (POJO class, VPackSlice or String for JSON). Only necessary if - * options.returnOld is set to true, otherwise can be null. - * @param options Additional options, can be null + * @param options Additional options * @return information about the document - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - DocumentDeleteEntity deleteDocument(String key, Class type, DocumentDeleteOptions options) - throws ArangoDBException; + DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options); + + /** + * Deletes the document with the given {@code key} from the collection. + * + * @param key The key of the document + * @param type Deserialization target type for the returned documents. + * @param options Additional options + * @return information about the document + * @see + * API + * Documentation + */ + DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options, Class type); + + /** + * Deletes multiple documents from the collection. + * + * @param values Raw data representing the keys of the documents or the documents themselves + * @return information about the documents + * @see API + * Documentation + */ + MultiDocumentEntity> deleteDocuments(RawData values); + + /** + * Deletes multiple documents from the collection. + * + * @param values Raw data representing the keys of the documents or the documents themselves + * @param options Additional options + * @return information about the documents + * @see API + * Documentation + */ + MultiDocumentEntity> deleteDocuments( + RawData values, DocumentDeleteOptions options); /** * Deletes multiple documents from the collection. * * @param values The keys of the documents or the documents themselves * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ - MultiDocumentEntity> deleteDocuments(Collection values) throws ArangoDBException; + MultiDocumentEntity> deleteDocuments(Collection values); /** * Deletes multiple documents from the collection. * * @param values The keys of the documents or the documents themselves - * @param type The type of the documents (POJO class, VPackSlice or String for JSON). Only necessary if - * options.returnOld is set to true, otherwise can be null. - * @param options Additional options, can be null + * @param options Additional options * @return information about the documents - * @throws ArangoDBException * @see API * Documentation */ MultiDocumentEntity> deleteDocuments( - Collection values, Class type, DocumentDeleteOptions options) throws ArangoDBException; + Collection values, DocumentDeleteOptions options); + + /** + * Deletes multiple documents from the collection. + * + * @param values The keys of the documents or the documents themselves + * @param type Deserialization target type for the returned documents. + * @param options Additional options + * @return information about the documents + * @see API + * Documentation + */ + MultiDocumentEntity> deleteDocuments( + Collection values, DocumentDeleteOptions options, Class type); /** * Checks if the document exists by reading a single document head @@ -430,32 +571,44 @@ MultiDocumentEntity> deleteDocuments( * @param key The key of the document * @param options Additional options, can be null * @return true if the document was found, otherwise false - * @throws ArangoDBException only thrown when {@link DocumentExistsOptions#isCatchException()} == false * @see API * Documentation */ - Boolean documentExists(String key, DocumentExistsOptions options) throws ArangoDBException; + Boolean documentExists(String key, DocumentExistsOptions options); /** * Fetches information about the index with the given {@code id} and returns it. + *
+ * Note: inverted indexes are not returned by this method. Use + * {@link ArangoCollection#getInvertedIndex(String)} instead. + * + * @param id The index-handle + * @return information about the index + * @see + * API Documentation + */ + IndexEntity getIndex(String id); + + /** + * Fetches information about the inverted index with the given {@code id} and returns it. * * @param id The index-handle * @return information about the index - * @throws ArangoDBException * @see API Documentation + * @since ArangoDB 3.10 */ - IndexEntity getIndex(String id) throws ArangoDBException; + InvertedIndexEntity getInvertedIndex(String id); /** * Deletes the index with the given {@code id} from the collection. * * @param id The index-handle * @return the id of the index - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation */ - String deleteIndex(String id) throws ArangoDBException; + String deleteIndex(String id); /** * Creates a hash index for the collection if it does not already exist. @@ -463,13 +616,13 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation * @deprecated use {@link #ensurePersistentIndex(Iterable, PersistentIndexOptions)} instead. Since ArangoDB 3.7 a * hash index is an alias for a persistent index. */ @Deprecated - IndexEntity ensureHashIndex(Iterable fields, HashIndexOptions options) throws ArangoDBException; + IndexEntity ensureHashIndex(Iterable fields, HashIndexOptions options); /** * Creates a skip-list index for the collection, if it does not already exist. @@ -477,14 +630,13 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException * @see API * Documentation * @deprecated use {@link #ensurePersistentIndex(Iterable, PersistentIndexOptions)} instead. Since ArangoDB 3.7 a * skiplist index is an alias for a persistent index. */ @Deprecated - IndexEntity ensureSkiplistIndex(Iterable fields, SkiplistIndexOptions options) throws ArangoDBException; + IndexEntity ensureSkiplistIndex(Iterable fields, SkiplistIndexOptions options); /** * Creates a persistent index for the collection, if it does not already exist. @@ -492,11 +644,10 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException * @see API * Documentation */ - IndexEntity ensurePersistentIndex(Iterable fields, PersistentIndexOptions options) throws ArangoDBException; + IndexEntity ensurePersistentIndex(Iterable fields, PersistentIndexOptions options); /** * Creates a geo-spatial index for the collection, if it does not already exist. @@ -504,11 +655,10 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException * @see API * Documentation */ - IndexEntity ensureGeoIndex(Iterable fields, GeoIndexOptions options) throws ArangoDBException; + IndexEntity ensureGeoIndex(Iterable fields, GeoIndexOptions options); /** * Creates a fulltext index for the collection, if it does not already exist. @@ -516,11 +666,12 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException * @see API * Documentation + * @deprecated since ArangoDB 3.10, use ArangoSearch or Inverted indexes instead. */ - IndexEntity ensureFulltextIndex(Iterable fields, FulltextIndexOptions options) throws ArangoDBException; + @Deprecated + IndexEntity ensureFulltextIndex(Iterable fields, FulltextIndexOptions options); /** * Creates a ttl index for the collection, if it does not already exist. @@ -528,11 +679,10 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException * @see API * Documentation */ - IndexEntity ensureTtlIndex(Iterable fields, TtlIndexOptions options) throws ArangoDBException; + IndexEntity ensureTtlIndex(Iterable fields, TtlIndexOptions options); /** * Creates a ZKD multi-dimensional index for the collection, if it does not already exist. @@ -541,85 +691,104 @@ MultiDocumentEntity> deleteDocuments( * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.9 */ - IndexEntity ensureZKDIndex(Iterable fields, ZKDIndexOptions options) throws ArangoDBException; + IndexEntity ensureZKDIndex(Iterable fields, ZKDIndexOptions options); + + /** + * Creates an inverted index for the collection, if it does not already exist. + * + * @param options index creation options + * @return information about the index + * @see API Documentation + * @since ArangoDB 3.10 + */ + InvertedIndexEntity ensureInvertedIndex(InvertedIndexOptions options); /** * Fetches a list of all indexes on this collection. + *
+ * Note: inverted indexes are not returned by this method. Use + * {@link ArangoCollection#getInvertedIndexes()} instead. + * + * @return information about the indexes + * @see API + * Documentation + */ + Collection getIndexes(); + + /** + * Fetches a list of all inverted indexes on this collection. * * @return information about the indexes - * @throws ArangoDBException * @see API * Documentation + * @since ArangoDB 3.10 */ - Collection getIndexes() throws ArangoDBException; + Collection getInvertedIndexes(); /** * Checks whether the collection exists * * @return true if the collection exists, otherwise false */ - boolean exists() throws ArangoDBException; + boolean exists(); /** * Removes all documents from the collection, but leaves the indexes intact * * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity truncate() throws ArangoDBException; + CollectionEntity truncate(); /** * Removes all documents from the collection, but leaves the indexes intact * * @param options * @return information about the collection - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.5.0 */ - CollectionEntity truncate(CollectionTruncateOptions options) throws ArangoDBException; + CollectionEntity truncate(CollectionTruncateOptions options); /** * Counts the documents in a collection * * @return information about the collection, including the number of documents - * @throws ArangoDBException * @see API + * "https://www.arangodb.com/docs/stable/http/collection-getting + * .html#return-number-of-documents-in-a-collection">API * Documentation */ - CollectionPropertiesEntity count() throws ArangoDBException; + CollectionPropertiesEntity count(); /** * Counts the documents in a collection * * @param options * @return information about the collection, including the number of documents - * @throws ArangoDBException * @see API + * "https://www.arangodb.com/docs/stable/http/collection-getting + * .html#return-number-of-documents-in-a-collection">API * Documentation * @since ArangoDB 3.5.0 */ - CollectionPropertiesEntity count(CollectionCountOptions options) throws ArangoDBException; + CollectionPropertiesEntity count(CollectionCountOptions options); /** * Creates a collection for this collection's name, then returns collection information from the server. * * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity create() throws ArangoDBException; + CollectionEntity create(); /** * Creates a collection with the given {@code options} for this collection's name, then returns collection @@ -627,102 +796,71 @@ MultiDocumentEntity> deleteDocuments( * * @param options Additional options, can be null * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity create(CollectionCreateOptions options) throws ArangoDBException; + CollectionEntity create(CollectionCreateOptions options); /** * Deletes the collection from the database. * - * @throws ArangoDBException * @see API * Documentation */ - void drop() throws ArangoDBException; + void drop(); /** * Deletes the collection from the database. * - * @param isSystem Whether or not the collection to drop is a system collection. This parameter must be set to true in + * @param isSystem Whether or not the collection to drop is a system collection. This parameter must be set to + * true in * order to drop a system collection. - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.1.0 */ - void drop(boolean isSystem) throws ArangoDBException; - - /** - * Tells the server to load the collection into memory. - * - * @return information about the collection - * @throws ArangoDBException - * @see API - * Documentation - * @deprecated MMFiles only - */ - @Deprecated - CollectionEntity load() throws ArangoDBException; - - /** - * Tells the server to remove the collection from memory. This call does not delete any documents. You can use the - * collection afterwards; in which case it will be loaded into memory, again. - * - * @return information about the collection - * @throws ArangoDBException - * @see API - * Documentation - * @deprecated MMFiles only - */ - @Deprecated - CollectionEntity unload() throws ArangoDBException; + void drop(boolean isSystem); /** * Returns information about the collection * * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity getInfo() throws ArangoDBException; + CollectionEntity getInfo(); /** * Reads the properties of the specified collection * * @return properties of the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionPropertiesEntity getProperties() throws ArangoDBException; + CollectionPropertiesEntity getProperties(); /** * Changes the properties of the collection * * @param options Additional options, can be null * @return properties of the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionPropertiesEntity changeProperties(CollectionPropertiesOptions options) throws ArangoDBException; + CollectionPropertiesEntity changeProperties(CollectionPropertiesOptions options); /** * Renames the collection * * @param newName The new name * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity rename(String newName) throws ArangoDBException; + CollectionEntity rename(String newName); /** * Returns the responsible shard for the document. @@ -731,8 +869,8 @@ MultiDocumentEntity> deleteDocuments( * @param value A projection of the document containing at least the shard key (_key or a custom attribute) for * which the responsible shard should be determined * @return information about the responsible shard - * @throws ArangoDBException - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ @@ -742,11 +880,11 @@ MultiDocumentEntity> deleteDocuments( * Retrieve the collections revision * * @return information about the collection, including the collections revision - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - CollectionRevisionEntity getRevision() throws ArangoDBException; + CollectionRevisionEntity getRevision(); /** * Grants or revoke access to the collection for user user. You need permission to the _system database in order to @@ -754,47 +892,44 @@ MultiDocumentEntity> deleteDocuments( * * @param user The name of the user * @param permissions The permissions the user grant - * @throws ArangoDBException * @see API * Documentation */ - void grantAccess(String user, Permissions permissions) throws ArangoDBException; + void grantAccess(String user, Permissions permissions); /** * Revokes access to the collection for user user. You need permission to the _system database in order to execute * this call. * * @param user The name of the user - * @throws ArangoDBException * @see API * Documentation */ - void revokeAccess(String user) throws ArangoDBException; + void revokeAccess(String user); /** * Clear the collection access level, revert back to the default access level. * * @param user The name of the user - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.2.0 */ - void resetAccess(String user) throws ArangoDBException; + void resetAccess(String user); /** * Get the collection access level * * @param user The name of the user * @return permissions of the user - * @throws ArangoDBException - * @see + * @see + * * API Documentation * @since ArangoDB 3.2.0 */ - Permissions getPermissions(String user) throws ArangoDBException; + Permissions getPermissions(String user); } diff --git a/src/main/java/com/arangodb/ArangoCursor.java b/core/src/main/java/com/arangodb/ArangoCursor.java similarity index 86% rename from src/main/java/com/arangodb/ArangoCursor.java rename to core/src/main/java/com/arangodb/ArangoCursor.java index eab1e2a88..259b81d73 100644 --- a/src/main/java/com/arangodb/ArangoCursor.java +++ b/core/src/main/java/com/arangodb/ArangoCursor.java @@ -20,8 +20,8 @@ package com.arangodb; -import com.arangodb.entity.CursorEntity.Stats; -import com.arangodb.entity.CursorEntity.Warning; +import com.arangodb.entity.CursorStats; +import com.arangodb.entity.CursorWarning; import java.io.Closeable; import java.util.Collection; @@ -53,12 +53,12 @@ public interface ArangoCursor extends ArangoIterable, ArangoIterator, C * number of modified documents and the number of documents that could not be modified due to an error (if * ignoreErrors query option is specified) */ - Stats getStats(); + CursorStats getStats(); /** * @return warnings which the query could have been produced */ - Collection getWarnings(); + Collection getWarnings(); /** * @return indicating whether the query result was served from the query cache or not @@ -70,4 +70,10 @@ public interface ArangoCursor extends ArangoIterable, ArangoIterator, C */ List asListRemaining(); + /** + * @return true if the result is a potential dirty read + * @since ArangoDB 3.10 + */ + boolean isPotentialDirtyRead(); + } diff --git a/core/src/main/java/com/arangodb/ArangoDB.java b/core/src/main/java/com/arangodb/ArangoDB.java new file mode 100644 index 000000000..1a22d50c3 --- /dev/null +++ b/core/src/main/java/com/arangodb/ArangoDB.java @@ -0,0 +1,357 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.*; +import com.arangodb.internal.ArangoDBImpl; +import com.arangodb.internal.InternalArangoDBBuilder; +import com.arangodb.internal.net.*; +import com.arangodb.model.DBCreateOptions; +import com.arangodb.model.LogOptions; +import com.arangodb.model.UserCreateOptions; +import com.arangodb.model.UserUpdateOptions; + +import javax.annotation.concurrent.ThreadSafe; +import java.util.Collection; + +/** + * Central access point for applications to communicate with an ArangoDB server. + * + *

+ * Will be instantiated through {@link ArangoDB.Builder} + *

+ * + *
+ * ArangoDB arango = new ArangoDB.Builder().build();
+ * ArangoDB arango = new ArangoDB.Builder().host("127.0.0.1", 8529).build();
+ * 
+ * + * @author Mark Vollmary + * @author Michele Rastelli + */ +@ThreadSafe +public interface ArangoDB extends ArangoSerdeAccessor { + + /** + * Releases all connections to the server and clear the connection pool. + */ + void shutdown(); + + /** + * Updates the JWT used for requests authorization. It does not change already existing VST connections, since VST + * connections are authenticated during the initialization phase. + * + * @param jwt token to use + */ + void updateJwt(String jwt); + + /** + * Returns a {@code ArangoDatabase} instance for the {@code _system} database. + * + * @return database handler + */ + ArangoDatabase db(); + + /** + * Returns a {@code ArangoDatabase} instance for the given database name. + * + * @param dbName Name of the database + * @return database handler + */ + ArangoDatabase db(DbName dbName); + + /** + * @return entry point for accessing client metrics + */ + ArangoMetrics metrics(); + + /** + * Creates a new database with the given name. + * + * @param dbName Name of the database to create + * @return true if the database was created successfully. + * @see API + * Documentation + */ + Boolean createDatabase(DbName dbName); + + /** + * Creates a new database with the given name. + * + * @param options Creation options + * @return true if the database was created successfully. + * @see API + * Documentation + * @since ArangoDB 3.6.0 + */ + Boolean createDatabase(DBCreateOptions options); + + /** + * Retrieves a list of all existing databases + * + * @return a list of all existing databases + * @see API + * Documentation + */ + Collection getDatabases(); + + /** + * Retrieves a list of all databases the current user can access + * + * @return a list of all databases the current user can access + * @see API + * Documentation + */ + Collection getAccessibleDatabases(); + + /** + * List available database to the specified user + * + * @param user The name of the user for which you want to query the databases + * @return list of database names which are available for the specified user + * @see API + * Documentation + */ + Collection getAccessibleDatabasesFor(String user); + + /** + * Returns the server name and version number. + * + * @return the server version, number + * @see API + * Documentation + */ + ArangoDBVersion getVersion(); + + /** + * Returns the server storage engine. + * + * @return the storage engine name + * @see API + * Documentation + */ + ArangoDBEngine getEngine(); + + /** + * Returns the server role. + * + * @return the server role + */ + ServerRole getRole(); + + /** + * Returns the id of a server in a cluster. + * + * @return the server id + * @see API + * Documentation + */ + String getServerId(); + + /** + * Create a new user. This user will not have access to any database. You need permission to the _system database in + * order to execute this call. + * + * @param user The name of the user + * @param passwd The user password + * @return information about the user + * @see API Documentation + */ + UserEntity createUser(String user, String passwd); + + /** + * Create a new user. This user will not have access to any database. You need permission to the _system database in + * order to execute this call. + * + * @param user The name of the user + * @param passwd The user password + * @param options Additional options, can be null + * @return information about the user + * @see API Documentation + */ + UserEntity createUser(String user, String passwd, UserCreateOptions options); + + /** + * Removes an existing user, identified by user. You need access to the _system database. + * + * @param user The name of the user + * @see API Documentation + */ + void deleteUser(String user); + + /** + * Fetches data about the specified user. You can fetch information about yourself or you need permission to the + * _system database in order to execute this call. + * + * @param user The name of the user + * @return information about the user + * @see API Documentation + */ + UserEntity getUser(String user); + + /** + * Fetches data about all users. You can only execute this call if you have access to the _system database. + * + * @return informations about all users + * @see API + * Documentation + */ + Collection getUsers(); + + /** + * Partially updates the data of an existing user. The name of an existing user must be specified in user. You can + * only change the password of your self. You need access to the _system database to change the active flag. + * + * @param user The name of the user + * @param options Properties of the user to be changed + * @return information about the user + * @see API Documentation + */ + UserEntity updateUser(String user, UserUpdateOptions options); + + /** + * Replaces the data of an existing user. The name of an existing user must be specified in user. You can only + * change the password of your self. You need access to the _system database to change the active flag. + * + * @param user The name of the user + * @param options Additional properties of the user, can be null + * @return information about the user + * @see API + * Documentation + */ + UserEntity replaceUser(String user, UserUpdateOptions options); + + /** + * Sets the default access level for databases for the user {@code user}. You need permission to the _system + * database in order to execute this call. + * + * @param user The name of the user + * @param permissions The permissions the user grant + * @since ArangoDB 3.2.0 + */ + void grantDefaultDatabaseAccess(String user, Permissions permissions); + + /** + * Sets the default access level for collections for the user {@code user}. You need permission to the _system + * database in order to execute this call. + * + * @param user The name of the user + * @param permissions The permissions the user grant + * @since ArangoDB 3.2.0 + */ + void grantDefaultCollectionAccess(String user, Permissions permissions); + + /** + * Execute custom requests. Requests can be programmatically built by setting low level detail such as method, path, + * query parameters, headers and body payload. + * This method can be used to call FOXX services, API endpoints not (yet) implemented in this driver or trigger + * async jobs, see + * Fire and Forget + * and + * Async Execution and later Result Retrieval + * + * @param request request + * @param type Deserialization target type for the response body (POJO or {@link com.arangodb.util.RawData}) + * @return response + */ + Response execute(Request request, Class type); + + /** + * Returns the server logs + * + * @param options Additional options, can be null + * @return the log messages + * @see API + * Documentation + * @since ArangoDB 3.8 + */ + LogEntriesEntity getLogEntries(LogOptions options); + + /** + * Returns the server's current loglevel settings. + * + * @return the server's current loglevel settings + * @since ArangoDB 3.1.0 + */ + LogLevelEntity getLogLevel(); + + /** + * Modifies and returns the server's current loglevel settings. + * + * @param entity loglevel settings + * @return the server's current loglevel settings + * @since ArangoDB 3.1.0 + */ + LogLevelEntity setLogLevel(LogLevelEntity entity); + + /** + * @return the list of available rules and their respective flags + * @since ArangoDB 3.10 + */ + Collection getQueryOptimizerRules(); + + /** + * Builder class to build an instance of {@link ArangoDB}. + * + * @author Mark Vollmary + */ + class Builder extends InternalArangoDBBuilder { + + public Builder useProtocol(final Protocol protocol) { + config.setProtocol(protocol); + return this; + } + + /** + * Returns an instance of {@link ArangoDB}. + * + * @return {@link ArangoDB} + */ + public ArangoDB build() { + if (config.getHosts().isEmpty()) { + throw new ArangoDBException("No host has been set!"); + } + + ProtocolProvider protocolProvider = protocolProvider(config.getProtocol()); + config.setProtocolModule(protocolProvider.protocolModule()); + + ConnectionFactory connectionFactory = protocolProvider.createConnectionFactory(); + Collection hostList = createHostList(connectionFactory); + HostResolver hostResolver = createHostResolver(hostList, connectionFactory); + HostHandler hostHandler = createHostHandler(hostResolver); + hostHandler.setJwt(config.getJwt()); + + return new ArangoDBImpl( + config, + hostResolver, + protocolProvider, + hostHandler + ); + } + + } + +} diff --git a/src/main/java/com/arangodb/ArangoDBException.java b/core/src/main/java/com/arangodb/ArangoDBException.java similarity index 78% rename from src/main/java/com/arangodb/ArangoDBException.java rename to core/src/main/java/com/arangodb/ArangoDBException.java index 6ea9ce8c8..ab6d63610 100644 --- a/src/main/java/com/arangodb/ArangoDBException.java +++ b/core/src/main/java/com/arangodb/ArangoDBException.java @@ -30,36 +30,57 @@ public class ArangoDBException extends RuntimeException { private static final long serialVersionUID = 6165638002614173801L; private final ErrorEntity entity; private final Integer responseCode; + private final Long requestId; public ArangoDBException(final ErrorEntity errorEntity) { super(String.format("Response: %s, Error: %s - %s", errorEntity.getCode(), errorEntity.getErrorNum(), errorEntity.getErrorMessage())); this.entity = errorEntity; this.responseCode = null; + this.requestId = null; } public ArangoDBException(final String message) { super(message); this.entity = null; this.responseCode = null; + this.requestId = null; } public ArangoDBException(final String message, final Integer responseCode) { super(message); this.entity = null; this.responseCode = responseCode; + this.requestId = null; } public ArangoDBException(final Throwable cause) { super(cause); this.entity = null; this.responseCode = null; + this.requestId = null; } public ArangoDBException(final String message, final Throwable cause) { super(message, cause); this.entity = null; this.responseCode = null; + this.requestId = null; + } + + public ArangoDBException(Throwable cause, long requestId) { + super(cause); + this.entity = null; + this.responseCode = null; + this.requestId = requestId; + } + + public static ArangoDBException wrap(Throwable t) { + if (t instanceof ArangoDBException) { + return (ArangoDBException) t; + } else { + return new ArangoDBException(t); + } } /** @@ -91,4 +112,10 @@ public Integer getErrorNum() { return entity != null ? entity.getErrorNum() : null; } + /** + * @return request id + */ + public Long getRequestId() { + return requestId; + } } diff --git a/src/main/java/com/arangodb/ArangoDBMultipleException.java b/core/src/main/java/com/arangodb/ArangoDBMultipleException.java similarity index 100% rename from src/main/java/com/arangodb/ArangoDBMultipleException.java rename to core/src/main/java/com/arangodb/ArangoDBMultipleException.java diff --git a/src/main/java/com/arangodb/ArangoDatabase.java b/core/src/main/java/com/arangodb/ArangoDatabase.java similarity index 63% rename from src/main/java/com/arangodb/ArangoDatabase.java rename to core/src/main/java/com/arangodb/ArangoDatabase.java index f0cfede5f..1ef5e1de1 100644 --- a/src/main/java/com/arangodb/ArangoDatabase.java +++ b/core/src/main/java/com/arangodb/ArangoDatabase.java @@ -21,12 +21,13 @@ package com.arangodb; import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.AnalyzerEntity; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; +import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; import java.util.Map; @@ -38,8 +39,8 @@ * @see Databases API Documentation * @see Query API Documentation */ -@SuppressWarnings("UnusedReturnValue") -public interface ArangoDatabase extends ArangoSerializationAccessor { +@ThreadSafe +public interface ArangoDatabase extends ArangoSerdeAccessor { /** * Return the main entry point for the ArangoDB driver @@ -48,17 +49,6 @@ public interface ArangoDatabase extends ArangoSerializationAccessor { */ ArangoDB arango(); - /** - * Returns the name of the database - * - * @return database name - * @deprecated Use {@link #dbName()} instead - */ - @Deprecated - default String name() { - return dbName().get(); - } - /** * Returns the name of the database * @@ -70,39 +60,37 @@ default String name() { * Returns the server name and version number. * * @return the server version, number - * @throws ArangoDBException * @see API * Documentation */ - ArangoDBVersion getVersion() throws ArangoDBException; + ArangoDBVersion getVersion(); /** * Returns the name of the used storage engine. * * @return the storage engine name - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - ArangoDBEngine getEngine() throws ArangoDBException; + ArangoDBEngine getEngine(); /** * Checks whether the database exists * * @return true if the database exists, otherwise false */ - boolean exists() throws ArangoDBException; + boolean exists(); /** * Retrieves a list of all databases the current user can access * * @return a list of all databases the current user can access - * @throws ArangoDBException * @see API * Documentation */ - Collection getAccessibleDatabases() throws ArangoDBException; + Collection getAccessibleDatabases(); /** * Returns a {@code ArangoCollection} instance for the given collection name. @@ -117,11 +105,10 @@ default String name() { * * @param name The name of the collection * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity createCollection(String name) throws ArangoDBException; + CollectionEntity createCollection(String name); /** * Creates a collection with the given {@code options} for this collection's name, then returns collection @@ -130,72 +117,67 @@ default String name() { * @param name The name of the collection * @param options Additional options, can be null * @return information about the collection - * @throws ArangoDBException * @see API * Documentation */ - CollectionEntity createCollection(String name, CollectionCreateOptions options) throws ArangoDBException; + CollectionEntity createCollection(String name, CollectionCreateOptions options); /** * Fetches all collections from the database and returns an list of collection descriptions. * * @return list of information about all collections - * @throws ArangoDBException * @see API * Documentation */ - Collection getCollections() throws ArangoDBException; + Collection getCollections(); /** * Fetches all collections from the database and returns an list of collection descriptions. * * @param options Additional options, can be null * @return list of information about all collections - * @throws ArangoDBException * @see API * Documentation */ - Collection getCollections(CollectionsReadOptions options) throws ArangoDBException; + Collection getCollections(CollectionsReadOptions options); /** * Returns an index * * @param id The index-handle * @return information about the index - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation */ - IndexEntity getIndex(String id) throws ArangoDBException; + IndexEntity getIndex(String id); /** * Deletes an index * * @param id The index-handle * @return the id of the index - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation */ - String deleteIndex(String id) throws ArangoDBException; + String deleteIndex(String id); /** * Creates the database * * @return true if the database was created successfully. - * @throws ArangoDBException * @see API * Documentation */ - Boolean create() throws ArangoDBException; + Boolean create(); /** * Deletes the database from the server. * * @return true if the database was dropped successfully - * @throws ArangoDBException * @see API * Documentation */ - Boolean drop() throws ArangoDBException; + Boolean drop(); /** * Grants or revoke access to the database for user {@code user}. You need permission to the _system database in @@ -203,44 +185,40 @@ default String name() { * * @param user The name of the user * @param permissions The permissions the user grant - * @throws ArangoDBException * @see * API Documentation */ - void grantAccess(String user, Permissions permissions) throws ArangoDBException; + void grantAccess(String user, Permissions permissions); /** * Grants access to the database for user {@code user}. You need permission to the _system database in order to * execute this call. * * @param user The name of the user - * @throws ArangoDBException * @see * API Documentation */ - void grantAccess(String user) throws ArangoDBException; + void grantAccess(String user); /** * Revokes access to the database dbname for user {@code user}. You need permission to the _system database in order * to execute this call. * * @param user The name of the user - * @throws ArangoDBException * @see * API Documentation */ - void revokeAccess(String user) throws ArangoDBException; + void revokeAccess(String user); /** * Clear the database access level, revert back to the default access level. * * @param user The name of the user - * @throws ArangoDBException * @see * API Documentation * @since ArangoDB 3.2.0 */ - void resetAccess(String user) throws ArangoDBException; + void resetAccess(String user); /** * Sets the default access level for collections within this database for the user {@code user}. You need permission @@ -248,22 +226,20 @@ default String name() { * * @param user The name of the user * @param permissions The permissions the user grant - * @throws ArangoDBException * @since ArangoDB 3.2.0 */ - void grantDefaultCollectionAccess(String user, Permissions permissions) throws ArangoDBException; + void grantDefaultCollectionAccess(String user, Permissions permissions); /** * Get specific database access level * * @param user The name of the user * @return permissions of the user - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.2.0 */ - Permissions getPermissions(String user) throws ArangoDBException; + Permissions getPermissions(String user); /** * Performs a database query using the given {@code query} and {@code bindVars}, then returns a new @@ -272,14 +248,13 @@ default String name() { * @param query An AQL query string * @param bindVars key/value pairs defining the variables to bind the query to * @param options Additional options that will be passed to the query API, can be null - * @param type The type of the result (POJO class, VPackSlice, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - ArangoCursor query(String query, Map bindVars, AqlQueryOptions options, Class type) - throws ArangoDBException; + ArangoCursor query(String query, Map bindVars, AqlQueryOptions options, Class type); /** * Performs a database query using the given {@code query}, then returns a new {@code ArangoCursor} instance for the @@ -287,13 +262,13 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * * @param query An AQL query string * @param options Additional options that will be passed to the query API, can be null - * @param type The type of the result (POJO class, VPackSlice, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - ArangoCursor query(String query, AqlQueryOptions options, Class type) throws ArangoDBException; + ArangoCursor query(String query, AqlQueryOptions options, Class type); /** * Performs a database query using the given {@code query} and {@code bindVars}, then returns a new @@ -301,39 +276,39 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * * @param query An AQL query string * @param bindVars key/value pairs defining the variables to bind the query to - * @param type The type of the result (POJO class, VPackSlice, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - ArangoCursor query(String query, Map bindVars, Class type) throws ArangoDBException; + ArangoCursor query(String query, Map bindVars, Class type); /** * Performs a database query using the given {@code query}, then returns a new {@code ArangoCursor} instance for the * result list. * * @param query An AQL query string - * @param type The type of the result (POJO class, VPackSlice, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - ArangoCursor query(String query, Class type) throws ArangoDBException; + ArangoCursor query(String query, Class type); /** * Return an cursor from the given cursor-ID if still existing * * @param cursorId The ID of the cursor - * @param type The type of the result (POJO class, VPackSlice, String for JSON, or Collection/List/Map) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results - * @throws ArangoDBException * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cursor-accessing-cursors + * .html#read-next-batch-from-cursor">API * Documentation */ - ArangoCursor cursor(String cursorId, Class type) throws ArangoDBException; + ArangoCursor cursor(String cursorId, Class type); /** * Explain an AQL query and return information about it @@ -342,12 +317,10 @@ ArangoCursor query(String query, Map bindVars, AqlQueryOp * @param bindVars key/value pairs representing the bind parameters * @param options Additional options, can be null * @return information about the query - * @throws ArangoDBException * @see API * Documentation */ - AqlExecutionExplainEntity explainQuery(String query, Map bindVars, AqlQueryExplainOptions options) - throws ArangoDBException; + AqlExecutionExplainEntity explainQuery(String query, Map bindVars, AqlQueryExplainOptions options); /** * Parse an AQL query and return information about it This method is for query validation only. To actually query @@ -355,32 +328,31 @@ AqlExecutionExplainEntity explainQuery(String query, Map bindVar * * @param query the query which you want parse * @return imformation about the query - * @throws ArangoDBException * @see API * Documentation */ - AqlParseEntity parseQuery(String query) throws ArangoDBException; + AqlParseEntity parseQuery(String query); /** * Clears the AQL query cache * - * @throws ArangoDBException * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cache + * .html#clears-any-results-in-the-aql-query-results-cache">API * Documentation */ - void clearQueryCache() throws ArangoDBException; + void clearQueryCache(); /** * Returns the global configuration for the AQL query cache * * @return configuration for the AQL query cache - * @throws ArangoDBException * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cache + * .html#returns-the-global-properties-for-the-aql-query-results-cache">API * Documentation */ - QueryCachePropertiesEntity getQueryCacheProperties() throws ArangoDBException; + QueryCachePropertiesEntity getQueryCacheProperties(); /** * Changes the configuration for the AQL query cache. Note: changing the properties may invalidate all results in @@ -388,78 +360,71 @@ AqlExecutionExplainEntity explainQuery(String query, Map bindVar * * @param properties properties to be set * @return current set of properties - * @throws ArangoDBException * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cache + * .html#globally-adjusts-the-aql-query-results-cache-properties">API * Documentation */ - QueryCachePropertiesEntity setQueryCacheProperties(QueryCachePropertiesEntity properties) throws ArangoDBException; + QueryCachePropertiesEntity setQueryCacheProperties(QueryCachePropertiesEntity properties); /** * Returns the configuration for the AQL query tracking * * @return configuration for the AQL query tracking - * @throws ArangoDBException * @see API * Documentation */ - QueryTrackingPropertiesEntity getQueryTrackingProperties() throws ArangoDBException; + QueryTrackingPropertiesEntity getQueryTrackingProperties(); /** * Changes the configuration for the AQL query tracking * * @param properties properties to be set * @return current set of properties - * @throws ArangoDBException * @see API * Documentation */ - QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingPropertiesEntity properties) - throws ArangoDBException; + QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingPropertiesEntity properties); /** * Returns a list of currently running AQL queries * * @return a list of currently running AQL queries - * @throws ArangoDBException * @see API * Documentation */ - Collection getCurrentlyRunningQueries() throws ArangoDBException; + Collection getCurrentlyRunningQueries(); /** * Returns a list of slow running AQL queries * * @return a list of slow running AQL queries - * @throws ArangoDBException * @see API * Documentation */ - Collection getSlowQueries() throws ArangoDBException; + Collection getSlowQueries(); /** * Clears the list of slow AQL queries * - * @throws ArangoDBException * @see API * Documentation */ - void clearSlowQueries() throws ArangoDBException; + void clearSlowQueries(); /** * Kills a running query. The query will be terminated at the next cancelation point. * * @param id The id of the query - * @throws ArangoDBException * @see API * Documentation */ - void killQuery(String id) throws ArangoDBException; + void killQuery(String id); /** * Create a new AQL user function @@ -467,11 +432,10 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * @param name A valid AQL function name, e.g.: `"myfuncs::accounting::calculate_vat"` * @param code A String evaluating to a JavaScript function * @param options Additional options, can be null - * @throws ArangoDBException * @see API * Documentation */ - void createAqlFunction(String name, String code, AqlFunctionCreateOptions options) throws ArangoDBException; + void createAqlFunction(String name, String code, AqlFunctionCreateOptions options); /** * Deletes the AQL user function with the given name from the database. @@ -479,24 +443,22 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * @param name The name of the user function to delete * @param options Additional options, can be null * @return number of deleted functions (since ArangoDB 3.4.0) - * @throws ArangoDBException * @see API * Documentation */ - Integer deleteAqlFunction(String name, AqlFunctionDeleteOptions options) throws ArangoDBException; + Integer deleteAqlFunction(String name, AqlFunctionDeleteOptions options); /** * Gets all reqistered AQL user functions * * @param options Additional options, can be null * @return all reqistered AQL user functions - * @throws ArangoDBException * @see API * Documentation */ - Collection getAqlFunctions(AqlFunctionGetOptions options) throws ArangoDBException; + Collection getAqlFunctions(AqlFunctionGetOptions options); /** * Returns a {@code ArangoGraph} instance for the given graph name. @@ -513,11 +475,10 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * @param name Name of the graph * @param edgeDefinitions An array of definitions for the edge * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity createGraph(String name, Collection edgeDefinitions) throws ArangoDBException; + GraphEntity createGraph(String name, Collection edgeDefinitions); /** * Create a new graph in the graph module. The creation of a graph requires the name of the graph and a definition @@ -527,171 +488,139 @@ QueryTrackingPropertiesEntity setQueryTrackingProperties(QueryTrackingProperties * @param edgeDefinitions An array of definitions for the edge * @param options Additional options, can be null * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity createGraph(String name, Collection edgeDefinitions, GraphCreateOptions options) - throws ArangoDBException; + GraphEntity createGraph(String name, Collection edgeDefinitions, GraphCreateOptions options); /** * Lists all graphs known to the graph module * * @return graphs stored in this database - * @throws ArangoDBException * @see API * Documentation */ - Collection getGraphs() throws ArangoDBException; + Collection getGraphs(); /** * Performs a server-side transaction and returns its return value. * * @param action A String evaluating to a JavaScript function to be executed on the server. - * @param type The type of the result (POJO class, VPackSlice or String for JSON) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the result of the transaction if it succeeded - * @throws ArangoDBException * @see API * Documentation */ - T transaction(String action, Class type, TransactionOptions options) throws ArangoDBException; + T transaction(String action, Class type, TransactionOptions options); /** * Begins a Stream Transaction. * * @param options Additional options, can be null * @return information about the transaction - * @throws ArangoDBException - * @see API + * @see + * API * Documentation * @since ArangoDB 3.5.0 */ - StreamTransactionEntity beginStreamTransaction(StreamTransactionOptions options) throws ArangoDBException; + StreamTransactionEntity beginStreamTransaction(StreamTransactionOptions options); /** * Aborts a Stream Transaction. * * @return information about the transaction - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - StreamTransactionEntity abortStreamTransaction(String id) throws ArangoDBException; + StreamTransactionEntity abortStreamTransaction(String id); /** * Gets information about a Stream Transaction. * * @return information about the transaction - * @throws ArangoDBException - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ - StreamTransactionEntity getStreamTransaction(String id) throws ArangoDBException; + StreamTransactionEntity getStreamTransaction(String id); /** * Gets all the currently running Stream Transactions. * * @return all the currently running Stream Transactions - * @throws ArangoDBException - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ - Collection getStreamTransactions() throws ArangoDBException; + Collection getStreamTransactions(); /** * Commits a Stream Transaction. * * @return information about the transaction - * @throws ArangoDBException - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ - StreamTransactionEntity commitStreamTransaction(String id) throws ArangoDBException; + StreamTransactionEntity commitStreamTransaction(String id); /** * Retrieves information about the current database * * @return information about the current database - * @throws ArangoDBException * @see API * Documentation */ - DatabaseEntity getInfo() throws ArangoDBException; - - /** - * Execute a server-side traversal - * - * @param vertexClass The type of the vertex documents (POJO class, VPackSlice or String for JSON) - * @param edgeClass The type of the edge documents (POJO class, VPackSlice or String for JSON) - * @param options Additional options - * @return Result of the executed traversal - * @throws ArangoDBException - * @see API - * Documentation - * @deprecated use {@link this#query(String, Map, AqlQueryOptions, Class)} - */ - @Deprecated - TraversalEntity executeTraversal(Class vertexClass, Class edgeClass, TraversalOptions options) - throws ArangoDBException; + DatabaseEntity getInfo(); /** * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO class, VPackSlice or String for JSON) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @return the document identified by the id - * @throws ArangoDBException * @see API * Documentation */ - T getDocument(String id, Class type) throws ArangoDBException; + T getDocument(String id, Class type); /** * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO class, VPackSlice or String for JSON) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the document identified by the id - * @throws ArangoDBException * @see API * Documentation */ - T getDocument(String id, Class type, DocumentReadOptions options) throws ArangoDBException; + T getDocument(String id, Class type, DocumentReadOptions options); /** * Reload the routing table. * - * @throws ArangoDBException * @see API + * "https://www.arangodb.com/docs/stable/http/administration-and-monitoring + * .html#reloads-the-routing-information">API * Documentation */ - void reloadRouting() throws ArangoDBException; - - /** - * Returns a new {@link ArangoRoute} instance for the given path (relative to the database) that can be used to - * perform arbitrary requests. - * - * @param path The database-relative URL of the route - * @return {@link ArangoRoute} - */ - ArangoRoute route(String... path); + void reloadRouting(); /** * Fetches all views from the database and returns an list of view descriptions. * * @return list of information about all views - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation * @since ArangoDB 3.4.0 */ - Collection getViews() throws ArangoDBException; + Collection getViews(); /** * Returns a {@code ArangoView} instance for the given view name. @@ -703,7 +632,7 @@ TraversalEntity executeTraversal(Class vertexClass, Class edg ArangoView view(String name); /** - * Returns a {@code ArangoSearch} instance for the given ArangoSearch view name. + * Returns a {@link ArangoSearch} instance for the given view name. * * @param name Name of the view * @return ArangoSearch view handler @@ -711,16 +640,24 @@ TraversalEntity executeTraversal(Class vertexClass, Class edg */ ArangoSearch arangoSearch(String name); + /** + * Returns a {@link SearchAlias} instance for the given view name. + * + * @param name Name of the view + * @return SearchAlias view handler + * @since ArangoDB 3.10 + */ + SearchAlias searchAlias(String name); + /** * Creates a view of the given {@code type}, then returns view information from the server. * * @param name The name of the view * @param type The type of the view * @return information about the view - * @throws ArangoDBException * @since ArangoDB 3.4.0 */ - ViewEntity createView(String name, ViewType type) throws ArangoDBException; + ViewEntity createView(String name, ViewType type); /** * Creates a ArangoSearch view with the given {@code options}, then returns view information from the server. @@ -728,127 +665,70 @@ TraversalEntity executeTraversal(Class vertexClass, Class edg * @param name The name of the view * @param options Additional options, can be null * @return information about the view - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.4.0 */ - ViewEntity createArangoSearch(String name, ArangoSearchCreateOptions options) throws ArangoDBException; + ViewEntity createArangoSearch(String name, ArangoSearchCreateOptions options); /** - * Creates an Analyzer + * Creates a SearchAlias view with the given {@code options}, then returns view information from the server. * - * @param options AnalyzerEntity - * @return the created Analyzer - * @throws ArangoDBException - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#createSearchAnalyzer(SearchAnalyzer)}} + * @param name The name of the view + * @param options Additional options, can be null + * @return information about the view + * @see API + * Documentation + * @since ArangoDB 3.10 */ - @Deprecated - AnalyzerEntity createAnalyzer(AnalyzerEntity options) throws ArangoDBException; + ViewEntity createSearchAlias(String name, SearchAliasCreateOptions options); /** * Creates an Analyzer * * @param analyzer SearchAnalyzer * @return the created Analyzer - * @throws ArangoDBException - * @see API Documentation - * @since ArangoDB 3.5.0 - */ - SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer) throws ArangoDBException; - - /** - * Gets information about an Analyzer - * - * @param name of the Analyzer without database prefix - * @return information about an Analyzer - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 - * @deprecated use {@link this#getSearchAnalyzer(String)}} */ - @Deprecated - AnalyzerEntity getAnalyzer(String name) throws ArangoDBException; + SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer); /** * Gets information about an Analyzer * * @param name of the Analyzer without database prefix * @return information about an Analyzer - * @throws ArangoDBException - * @see API Documentation - * @since ArangoDB 3.5.0 - */ - SearchAnalyzer getSearchAnalyzer(String name) throws ArangoDBException; - - /** - * Retrieves all analyzers definitions. - * - * @return collection of all analyzers definitions - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 - * @deprecated use {@link this#getSearchAnalyzers()} */ - @Deprecated - Collection getAnalyzers() throws ArangoDBException; + SearchAnalyzer getSearchAnalyzer(String name); /** * Retrieves all analyzers definitions. * * @return collection of all analyzers definitions - * @throws ArangoDBException - * @see API Documentation - * @since ArangoDB 3.5.0 - */ - Collection getSearchAnalyzers() throws ArangoDBException; - - /** - * Deletes an Analyzer - * - * @param name of the Analyzer without database prefix - * @throws ArangoDBException - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#deleteSearchAnalyzer(String)}}} - */ - @Deprecated - void deleteAnalyzer(String name) throws ArangoDBException; - - /** - * Deletes an Analyzer - * - * @param name of the Analyzer without database prefix - * @param options AnalyzerDeleteOptions - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 - * @deprecated use {@link this#deleteSearchAnalyzer(String, AnalyzerDeleteOptions)}}} */ - @Deprecated - void deleteAnalyzer(String name, AnalyzerDeleteOptions options) throws ArangoDBException; + Collection getSearchAnalyzers(); /** * Deletes an Analyzer * * @param name of the Analyzer without database prefix - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ - void deleteSearchAnalyzer(String name) throws ArangoDBException; + void deleteSearchAnalyzer(String name); /** * Deletes an Analyzer * * @param name of the Analyzer without database prefix * @param options AnalyzerDeleteOptions - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ - void deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options) throws ArangoDBException; + void deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options); } diff --git a/src/main/java/com/arangodb/ArangoEdgeCollection.java b/core/src/main/java/com/arangodb/ArangoEdgeCollection.java similarity index 69% rename from src/main/java/com/arangodb/ArangoEdgeCollection.java rename to core/src/main/java/com/arangodb/ArangoEdgeCollection.java index 17d6d054b..c0d64d369 100644 --- a/src/main/java/com/arangodb/ArangoEdgeCollection.java +++ b/core/src/main/java/com/arangodb/ArangoEdgeCollection.java @@ -24,14 +24,16 @@ import com.arangodb.entity.EdgeUpdateEntity; import com.arangodb.model.*; +import javax.annotation.concurrent.ThreadSafe; + /** * Interface for operations on ArangoDB edge collection level. * * @author Mark Vollmary * @see API Documentation */ -@SuppressWarnings("UnusedReturnValue") -public interface ArangoEdgeCollection extends ArangoSerializationAccessor { +@ThreadSafe +public interface ArangoEdgeCollection extends ArangoSerdeAccessor { /** * The the handler of the named graph the edge collection is within @@ -50,84 +52,77 @@ public interface ArangoEdgeCollection extends ArangoSerializationAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, VPackSlice or String for JSON) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData}) * @return information about the edge - * @throws ArangoDBException * @see API Documentation */ - EdgeEntity insertEdge(T value) throws ArangoDBException; + EdgeEntity insertEdge(Object value); /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, VPackSlice or String for JSON) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the edge - * @throws ArangoDBException * @see API Documentation */ - EdgeEntity insertEdge(T value, EdgeCreateOptions options) throws ArangoDBException; + EdgeEntity insertEdge(Object value, EdgeCreateOptions options); /** * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO class, VPackSlice or String for JSON) + * @param type The type of the edge-document (POJO or {@link com.arangodb.util.RawData}) * @return the edge identified by the key - * @throws ArangoDBException * @see API Documentation */ - T getEdge(String key, Class type) throws ArangoDBException; + T getEdge(String key, Class type); /** * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO class, VPackSlice or String for JSON) + * @param type The type of the edge-document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the edge identified by the key - * @throws ArangoDBException * @see API Documentation */ - T getEdge(String key, Class type, GraphDocumentReadOptions options) throws ArangoDBException; + T getEdge(String key, Class type, GraphDocumentReadOptions options); /** * Replaces the edge with key with the one in the body, provided there is such a edge and no precondition is * violated * - * @param key The key of the edge - * @param The type of the edge-document (POJO class, VPackSlice or String for JSON) + * @param key The key of the edge + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData}) * @return information about the edge - * @throws ArangoDBException * @see API Documentation */ - EdgeUpdateEntity replaceEdge(String key, T value) throws ArangoDBException; + EdgeUpdateEntity replaceEdge(String key, Object value); /** * Replaces the edge with key with the one in the body, provided there is such a edge and no precondition is * violated * * @param key The key of the edge - * @param The type of the edge-document (POJO class, VPackSlice or String for JSON) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the edge - * @throws ArangoDBException * @see API Documentation */ - EdgeUpdateEntity replaceEdge(String key, T value, EdgeReplaceOptions options) throws ArangoDBException; + EdgeUpdateEntity replaceEdge(String key, Object value, EdgeReplaceOptions options); /** * Partially updates the edge identified by document-key. The value must contain a document with the attributes to * patch (the patch document). All attributes from the patch document will be added to the existing document if they * do not yet exist, and overwritten in the existing document if they do exist there. * - * @param key The key of the edge - * @param The type of the edge-document (POJO class, VPackSlice or String for JSON) + * @param key The key of the edge + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData}) * @return information about the edge - * @throws ArangoDBException * @see API Documentation */ - EdgeUpdateEntity updateEdge(String key, T value) throws ArangoDBException; + EdgeUpdateEntity updateEdge(String key, Object value); /** * Partially updates the edge identified by document-key. The value must contain a document with the attributes to @@ -135,31 +130,28 @@ public interface ArangoEdgeCollection extends ArangoSerializationAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the edge - * @param The type of the edge-document (POJO class, VPackSlice or String for JSON) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the edge - * @throws ArangoDBException * @see API Documentation */ - EdgeUpdateEntity updateEdge(String key, T value, EdgeUpdateOptions options) throws ArangoDBException; + EdgeUpdateEntity updateEdge(String key, Object value, EdgeUpdateOptions options); /** * Removes a edge * * @param key The key of the edge - * @throws ArangoDBException * @see API Documentation */ - void deleteEdge(String key) throws ArangoDBException; + void deleteEdge(String key); /** * Removes a edge * * @param key The key of the edge * @param options Additional options, can be null - * @throws ArangoDBException * @see API Documentation */ - void deleteEdge(String key, EdgeDeleteOptions options) throws ArangoDBException; + void deleteEdge(String key, EdgeDeleteOptions options); } diff --git a/src/main/java/com/arangodb/ArangoGraph.java b/core/src/main/java/com/arangodb/ArangoGraph.java similarity index 80% rename from src/main/java/com/arangodb/ArangoGraph.java rename to core/src/main/java/com/arangodb/ArangoGraph.java index 873405cda..49038891a 100644 --- a/src/main/java/com/arangodb/ArangoGraph.java +++ b/core/src/main/java/com/arangodb/ArangoGraph.java @@ -25,6 +25,7 @@ import com.arangodb.model.GraphCreateOptions; import com.arangodb.model.VertexCollectionCreateOptions; +import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; /** @@ -33,7 +34,8 @@ * @author Mark Vollmary * @see API Documentation */ -public interface ArangoGraph extends ArangoSerializationAccessor { +@ThreadSafe +public interface ArangoGraph extends ArangoSerdeAccessor { /** * The the handler of the database the named graph is within @@ -54,7 +56,7 @@ public interface ArangoGraph extends ArangoSerializationAccessor { * * @return true if the graph exists, otherwise false */ - boolean exists() throws ArangoDBException; + boolean exists(); /** * Creates the graph in the graph module. The creation of a graph requires the name of the graph and a definition of @@ -62,11 +64,10 @@ public interface ArangoGraph extends ArangoSerializationAccessor { * * @param edgeDefinitions An array of definitions for the edge * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity create(Collection edgeDefinitions) throws ArangoDBException; + GraphEntity create(Collection edgeDefinitions); /** * Creates the graph in the graph module. The creation of a graph requires the name of the graph and a definition of @@ -75,50 +76,47 @@ public interface ArangoGraph extends ArangoSerializationAccessor { * @param edgeDefinitions An array of definitions for the edge * @param options Additional options, can be null * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity create(Collection edgeDefinitions, GraphCreateOptions options) throws ArangoDBException; + GraphEntity create(Collection edgeDefinitions, GraphCreateOptions options); /** * Deletes the graph from the database. * - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation */ - void drop() throws ArangoDBException; + void drop(); /** * Deletes the graph from the database. * * @param dropCollections Drop collections of this graph as well. Collections will only be * dropped if they are not used in other graphs. - * @throws ArangoDBException * @see API * Documentation */ - void drop(boolean dropCollections) throws ArangoDBException; + void drop(boolean dropCollections); /** * Retrieves general information about the graph. * * @return the definition content of this graph - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation */ - GraphEntity getInfo() throws ArangoDBException; + GraphEntity getInfo(); /** * Fetches all vertex collections from the graph and returns a list of collection names. * * @return all vertex collections within this graph - * @throws ArangoDBException * @see API * Documentation */ - Collection getVertexCollections() throws ArangoDBException; + Collection getVertexCollections(); /** * Adds a vertex collection to the set of collections of the graph. If the collection does not exist, it will be @@ -126,25 +124,23 @@ public interface ArangoGraph extends ArangoSerializationAccessor { * * @param name Name of the vertex collection * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity addVertexCollection(String name) throws ArangoDBException; + GraphEntity addVertexCollection(String name); /** * Adds a vertex collection to the set of collections of the graph. If the collection does not exist, it will be * created. * - * @param name Name of the vertex collection + * @param name Name of the vertex collection * @param options additional options * @return information about the graph - * @throws ArangoDBException * @see API * Documentation * @since ArangoDB 3.9 */ - GraphEntity addVertexCollection(String name, VertexCollectionCreateOptions options) throws ArangoDBException; + GraphEntity addVertexCollection(String name, VertexCollectionCreateOptions options); /** * Returns a {@code ArangoVertexCollection} instance for the given vertex collection name. @@ -166,22 +162,20 @@ public interface ArangoGraph extends ArangoSerializationAccessor { * Fetches all edge collections from the graph and returns a list of collection names. * * @return all edge collections within this graph - * @throws ArangoDBException * @see API * Documentation */ - Collection getEdgeDefinitions() throws ArangoDBException; + Collection getEdgeDefinitions(); /** * Adds the given edge definition to the graph. * * @param definition The edge definition * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity addEdgeDefinition(EdgeDefinition definition) throws ArangoDBException; + GraphEntity addEdgeDefinition(EdgeDefinition definition); /** * Change one specific edge definition. This will modify all occurrences of this definition in all graphs known to @@ -189,11 +183,10 @@ public interface ArangoGraph extends ArangoSerializationAccessor { * * @param definition The edge definition * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity replaceEdgeDefinition(EdgeDefinition definition) throws ArangoDBException; + GraphEntity replaceEdgeDefinition(EdgeDefinition definition); /** * Remove one edge definition from the graph. This will only remove the edge collection, the vertex collections @@ -201,11 +194,10 @@ public interface ArangoGraph extends ArangoSerializationAccessor { * * @param definitionName The name of the edge collection used in the definition * @return information about the graph - * @throws ArangoDBException * @see API * Documentation */ - GraphEntity removeEdgeDefinition(String definitionName) throws ArangoDBException; + GraphEntity removeEdgeDefinition(String definitionName); } diff --git a/src/main/java/com/arangodb/util/ArangoSerialization.java b/core/src/main/java/com/arangodb/ArangoIterable.java similarity index 74% rename from src/main/java/com/arangodb/util/ArangoSerialization.java rename to core/src/main/java/com/arangodb/ArangoIterable.java index 2396d51b2..b0848c292 100644 --- a/src/main/java/com/arangodb/util/ArangoSerialization.java +++ b/core/src/main/java/com/arangodb/ArangoIterable.java @@ -1,28 +1,35 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -/** - * @author Mark Vollmary - */ -public interface ArangoSerialization extends ArangoSerializer, ArangoDeserializer { - -} +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import java.util.stream.Stream; + +/** + * @author Mark Vollmary + */ +public interface ArangoIterable extends Iterable { + + @Override + ArangoIterator iterator(); + + Stream stream(); + +} diff --git a/src/main/java/com/arangodb/ArangoIterator.java b/core/src/main/java/com/arangodb/ArangoIterator.java similarity index 100% rename from src/main/java/com/arangodb/ArangoIterator.java rename to core/src/main/java/com/arangodb/ArangoIterator.java diff --git a/src/main/java/com/arangodb/ArangoMetrics.java b/core/src/main/java/com/arangodb/ArangoMetrics.java similarity index 93% rename from src/main/java/com/arangodb/ArangoMetrics.java rename to core/src/main/java/com/arangodb/ArangoMetrics.java index 21d659b53..38253fac4 100644 --- a/src/main/java/com/arangodb/ArangoMetrics.java +++ b/core/src/main/java/com/arangodb/ArangoMetrics.java @@ -20,12 +20,15 @@ package com.arangodb; +import javax.annotation.concurrent.ThreadSafe; + /** * Interface for accessing metrics. * * @author Michele Rastelli * @since ArangoDB 3.9 */ +@ThreadSafe public interface ArangoMetrics { /** * @return queue time metrics diff --git a/src/main/java/com/arangodb/ArangoSearch.java b/core/src/main/java/com/arangodb/ArangoSearch.java similarity index 82% rename from src/main/java/com/arangodb/ArangoSearch.java rename to core/src/main/java/com/arangodb/ArangoSearch.java index 7a6600d79..8bdaf6c66 100644 --- a/src/main/java/com/arangodb/ArangoSearch.java +++ b/core/src/main/java/com/arangodb/ArangoSearch.java @@ -25,68 +25,67 @@ import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; +import javax.annotation.concurrent.ThreadSafe; + /** * Interface for operations on ArangoDB view level for ArangoSearch views. * * @author Mark Vollmary - * @see View API Documentation + * @see View API Documentation * @since ArangoDB 3.4.0 */ +@ThreadSafe public interface ArangoSearch extends ArangoView { /** * Creates a view, then returns view information from the server. * * @return information about the view - * @throws ArangoDBException * @see API * Documentation */ - ViewEntity create() throws ArangoDBException; + ViewEntity create(); /** * Creates a view with the given {@code options}, then returns view information from the server. * * @param options Additional options, can be null * @return information about the view - * @throws ArangoDBException * @see API * Documentation */ - ViewEntity create(ArangoSearchCreateOptions options) throws ArangoDBException; + ViewEntity create(ArangoSearchCreateOptions options); /** * Reads the properties of the specified view. * * @return properties of the view - * @throws ArangoDBException * @see API * Documentation */ - ArangoSearchPropertiesEntity getProperties() throws ArangoDBException; + ArangoSearchPropertiesEntity getProperties(); /** * Partially changes properties of the view. * * @param options properties to change * @return properties of the view - * @throws ArangoDBException * @see API + * "https://www.arangodb.com/docs/stable/http/views-arangosearch + * .html#partially-changes-properties-of-an-arangosearch-view">API * Documentation */ - ArangoSearchPropertiesEntity updateProperties(ArangoSearchPropertiesOptions options) throws ArangoDBException; + ArangoSearchPropertiesEntity updateProperties(ArangoSearchPropertiesOptions options); /** * Changes properties of the view. * * @param options properties to change * @return properties of the view - * @throws ArangoDBException * @see API * Documentation */ - ArangoSearchPropertiesEntity replaceProperties(ArangoSearchPropertiesOptions options) throws ArangoDBException; + ArangoSearchPropertiesEntity replaceProperties(ArangoSearchPropertiesOptions options); } diff --git a/src/main/java/com/arangodb/Consumer.java b/core/src/main/java/com/arangodb/ArangoSerdeAccessor.java similarity index 70% rename from src/main/java/com/arangodb/Consumer.java rename to core/src/main/java/com/arangodb/ArangoSerdeAccessor.java index 3edbe3c4e..7ff4892c0 100644 --- a/src/main/java/com/arangodb/Consumer.java +++ b/core/src/main/java/com/arangodb/ArangoSerdeAccessor.java @@ -20,19 +20,21 @@ package com.arangodb; +import com.arangodb.internal.serde.InternalSerde; + +import javax.annotation.concurrent.ThreadSafe; + /** - * @param the type of the input to the operation * @author Mark Vollmary - * @deprecated Use {@link java.util.function.Consumer} instead. */ -@Deprecated -public interface Consumer { +@ThreadSafe +public interface ArangoSerdeAccessor { /** - * Performs this operation on the given argument. + * Returns driver internal serialization implementation for serializing and deserializing driver's classes. * - * @param t the input argument + * @return ArangoSerde */ - void accept(T t); + InternalSerde getSerde(); } diff --git a/src/main/java/com/arangodb/ArangoVertexCollection.java b/core/src/main/java/com/arangodb/ArangoVertexCollection.java similarity index 61% rename from src/main/java/com/arangodb/ArangoVertexCollection.java rename to core/src/main/java/com/arangodb/ArangoVertexCollection.java index e34705cf4..fa43961f8 100644 --- a/src/main/java/com/arangodb/ArangoVertexCollection.java +++ b/core/src/main/java/com/arangodb/ArangoVertexCollection.java @@ -24,13 +24,16 @@ import com.arangodb.entity.VertexUpdateEntity; import com.arangodb.model.*; +import javax.annotation.concurrent.ThreadSafe; + /** * Interface for operations on ArangoDB vertex collection level. * * @author Mark Vollmary * @see API Documentation */ -public interface ArangoVertexCollection extends ArangoSerializationAccessor { +@ThreadSafe +public interface ArangoVertexCollection extends ArangoSerdeAccessor { /** * The the handler of the named graph the edge collection is within @@ -50,95 +53,90 @@ public interface ArangoVertexCollection extends ArangoSerializationAccessor { * Removes a vertex collection from the graph and optionally deletes the collection, if it is not used in any other * graph * - * @throws ArangoDBException * @see API * Documentation */ - void drop() throws ArangoDBException; + void drop(); /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, VPackSlice or String for JSON) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @return information about the vertex - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation */ - VertexEntity insertVertex(T value) throws ArangoDBException; + VertexEntity insertVertex(Object value); /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, VPackSlice or String for JSON) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the vertex - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation */ - VertexEntity insertVertex(T value, VertexCreateOptions options) throws ArangoDBException; + VertexEntity insertVertex(Object value, VertexCreateOptions options); /** * Retrieves the vertex document with the given {@code key} from the collection. * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO class, VPackSlice or String for JSON) + * @param type The type of the vertex-document (POJO or {@link com.arangodb.util.RawData}) * @return the vertex identified by the key - * @throws ArangoDBException * @see API Documentation */ - T getVertex(String key, Class type) throws ArangoDBException; + T getVertex(String key, Class type); /** * Retrieves the vertex document with the given {@code key} from the collection. * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO class, VPackSlice or String for JSON) + * @param type The type of the vertex-document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the vertex identified by the key - * @throws ArangoDBException * @see API Documentation */ - T getVertex(String key, Class type, GraphDocumentReadOptions options) throws ArangoDBException; + T getVertex(String key, Class type, GraphDocumentReadOptions options); /** * Replaces the vertex with key with the one in the body, provided there is such a vertex and no precondition is * violated * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO, VPackSlice or String for JSON) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @return information about the vertex - * @throws ArangoDBException * @see API * Documentation */ - VertexUpdateEntity replaceVertex(String key, T value) throws ArangoDBException; + VertexUpdateEntity replaceVertex(String key, Object value); /** * Replaces the vertex with key with the one in the body, provided there is such a vertex and no precondition is * violated * * @param key The key of the vertex - * @param value A representation of a single vertex (POJO, VPackSlice or String for JSON) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the vertex - * @throws ArangoDBException * @see API * Documentation */ - VertexUpdateEntity replaceVertex(String key, T value, VertexReplaceOptions options) throws ArangoDBException; + VertexUpdateEntity replaceVertex(String key, Object value, VertexReplaceOptions options); /** * Partially updates the vertex identified by document-key. The value must contain a document with the attributes to * patch (the patch document). All attributes from the patch document will be added to the existing document if they * do not yet exist, and overwritten in the existing document if they do exist there. * - * @param key The key of the vertex - * @param The type of the vertex-document (POJO class, VPackSlice or String for JSON) + * @param key The key of the vertex + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @return information about the vertex - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation */ - VertexUpdateEntity updateVertex(String key, T value) throws ArangoDBException; + VertexUpdateEntity updateVertex(String key, Object value); /** * Partially updates the vertex identified by document-key. The value must contain a document with the attributes to @@ -146,31 +144,31 @@ public interface ArangoVertexCollection extends ArangoSerializationAccessor { * do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the vertex - * @param The type of the vertex-document (POJO class, VPackSlice or String for JSON) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the vertex - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation */ - VertexUpdateEntity updateVertex(String key, T value, VertexUpdateOptions options) throws ArangoDBException; + VertexUpdateEntity updateVertex(String key, Object value, VertexUpdateOptions options); /** * Deletes the vertex with the given {@code key} from the collection. * * @param key The key of the vertex - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation */ - void deleteVertex(String key) throws ArangoDBException; + void deleteVertex(String key); /** * Deletes the vertex with the given {@code key} from the collection. * * @param key The key of the vertex * @param options Additional options, can be null - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation */ - void deleteVertex(String key, VertexDeleteOptions options) throws ArangoDBException; + void deleteVertex(String key, VertexDeleteOptions options); } diff --git a/src/main/java/com/arangodb/ArangoView.java b/core/src/main/java/com/arangodb/ArangoView.java similarity index 67% rename from src/main/java/com/arangodb/ArangoView.java rename to core/src/main/java/com/arangodb/ArangoView.java index 56a3a7995..38f848c09 100644 --- a/src/main/java/com/arangodb/ArangoView.java +++ b/core/src/main/java/com/arangodb/ArangoView.java @@ -22,6 +22,8 @@ import com.arangodb.entity.ViewEntity; +import javax.annotation.concurrent.ThreadSafe; + /** * Interface for operations on ArangoDB view level. * @@ -29,8 +31,8 @@ * @see View API Documentation * @since ArangoDB 3.4.0 */ -@SuppressWarnings("UnusedReturnValue") -public interface ArangoView extends ArangoSerializationAccessor { +@ThreadSafe +public interface ArangoView extends ArangoSerdeAccessor { /** * The the handler of the database the collection is within @@ -50,36 +52,35 @@ public interface ArangoView extends ArangoSerializationAccessor { * Checks whether the view exists. * * @return true if the view exists, otherwise false - * @throws ArangoDBException */ - boolean exists() throws ArangoDBException; + boolean exists(); /** * Deletes the view from the database. * - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation */ - void drop() throws ArangoDBException; + void drop(); /** * Renames the view. * * @param newName The new name * @return information about the view - * @throws ArangoDBException - * @see API Documentation + * @see + * API Documentation */ - ViewEntity rename(String newName) throws ArangoDBException; + ViewEntity rename(String newName); /** * Returns information about the view. * * @return information about the view - * @throws ArangoDBException - * @see API + * @see + * API * Documentation */ - ViewEntity getInfo() throws ArangoDBException; + ViewEntity getInfo(); } diff --git a/src/main/java/com/arangodb/entity/Entity.java b/core/src/main/java/com/arangodb/ContentType.java similarity index 82% rename from src/main/java/com/arangodb/entity/Entity.java rename to core/src/main/java/com/arangodb/ContentType.java index 146e561ae..ec63aaf8d 100644 --- a/src/main/java/com/arangodb/entity/Entity.java +++ b/core/src/main/java/com/arangodb/ContentType.java @@ -1,7 +1,7 @@ /* * DISCLAIMER * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * Copyright 2016 ArangoDB GmbH, Cologne, Germany * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +17,8 @@ * * Copyright holder is ArangoDB GmbH, Cologne, Germany */ +package com.arangodb; -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public interface Entity { - +public enum ContentType { + JSON, VPACK } diff --git a/src/main/java/com/arangodb/DbName.java b/core/src/main/java/com/arangodb/DbName.java similarity index 100% rename from src/main/java/com/arangodb/DbName.java rename to core/src/main/java/com/arangodb/DbName.java index 70b3e5e42..37cffbe76 100644 --- a/src/main/java/com/arangodb/DbName.java +++ b/core/src/main/java/com/arangodb/DbName.java @@ -23,6 +23,10 @@ public final class DbName implements Supplier { private final String value; + private DbName(final String value) { + this.value = value; + } + /** * Creates a new {@link DbName} instance with the provided value. If the provided value is not * NFC-normalized, throws @@ -54,10 +58,6 @@ public static DbName normalize(final String value) { return new DbName(UnicodeUtils.normalize(value)); } - private DbName(final String value) { - this.value = value; - } - @Override public String get() { return value; diff --git a/core/src/main/java/com/arangodb/PackageVersion.java.in b/core/src/main/java/com/arangodb/PackageVersion.java.in new file mode 100644 index 000000000..e801e4d89 --- /dev/null +++ b/core/src/main/java/com/arangodb/PackageVersion.java.in @@ -0,0 +1,8 @@ +package com.arangodb; + +/** + * Automatically generated from PackageVersion.java.in by replacer plugin. + */ +public final class PackageVersion { + public final static String VERSION = "@project.version@"; +} diff --git a/src/main/java/com/arangodb/Protocol.java b/core/src/main/java/com/arangodb/Protocol.java similarity index 77% rename from src/main/java/com/arangodb/Protocol.java rename to core/src/main/java/com/arangodb/Protocol.java index 486ab62f7..1ca4bb4ea 100644 --- a/src/main/java/com/arangodb/Protocol.java +++ b/core/src/main/java/com/arangodb/Protocol.java @@ -24,20 +24,36 @@ * @author Mark Vollmary */ public enum Protocol { + /** * VelocyStream * * @see VelocyStream specification */ VST, + /** - * HTTP with JSON body + * HTTP 1.1 with JSON body */ HTTP_JSON, + + /** + * HTTP 1.1 with VelocyPack body + * + * @see VelocyPack specification + */ + HTTP_VPACK, + + /** + * HTTP 2 with JSON body + */ + HTTP2_JSON, + /** - * HTTP with VelocyPack body + * HTTP 2 with VelocyPack body * * @see VelocyPack specification */ - HTTP_VPACK + HTTP2_VPACK, + } diff --git a/src/main/java/com/arangodb/QueueTimeMetrics.java b/core/src/main/java/com/arangodb/QueueTimeMetrics.java similarity index 96% rename from src/main/java/com/arangodb/QueueTimeMetrics.java rename to core/src/main/java/com/arangodb/QueueTimeMetrics.java index 333d14997..c04a7110b 100644 --- a/src/main/java/com/arangodb/QueueTimeMetrics.java +++ b/core/src/main/java/com/arangodb/QueueTimeMetrics.java @@ -22,6 +22,8 @@ import com.arangodb.model.QueueTimeSample; +import javax.annotation.concurrent.ThreadSafe; + /** * Interface for accessing queue time latency metrics, reported by the "X-Arango-Queue-Time-Seconds" response header. * This header contains the most recent request (de)queuing time (in seconds) as tracked by the server’s scheduler. @@ -30,6 +32,7 @@ * @see API Documentation * @since ArangoDB 3.9 */ +@ThreadSafe public interface QueueTimeMetrics { /** diff --git a/core/src/main/java/com/arangodb/Request.java b/core/src/main/java/com/arangodb/Request.java new file mode 100644 index 000000000..dbc708632 --- /dev/null +++ b/core/src/main/java/com/arangodb/Request.java @@ -0,0 +1,130 @@ +package com.arangodb; + +import java.util.HashMap; +import java.util.Map; + +public final class Request { + private final DbName db; + private final Method method; + private final String path; + private final Map queryParams; + private final Map headers; + private final T body; + + public enum Method { + DELETE, + GET, + POST, + PUT, + HEAD, + PATCH, + OPTIONS + } + + public static Builder builder() { + return new Builder<>(); + } + + private Request(DbName db, Method method, String path, Map queryParams, Map headers, T body) { + this.db = db; + this.method = method; + this.path = path; + this.queryParams = queryParams; + this.headers = headers; + this.body = body; + } + + public DbName getDb() { + return db; + } + + public Method getMethod() { + return method; + } + + public String getPath() { + return path; + } + + public Map getQueryParams() { + return queryParams; + } + + public Map getHeaders() { + return headers; + } + + public T getBody() { + return body; + } + + public static final class Builder { + private DbName db; + private Request.Method method; + private String path; + private final Map queryParams; + private final Map headers; + private T body; + + public Builder() { + queryParams = new HashMap<>(); + headers = new HashMap<>(); + } + + public Builder db(DbName db) { + this.db = db; + return this; + } + + public Builder method(Request.Method method) { + this.method = method; + return this; + } + + public Builder path(String path) { + this.path = path; + return this; + } + + public Builder queryParam(final String key, final String value) { + if (value != null) { + queryParams.put(key, value); + } + return this; + } + + public Builder queryParams(Map queryParams) { + if (queryParams != null) { + for (Map.Entry it : queryParams.entrySet()) { + queryParam(it.getKey(), it.getValue()); + } + } + return this; + } + + public Builder header(final String key, final String value) { + if (value != null) { + headers.put(key, value); + } + return this; + } + + public Builder headers(Map headers) { + if (headers != null) { + for (Map.Entry it : headers.entrySet()) { + header(it.getKey(), it.getValue()); + } + } + return this; + } + + public Builder body(T body) { + this.body = body; + return this; + } + + public Request build() { + return new Request<>(db, method, path, queryParams, headers, body); + } + } +} diff --git a/core/src/main/java/com/arangodb/Response.java b/core/src/main/java/com/arangodb/Response.java new file mode 100644 index 000000000..49c37698b --- /dev/null +++ b/core/src/main/java/com/arangodb/Response.java @@ -0,0 +1,27 @@ +package com.arangodb; + +import java.util.Map; + +public final class Response { + private final int responseCode; + private final Map headers; + private final T body; + + public Response(int responseCode, Map headers, T body) { + this.responseCode = responseCode; + this.headers = headers; + this.body = body; + } + + public int getResponseCode() { + return responseCode; + } + + public Map getHeaders() { + return headers; + } + + public T getBody() { + return body; + } +} diff --git a/core/src/main/java/com/arangodb/SearchAlias.java b/core/src/main/java/com/arangodb/SearchAlias.java new file mode 100644 index 000000000..f8cd4353e --- /dev/null +++ b/core/src/main/java/com/arangodb/SearchAlias.java @@ -0,0 +1,87 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.ViewEntity; +import com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasPropertiesOptions; + +/** + * Interface for operations on ArangoDB view level for SearchAlias views. + * + * @author Michele Rastelli + * @see View API Documentation + * @since ArangoDB 3.10 + */ +public interface SearchAlias extends ArangoView { + + /** + * Creates a view, then returns view information from the server. + * + * @return information about the view + * @see API + * Documentation + */ + ViewEntity create(); + + /** + * Creates a view with the given {@code options}, then returns view information from the server. + * + * @param options Additional options, can be null + * @return information about the view + * @see API + * Documentation + */ + ViewEntity create(SearchAliasCreateOptions options); + + /** + * Reads the properties of the specified view. + * + * @return properties of the view + * @see API + * Documentation + */ + SearchAliasPropertiesEntity getProperties(); + + /** + * Partially changes properties of the view. + * + * @param options properties to change + * @return properties of the view + * @see API + * Documentation + */ + SearchAliasPropertiesEntity updateProperties(SearchAliasPropertiesOptions options); + + /** + * Changes properties of the view. + * + * @param options properties to change + * @return properties of the view + * @see API + * Documentation + */ + SearchAliasPropertiesEntity replaceProperties(SearchAliasPropertiesOptions options); + +} diff --git a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java b/core/src/main/java/com/arangodb/async/ArangoCollectionAsync.java similarity index 61% rename from src/main/java/com/arangodb/async/ArangoCollectionAsync.java rename to core/src/main/java/com/arangodb/async/ArangoCollectionAsync.java index c54a7c8e1..ad04dc5bf 100644 --- a/src/main/java/com/arangodb/async/ArangoCollectionAsync.java +++ b/core/src/main/java/com/arangodb/async/ArangoCollectionAsync.java @@ -20,11 +20,12 @@ package com.arangodb.async; -import com.arangodb.ArangoDBException; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.entity.*; import com.arangodb.model.*; +import com.arangodb.util.RawData; +import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; import java.util.concurrent.CompletableFuture; @@ -35,8 +36,8 @@ * @see Collection API Documentation * @see Documents API Documentation */ -@SuppressWarnings("unused") -public interface ArangoCollectionAsync extends ArangoSerializationAccessor { +@ThreadSafe +public interface ArangoCollectionAsync extends ArangoSerdeAccessor { /** * The the handler of the database the collection is within @@ -56,42 +57,81 @@ public interface ArangoCollectionAsync extends ArangoSerializationAccessor { * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, VPackSlice or String for Json) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @return information about the document * @see API * Documentation */ - CompletableFuture> insertDocument(final T value); + CompletableFuture> insertDocument(final Object value); /** * Creates a new document from the given document, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param value A representation of a single document (POJO, VPackSlice or String for Json) - * @param options Additional options, can be null + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options * @return information about the document * @see API * Documentation */ CompletableFuture> insertDocument(final T value, final DocumentCreateOptions options); + /** + * Creates a new document from the given document, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options + * @param type Deserialization target type for the returned documents. + * @return information about the document + * @see API + * Documentation + */ + CompletableFuture> insertDocument(final T value, final DocumentCreateOptions options, + Class type); + /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, VPackSlice or String for Json) + * @param values Raw data representing a collection of documents * @return information about the documents * @see API * Documentation */ - CompletableFuture>> insertDocuments(final Collection values); + CompletableFuture>> insertDocuments(final RawData values); /** * Creates new documents from the given documents, unless there is already a document with the _key given. If no * _key is given, a new unique _key is generated automatically. * - * @param values A List of documents (POJO, VPackSlice or String for Json) - * @param options Additional options, can be null + * @param values Raw data representing a collection of documents + * @param options Additional options + * @return information about the documents + * @see API + * Documentation + */ + CompletableFuture>> insertDocuments( + final RawData values, + final DocumentCreateOptions options); + + /** + * Creates new documents from the given documents, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) + * @return information about the documents + * @see API + * Documentation + */ + CompletableFuture>> insertDocuments(final Collection values); + + /** + * Creates new documents from the given documents, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options * @return information about the documents * @see API * Documentation @@ -100,10 +140,26 @@ CompletableFuture>> insertDocume final Collection values, final DocumentCreateOptions options); + /** + * Creates new documents from the given documents, unless there is already a document with the _key given. If no + * _key is given, a new unique _key is generated automatically. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options + * @param type Deserialization target type for the returned documents. + * @return information about the documents + * @see API + * Documentation + */ + CompletableFuture>> insertDocuments( + final Collection values, + final DocumentCreateOptions options, + final Class type); + /** * Imports documents * - * @param values a list of Objects that will be stored as documents + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @return information about the import */ CompletableFuture importDocuments(final Collection values); @@ -111,7 +167,7 @@ CompletableFuture>> insertDocume /** * Imports documents * - * @param values a list of Objects that will be stored as documents + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the import */ @@ -122,49 +178,48 @@ CompletableFuture importDocuments( /** * Imports documents * - * @param values JSON-encoded array of objects that will be stored as documents + * @param values Raw data representing a collection of documents * @return information about the import */ - CompletableFuture importDocuments(final String values); + CompletableFuture importDocuments(final RawData values); /** * Imports documents * - * @param values JSON-encoded array of objects that will be stored as documents + * @param values Raw data representing a collection of documents * @param options Additional options, can be null * @return information about the import */ - CompletableFuture importDocuments(final String values, final DocumentImportOptions options); + CompletableFuture importDocuments(final RawData values, final DocumentImportOptions options); /** * Reads a single document * * @param key The key of the document - * @param type The type of the document (POJO class, VPackSlice or String for Json) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @return the document identified by the key * @see API * Documentation */ - CompletableFuture getDocument(final String key, final Class type) throws ArangoDBException; + CompletableFuture getDocument(final String key, final Class type); /** * Reads a single document * * @param key The key of the document - * @param type The type of the document (POJO class, VPackSlice or String for Json) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the document identified by the key * @see API * Documentation */ - CompletableFuture getDocument(final String key, final Class type, final DocumentReadOptions options) - throws ArangoDBException; + CompletableFuture getDocument(final String key, final Class type, final DocumentReadOptions options); /** * Reads multiple documents * * @param keys The keys of the documents - * @param type The type of the documents (POJO class, VPackSlice or String for Json) + * @param type The type of the documents (POJO or {@link com.arangodb.util.RawData}) * @return the documents and possible errors */ CompletableFuture> getDocuments(final Collection keys, final Class type); @@ -173,7 +228,7 @@ CompletableFuture getDocument(final String key, final Class type, fina * Reads multiple documents * * @param keys The keys of the documents - * @param type The type of the documents (POJO class, VPackSlice or String for Json) + * @param type The type of the documents (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the documents and possible errors */ @@ -187,22 +242,24 @@ CompletableFuture> getDocuments( * violated * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for Json) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @return information about the document - * @see API + * @see + * API * Documentation */ - CompletableFuture> replaceDocument(final String key, final T value); + CompletableFuture> replaceDocument(final String key, final Object value); /** * Replaces the document with key with the one in the body, provided there is such a document and no precondition is * violated * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for Json) - * @param options Additional options, can be null + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options * @return information about the document - * @see API + * @see + * API * Documentation */ CompletableFuture> replaceDocument( @@ -210,43 +267,108 @@ CompletableFuture> replaceDocument( final T value, final DocumentReplaceOptions options); + /** + * Replaces the document with key with the one in the body, provided there is such a document and no precondition is + * violated + * + * @param key The key of the document + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options + * @param type Deserialization target type for the returned documents. + * @return information about the document + * @see + * API + * Documentation + */ + CompletableFuture> replaceDocument( + final String key, + final T value, + final DocumentReplaceOptions options, + final Class type); + /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, VPackSlice or String for Json) + * @param values Raw data representing a collection of documents * @return information about the documents - * @see API + * @see + * API * Documentation */ - CompletableFuture>> replaceDocuments(final Collection values); + CompletableFuture>> replaceDocuments(final RawData values); /** * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are * specified by the _key attributes in the documents in values. * - * @param values A List of documents (POJO, VPackSlice or String for Json) - * @param options Additional options, can be null + * @param values Raw data representing a collection of documents + * @param options Additional options + * @return information about the documents + * @see + * API + * Documentation + */ + CompletableFuture>> replaceDocuments( + final RawData values, + final DocumentReplaceOptions options); + + /** + * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are + * specified by the _key attributes in the documents in values. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) + * @return information about the documents + * @see + * API + * Documentation + */ + CompletableFuture>> replaceDocuments(final Collection values); + + /** + * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are + * specified by the _key attributes in the documents in values. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options * @return information about the documents - * @see API + * @see + * API * Documentation */ CompletableFuture>> replaceDocuments( final Collection values, final DocumentReplaceOptions options); + /** + * Replaces multiple documents in the specified collection with the ones in the values, the replaced documents are + * specified by the _key attributes in the documents in values. + * + * @param values A List of documents (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options + * @param type Deserialization target type for the returned documents. + * @return information about the documents + * @see + * API + * Documentation + */ + CompletableFuture>> replaceDocuments( + final Collection values, + final DocumentReplaceOptions options, + final Class type); + /** * Partially updates the document identified by document-key. The value must contain a document with the attributes * to patch (the patch document). All attributes from the patch document will be added to the existing document if * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for Json) + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) * @return information about the document * @see API * Documentation */ - CompletableFuture> updateDocument(final String key, final T value); + CompletableFuture> updateDocument(final String key, final Object value); /** * Partially updates the document identified by document-key. The value must contain a document with the attributes @@ -254,8 +376,8 @@ CompletableFuture>> replaceDocum * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for Json) - * @param options Additional options, can be null + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options * @return information about the document * @see API * Documentation @@ -271,18 +393,18 @@ CompletableFuture> updateDocument( * they do not yet exist, and overwritten in the existing document if they do exist there. * * @param key The key of the document - * @param value A representation of a single document (POJO, VPackSlice or String for Json) - * @param options Additional options, can be null + * @param value A representation of a single document (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the document * @see API * Documentation */ - CompletableFuture> updateDocument( + CompletableFuture> updateDocument( final String key, - final T value, + final Object value, final DocumentUpdateOptions options, - final Class returnType); + final Class returnType); /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on @@ -290,12 +412,13 @@ CompletableFuture> updateDocument( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, VPackSlice or String for Json) + * @param values Raw data representing a collection of documents * @return information about the documents - * @see API + * @see + * API * Documentation */ - CompletableFuture>> updateDocuments(final Collection values); + CompletableFuture>> updateDocuments(final RawData values); /** * Partially updates documents, the documents to update are specified by the _key attributes in the objects on @@ -303,10 +426,42 @@ CompletableFuture> updateDocument( * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, VPackSlice or String for Json) - * @param options Additional options, can be null + * @param values Raw data representing a collection of documents + * @param options Additional options + * @return information about the documents + * @see + * API + * Documentation + */ + CompletableFuture>> updateDocuments( + final RawData values, + final DocumentUpdateOptions options); + + /** + * Partially updates documents, the documents to update are specified by the _key attributes in the objects on + * values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All + * attributes from the patch documents will be added to the existing documents if they do not yet exist, and + * overwritten in the existing documents if they do exist there. + * + * @param values A list of documents (POJO or {@link com.arangodb.util.RawData}) + * @return information about the documents + * @see + * API + * Documentation + */ + CompletableFuture>> updateDocuments(final Collection values); + + /** + * Partially updates documents, the documents to update are specified by the _key attributes in the objects on + * values. Vales must contain a list of document updates with the attributes to patch (the patch documents). All + * attributes from the patch documents will be added to the existing documents if they do not yet exist, and + * overwritten in the existing documents if they do exist there. + * + * @param values A list of documents (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options * @return information about the documents - * @see API + * @see + * API * Documentation */ CompletableFuture>> updateDocuments( @@ -319,24 +474,26 @@ CompletableFuture>> updateDocume * attributes from the patch documents will be added to the existing documents if they do not yet exist, and * overwritten in the existing documents if they do exist there. * - * @param values A list of documents (POJO, VPackSlice or String for Json) - * @param options Additional options, can be null + * @param values A list of documents (POJO or {@link com.arangodb.util.RawData}) + * @param options Additional options * @param returnType Type of the returned newDocument and/or oldDocument * @return information about the documents - * @see API + * @see + * API * Documentation */ - CompletableFuture>> updateDocuments( - final Collection values, + CompletableFuture>> updateDocuments( + final Collection values, final DocumentUpdateOptions options, - final Class returnType); + final Class returnType); /** * Removes a document * * @param key The key of the document * @return information about the document - * @see API + * @see + * API * Documentation */ CompletableFuture> deleteDocument(final String key); @@ -345,16 +502,55 @@ CompletableFuture>> updateDoc * Removes a document * * @param key The key of the document - * @param type The type of the document (POJO class, VPackSlice or String for Json). Only necessary if - * options.returnOld is set to true, otherwise can be null. - * @param options Additional options, can be null + * @param options Additional options + * @return information about the document + * @see + * API + * Documentation + */ + CompletableFuture> deleteDocument( + final String key, + final DocumentDeleteOptions options); + + /** + * Removes a document + * + * @param key The key of the document + * @param type Deserialization target type for the returned documents. + * @param options Additional options * @return information about the document - * @see API + * @see + * API * Documentation */ CompletableFuture> deleteDocument( final String key, - final Class type, + final DocumentDeleteOptions options, + final Class type); + + /** + * Removes multiple document + * + * @param values Raw data representing the keys of the documents or the documents themselves + * @return information about the documents + * @see API + * Documentation + */ + CompletableFuture>> deleteDocuments(final RawData values); + + /** + * Removes multiple document + * + * @param values Raw data representing the keys of the documents or the documents themselves + * @param options Additional options + * @return information about the documents + * @see API + * Documentation + */ + CompletableFuture>> deleteDocuments( + final RawData values, final DocumentDeleteOptions options); /** @@ -372,9 +568,7 @@ CompletableFuture> deleteDocument( * Removes multiple document * * @param values The keys of the documents or the documents themselves - * @param type The type of the documents (POJO class, VPackSlice or String for Json). Only necessary if - * options.returnOld is set to true, otherwise can be null. - * @param options Additional options, can be null + * @param options Additional options * @return information about the documents * @see API @@ -382,9 +576,24 @@ CompletableFuture> deleteDocument( */ CompletableFuture>> deleteDocuments( final Collection values, - final Class type, final DocumentDeleteOptions options); + /** + * Removes multiple document + * + * @param values The keys of the documents or the documents themselves + * @param type Deserialization target type for the returned documents. + * @param options Additional options + * @return information about the documents + * @see API + * Documentation + */ + CompletableFuture>> deleteDocuments( + final Collection values, + final DocumentDeleteOptions options, + final Class type); + /** * Checks if the document exists by reading a single document head * @@ -410,19 +619,34 @@ CompletableFuture>> deleteDocume /** * Returns an index + *
+ * Note: inverted indexes are not returned by this method. Use + * {@link ArangoCollectionAsync#getInvertedIndex(String)} instead. * * @param id The index-handle * @return information about the index - * @see API Documentation + * @see + * API Documentation */ CompletableFuture getIndex(final String id); + /** + * Returns an inverted index + * + * @param id The index-handle + * @return information about the index + * @see API Documentation + * @since ArangoDB 3.10 + */ + CompletableFuture getInvertedIndex(String id); + /** * Deletes an index * * @param id The index-handle * @return the id of the index - * @see API Documentation + * @see + * API Documentation */ CompletableFuture deleteIndex(final String id); @@ -432,7 +656,8 @@ CompletableFuture>> deleteDocume * @param fields A list of attribute paths * @param options Additional options, can be null * @return information about the index - * @see API Documentation + * @see + * API Documentation * @deprecated use {@link #ensurePersistentIndex(Iterable, PersistentIndexOptions)} instead. Since ArangoDB 3.7 a * hash index is an alias for a persistent index. */ @@ -487,7 +712,9 @@ CompletableFuture ensurePersistentIndex( * @return information about the index * @see API * Documentation + * @deprecated since ArangoDB 3.10, use ArangoSearch or Inverted indexes instead. */ + @Deprecated CompletableFuture ensureFulltextIndex( final Iterable fields, final FulltextIndexOptions options); @@ -515,8 +742,21 @@ CompletableFuture ensureFulltextIndex( */ CompletableFuture ensureZKDIndex(final Iterable fields, final ZKDIndexOptions options); + /** + * Creates an inverted index for the collection, if it does not already exist. + * + * @param options index creation options + * @return information about the index + * @see API Documentation + * @since ArangoDB 3.10 + */ + CompletableFuture ensureInvertedIndex(InvertedIndexOptions options); + /** * Returns all indexes of the collection + *
+ * Note: inverted indexes are not returned by this method. Use + * {@link ArangoCollectionAsync#getInvertedIndexes()} instead. * * @return information about the indexes * @see ensureFulltextIndex( */ CompletableFuture> getIndexes(); + /** + * Fetches a list of all inverted indexes on this collection. + * + * @return information about the indexes + * @see API + * Documentation + * @since ArangoDB 3.10 + */ + CompletableFuture> getInvertedIndexes(); + /** * Checks whether the collection exists * @@ -555,7 +806,8 @@ CompletableFuture ensureFulltextIndex( * * @return information about the collection, including the number of documents * @see API + * "https://www.arangodb.com/docs/stable/http/collection-getting + * .html#return-number-of-documents-in-a-collection">API * Documentation */ CompletableFuture count(); @@ -565,7 +817,8 @@ CompletableFuture ensureFulltextIndex( * * @return information about the collection, including the number of documents * @see API + * "https://www.arangodb.com/docs/stable/http/collection-getting + * .html#return-number-of-documents-in-a-collection">API * Documentation */ CompletableFuture count(CollectionCountOptions options); @@ -601,7 +854,8 @@ CompletableFuture ensureFulltextIndex( /** * Drops the collection * - * @param isSystem Whether or not the collection to drop is a system collection. This parameter must be set to true in + * @param isSystem Whether or not the collection to drop is a system collection. This parameter must be set to + * true in * order to drop a system collection. * @return void * @see API @@ -609,29 +863,6 @@ CompletableFuture ensureFulltextIndex( */ CompletableFuture drop(final boolean isSystem); - /** - * Loads a collection into memory. - * - * @return information about the collection - * @see API - * Documentation - * @deprecated MMFiles only - */ - @Deprecated - CompletableFuture load(); - - /** - * Removes a collection from memory. This call does not delete any documents. You can use the collection afterwards; - * in which case it will be loaded into memory, again. - * - * @return information about the collection - * @see API - * Documentation - * @deprecated MMFiles only - */ - @Deprecated - CompletableFuture unload(); - /** * Returns information about the collection * @@ -680,7 +911,8 @@ CompletableFuture ensureFulltextIndex( * @param value A projection of the document containing at least the shard key (_key or a custom attribute) for * which the responsible shard should be determined * @return information about the responsible shard - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ @@ -690,7 +922,8 @@ CompletableFuture ensureFulltextIndex( * Retrieve the collections revision * * @return information about the collection, including the collections revision - * @see API + * @see + * API * Documentation */ CompletableFuture getRevision(); @@ -737,7 +970,8 @@ CompletableFuture ensureFulltextIndex( * * @param user The name of the user * @return permissions of the user - * @see + * @see + * * API Documentation * @since ArangoDB 3.2.0 */ diff --git a/src/main/java/com/arangodb/async/ArangoCursorAsync.java b/core/src/main/java/com/arangodb/async/ArangoCursorAsync.java similarity index 100% rename from src/main/java/com/arangodb/async/ArangoCursorAsync.java rename to core/src/main/java/com/arangodb/async/ArangoCursorAsync.java diff --git a/core/src/main/java/com/arangodb/async/ArangoDBAsync.java b/core/src/main/java/com/arangodb/async/ArangoDBAsync.java new file mode 100644 index 000000000..98386c500 --- /dev/null +++ b/core/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -0,0 +1,345 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.*; +import com.arangodb.async.internal.ArangoDBAsyncImpl; +import com.arangodb.entity.*; +import com.arangodb.internal.InternalArangoDBBuilder; +import com.arangodb.internal.net.*; +import com.arangodb.model.DBCreateOptions; +import com.arangodb.model.LogOptions; +import com.arangodb.model.UserCreateOptions; +import com.arangodb.model.UserUpdateOptions; + +import javax.annotation.concurrent.ThreadSafe; +import java.util.Collection; +import java.util.ServiceLoader; +import java.util.concurrent.CompletableFuture; + +/** + * Central access point for applications to communicate with an ArangoDB server. + * + *

+ * Will be instantiated through {@link ArangoDBAsync.Builder} + *

+ * + *
+ * ArangoDBAsync arango = new ArangoDBAsync.Builder().build();
+ * ArangoDBAsync arango = new ArangoDBAsync.Builder().host("127.0.0.1", 8529).build();
+ * 
+ * + * @author Mark Vollmary + */ +@ThreadSafe +public interface ArangoDBAsync extends ArangoSerdeAccessor { + + void shutdown(); + + /** + * Updates the JWT used for requests authorization. It does not change already existing VST connections, since VST + * connections are authenticated during the initialization phase. + * + * @param jwt token to use + */ + void updateJwt(String jwt); + + /** + * Returns a handler of the system database + * + * @return database handler + */ + ArangoDatabaseAsync db(); + + /** + * Returns a handler of the database by the given name + * + * @param dbName Name of the database + * @return database handler + */ + ArangoDatabaseAsync db(final DbName dbName); + + /** + * @return entry point for accessing client metrics + */ + ArangoMetrics metrics(); + + /** + * Creates a new database + * + * @param dbName database name + * @return true if the database was created successfully. + * @see API + * Documentation + */ + CompletableFuture createDatabase(final DbName dbName); + + /** + * Creates a new database + * + * @param options Creation options + * @return true if the database was created successfully. + * @see API + * Documentation + * @since ArangoDB 3.6.0 + */ + CompletableFuture createDatabase(final DBCreateOptions options); + + /** + * Retrieves a list of all existing databases + * + * @return a list of all existing databases + * @see API + * Documentation + */ + CompletableFuture> getDatabases(); + + /** + * Retrieves a list of all databases the current user can access + * + * @return a list of all databases the current user can access + * @see API + * Documentation + */ + CompletableFuture> getAccessibleDatabases(); + + /** + * List available database to the specified user + * + * @param user The name of the user for which you want to query the databases + * @return + * @see API + * Documentation + */ + CompletableFuture> getAccessibleDatabasesFor(final String user); + + /** + * Returns the server name and version number. + * + * @return the server version, number + * @see API + * Documentation + */ + CompletableFuture getVersion(); + + /** + * Returns the server role. + * + * @return the server role + */ + CompletableFuture getRole(); + + /** + * Create a new user. This user will not have access to any database. You need permission to the _system database in + * order to execute this call. + * + * @param user The name of the user + * @param passwd The user password + * @return information about the user + * @see API Documentation + */ + CompletableFuture createUser(final String user, final String passwd); + + /** + * Create a new user. This user will not have access to any database. You need permission to the _system database in + * order to execute this call. + * + * @param user The name of the user + * @param passwd The user password + * @param options Additional properties of the user, can be null + * @return information about the user + * @see API Documentation + */ + CompletableFuture createUser(final String user, final String passwd, final UserCreateOptions options); + + /** + * Removes an existing user, identified by user. You need access to the _system database. + * + * @param user The name of the user + * @return void + * @see API Documentation + */ + CompletableFuture deleteUser(final String user); + + /** + * Fetches data about the specified user. You can fetch information about yourself or you need permission to the + * _system database in order to execute this call. + * + * @param user The name of the user + * @return information about the user + * @see API Documentation + */ + CompletableFuture getUser(final String user); + + /** + * Fetches data about all users. You can only execute this call if you have access to the _system database. + * + * @return informations about all users + * @see API + * Documentation + */ + CompletableFuture> getUsers(); + + /** + * Partially updates the data of an existing user. The name of an existing user must be specified in user. You can + * only change the password of your self. You need access to the _system database to change the active flag. + * + * @param user The name of the user + * @param options Properties of the user to be changed + * @return information about the user + * @see API Documentation + */ + CompletableFuture updateUser(final String user, final UserUpdateOptions options); + + /** + * Replaces the data of an existing user. The name of an existing user must be specified in user. You can only + * change the password of your self. You need access to the _system database to change the active flag. + * + * @param user The name of the user + * @param options Additional properties of the user, can be null + * @return information about the user + * @see API + * Documentation + */ + CompletableFuture replaceUser(final String user, final UserUpdateOptions options); + + /** + * Sets the default access level for databases for the user user. You need permission to the _system + * database in order to execute this call. + * + * @param user The name of the user + * @param permissions The permissions the user grant + * @return void + * @since ArangoDB 3.2.0 + */ + CompletableFuture grantDefaultDatabaseAccess(final String user, final Permissions permissions); + + /** + * Sets the default access level for collections for the user user. You need permission to the _system + * database in order to execute this call. + * + * @param user The name of the user + * @param permissions The permissions the user grant + * @return void + * @since ArangoDB 3.2.0 + */ + CompletableFuture grantDefaultCollectionAccess(final String user, final Permissions permissions); + + /** + * Execute custom requests. Requests can be programmatically built by setting low level detail such as method, path, + * query parameters, headers and body payload. + * This method can be used to call FOXX services, API endpoints not (yet) implemented in this driver or trigger + * async jobs, see + * Fire and Forget + * and + * Async Execution and later Result Retrieval + * + * @param request request + * @param type Deserialization target type for the response body (POJO or {@link com.arangodb.util.RawData}) + * @return response + */ + CompletableFuture> execute(final Request request, final Class type); + + /** + * Returns the server logs + * + * @param options Additional options, can be null + * @return the log messages + * @see API + * Documentation + * @since ArangoDB 3.8 + */ + CompletableFuture getLogEntries(final LogOptions options); + + /** + * Returns the server's current loglevel settings. + * + * @return the server's current loglevel settings + */ + CompletableFuture getLogLevel(); + + /** + * Modifies and returns the server's current loglevel settings. + * + * @param entity loglevel settings + * @return the server's current loglevel settings + */ + CompletableFuture setLogLevel(final LogLevelEntity entity); + + /** + * @return the list of available rules and their respective flags + * @since ArangoDB 3.10 + */ + CompletableFuture> getQueryOptimizerRules(); + + /** + * Builder class to build an instance of {@link ArangoDBAsync}. + * + * @author Mark Vollmary + */ + class Builder extends InternalArangoDBBuilder { + + private AsyncProtocolProvider asyncProtocolProvider(Protocol protocol) { + ServiceLoader loader = ServiceLoader.load(AsyncProtocolProvider.class); + for (AsyncProtocolProvider p : loader) { + if (p.supportsProtocol(protocol)) { + return p; + } + } + throw new ArangoDBException("No ProtocolProvider found for protocol: " + protocol); + } + + /** + * Returns an instance of {@link ArangoDBAsync}. + * + * @return {@link ArangoDBAsync} + */ + public ArangoDBAsync build() { + if (config.getHosts().isEmpty()) { + throw new ArangoDBException("No host has been set!"); + } + + AsyncProtocolProvider asyncProtocolProvider = asyncProtocolProvider(Protocol.VST); + ProtocolProvider protocolProvider = protocolProvider(Protocol.VST); + + config.setProtocol(Protocol.VST); + config.setProtocolModule(asyncProtocolProvider.protocolModule()); + + final ConnectionFactory asyncConnectionFactory = asyncProtocolProvider.createConnectionFactory(); + final ConnectionFactory syncConnectionFactory = protocolProvider.createConnectionFactory(); + final HostResolver asyncHostResolver = createHostResolver(createHostList(asyncConnectionFactory), asyncConnectionFactory); + final HostResolver syncHostResolver = createHostResolver(createHostList(syncConnectionFactory), syncConnectionFactory); + final HostHandler asyncHostHandler = createHostHandler(asyncHostResolver); + final HostHandler syncHostHandler = createHostHandler(syncHostResolver); + return new ArangoDBAsyncImpl( + config, + asyncHostResolver, + syncHostResolver, + asyncProtocolProvider, + protocolProvider, + asyncHostHandler, + syncHostHandler + ); + } + } +} diff --git a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java b/core/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java similarity index 79% rename from src/main/java/com/arangodb/async/ArangoDatabaseAsync.java rename to core/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java index 420034655..bbd46f8b6 100644 --- a/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java +++ b/core/src/main/java/com/arangodb/async/ArangoDatabaseAsync.java @@ -20,16 +20,16 @@ package com.arangodb.async; -import com.arangodb.ArangoDBException; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.DbName; import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.AnalyzerEntity; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; +import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -41,8 +41,8 @@ * @see Databases API Documentation * @see Query API Documentation */ -@SuppressWarnings("unused") -public interface ArangoDatabaseAsync extends ArangoSerializationAccessor { +@ThreadSafe +public interface ArangoDatabaseAsync extends ArangoSerdeAccessor { /** * Return the main entry point for the ArangoDB driver @@ -51,17 +51,6 @@ public interface ArangoDatabaseAsync extends ArangoSerializationAccessor { */ ArangoDBAsync arango(); - /** - * Returns the name of the database - * - * @return database name - * @deprecated Use {@link #dbName()} instead - */ - @Deprecated - default String name() { - return dbName().get(); - } - /** * Returns the name of the database * @@ -82,7 +71,8 @@ default String name() { * Returns the name of the used storage engine. * * @return the storage engine name - * @see API + * @see + * API * Documentation */ CompletableFuture getEngine(); @@ -157,7 +147,8 @@ default String name() { * * @param id The index-handle * @return information about the index - * @see API Documentation + * @see + * API Documentation */ CompletableFuture getIndex(final String id); @@ -166,7 +157,8 @@ default String name() { * * @param id The index handle * @return the id of the index - * @see API Documentation + * @see + * API Documentation */ CompletableFuture deleteIndex(final String id); @@ -261,9 +253,10 @@ default String name() { * @param query contains the query string to be executed * @param bindVars key/value pairs representing the bind parameters * @param options Additional options, can be null - * @param type The type of the result (POJO class, VPackSlice, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results - * @see API + * @see + * API * Documentation */ CompletableFuture> query( @@ -278,9 +271,10 @@ CompletableFuture> query( * * @param query contains the query string to be executed * @param options Additional options, can be null - * @param type The type of the result (POJO class, VPackSlice, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results - * @see API + * @see + * API * Documentation */ CompletableFuture> query( @@ -294,9 +288,10 @@ CompletableFuture> query( * * @param query contains the query string to be executed * @param bindVars key/value pairs representing the bind parameters - * @param type The type of the result (POJO class, VPackSlice, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results - * @see API + * @see + * API * Documentation */ CompletableFuture> query( @@ -309,9 +304,10 @@ CompletableFuture> query( * result list. * * @param query contains the query string to be executed - * @param type The type of the result (POJO class, VPackSlice, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results - * @see API + * @see + * API * Documentation */ CompletableFuture> query(final String query, final Class type); @@ -320,10 +316,11 @@ CompletableFuture> query( * Return an cursor from the given cursor-ID if still existing * * @param cursorId The ID of the cursor - * @param type The type of the result (POJO class, VPackSlice, String for Json, or Collection/List/Map) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @return cursor of the results * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cursor-accessing-cursors + * .html#read-next-batch-from-cursor">API * Documentation */ CompletableFuture> cursor(final String cursorId, final Class type); @@ -359,7 +356,8 @@ CompletableFuture explainQuery( * * @return void * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cache + * .html#clears-any-results-in-the-aql-query-results-cache">API * Documentation */ CompletableFuture clearQueryCache(); @@ -369,7 +367,8 @@ CompletableFuture explainQuery( * * @return configuration for the AQL query cache * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cache + * .html#returns-the-global-properties-for-the-aql-query-results-cache">API * Documentation */ CompletableFuture getQueryCacheProperties(); @@ -381,7 +380,8 @@ CompletableFuture explainQuery( * @param properties properties to be set * @return current set of properties * @see API + * "https://www.arangodb.com/docs/stable/http/aql-query-cache + * .html#globally-adjusts-the-aql-query-results-cache-properties">API * Documentation */ CompletableFuture setQueryCacheProperties(final QueryCachePropertiesEntity properties); @@ -535,7 +535,7 @@ CompletableFuture createGraph( * Execute a server-side transaction * * @param action the actual transaction operations to be executed, in the form of stringified JavaScript code - * @param type The type of the result (POJO class, VPackSlice or String for Json) + * @param type The type of the result (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the result of the transaction if it succeeded * @see API @@ -548,7 +548,8 @@ CompletableFuture createGraph( * * @param options Additional options, can be null * @return information about the transaction - * @see API + * @see + * API * Documentation * @since ArangoDB 3.5.0 */ @@ -558,7 +559,8 @@ CompletableFuture createGraph( * Aborts a Stream Transaction. * * @return information about the transaction - * @see API + * @see + * API * Documentation */ CompletableFuture abortStreamTransaction(String id); @@ -567,7 +569,8 @@ CompletableFuture createGraph( * Gets information about a Stream Transaction. * * @return information about the transaction - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ @@ -577,7 +580,8 @@ CompletableFuture createGraph( * Gets all the currently running Stream Transactions. * * @return all the currently running Stream Transactions - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ @@ -587,7 +591,8 @@ CompletableFuture createGraph( * Commits a Stream Transaction. * * @return information about the transaction - * @see + * @see + * * API Documentation * @since ArangoDB 3.5.0 */ @@ -603,53 +608,36 @@ CompletableFuture createGraph( */ CompletableFuture getInfo(); - /** - * Execute a server-side traversal - * - * @param vertexClass The type of the vertex documents (POJO class, VPackSlice or String for Json) - * @param edgeClass The type of the edge documents (POJO class, VPackSlice or String for Json) - * @param options Additional options - * @return Result of the executed traversal - * @see API - * Documentation - * @deprecated use {@link this#query(String, Map, AqlQueryOptions, Class)} - */ - @Deprecated - CompletableFuture> executeTraversal( - final Class vertexClass, - final Class edgeClass, - final TraversalOptions options); - /** * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO class, VPackSlice or String for Json) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @return the document identified by the id * @see API * Documentation */ - CompletableFuture getDocument(final String id, final Class type) throws ArangoDBException; + CompletableFuture getDocument(final String id, final Class type); /** * Reads a single document * * @param id The id of the document - * @param type The type of the document (POJO class, VPackSlice or String for Json) + * @param type The type of the document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the document identified by the id * @see API * Documentation */ - CompletableFuture getDocument(final String id, final Class type, final DocumentReadOptions options) - throws ArangoDBException; + CompletableFuture getDocument(final String id, final Class type, final DocumentReadOptions options); /** * Reload the routing table. * * @return void * @see API + * "https://www.arangodb.com/docs/stable/http/administration-and-monitoring + * .html#reloads-the-routing-information">API * Documentation */ CompletableFuture reloadRouting(); @@ -667,7 +655,8 @@ CompletableFuture getDocument(final String id, final Class type, final * Fetches all views from the database and returns an list of view descriptions. * * @return list of information about all views - * @see API Documentation + * @see + * API Documentation * @since ArangoDB 3.4.0 */ CompletableFuture> getViews(); @@ -682,7 +671,7 @@ CompletableFuture getDocument(final String id, final Class type, final ArangoViewAsync view(String name); /** - * Returns a {@code ArangoSearchAsync} instance for the given ArangoSearch view name. + * Returns a {@link ArangoSearchAsync} instance for the given ArangoSearch view name. * * @param name Name of the view * @return ArangoSearch view handler @@ -690,6 +679,15 @@ CompletableFuture getDocument(final String id, final Class type, final */ ArangoSearchAsync arangoSearch(String name); + /** + * Returns a {@link SearchAliasAsync} instance for the given view name. + * + * @param name Name of the view + * @return SearchAlias view handler + * @since ArangoDB 3.10 + */ + SearchAliasAsync searchAlias(String name); + /** * Creates a view of the given {@code type}, then returns view information from the server. * @@ -713,23 +711,22 @@ CompletableFuture getDocument(final String id, final Class type, final CompletableFuture createArangoSearch(String name, ArangoSearchCreateOptions options); /** - * Creates an Analyzer + * Creates a SearchAlias view with the given {@code options}, then returns view information from the server. * - * @param options AnalyzerEntity - * @return the created Analyzer - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#createSearchAnalyzer(SearchAnalyzer)}} + * @param name The name of the view + * @param options Additional options, can be null + * @return information about the view + * @see API + * Documentation + * @since ArangoDB 3.10 */ - @Deprecated - CompletableFuture createAnalyzer(AnalyzerEntity options); + CompletableFuture createSearchAlias(String name, SearchAliasCreateOptions options); /** * Creates an Analyzer * * @param analyzer SearchAnalyzer * @return the created Analyzer - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ @@ -742,19 +739,6 @@ CompletableFuture getDocument(final String id, final Class type, final * @return information about an Analyzer * @see API Documentation * @since ArangoDB 3.5.0 - * @deprecated use {@link this#getSearchAnalyzer(String)}} - */ - @Deprecated - CompletableFuture getAnalyzer(String name); - - /** - * Gets information about an Analyzer - * - * @param name of the Analyzer without database prefix - * @return information about an Analyzer - * @throws ArangoDBException - * @see API Documentation - * @since ArangoDB 3.5.0 */ CompletableFuture getSearchAnalyzer(String name); @@ -764,18 +748,6 @@ CompletableFuture getDocument(final String id, final Class type, final * @return collection of all analyzers definitions * @see API Documentation * @since ArangoDB 3.5.0 - * @deprecated use {@link this#getSearchAnalyzers()} - */ - @Deprecated - CompletableFuture> getAnalyzers(); - - /** - * Retrieves all analyzers definitions. - * - * @return collection of all analyzers definitions - * @throws ArangoDBException - * @see API Documentation - * @since ArangoDB 3.5.0 */ CompletableFuture> getSearchAnalyzers(); @@ -785,30 +757,6 @@ CompletableFuture getDocument(final String id, final Class type, final * @param name of the Analyzer without database prefix * @see API Documentation * @since ArangoDB 3.5.0 - * @deprecated use {@link this#deleteSearchAnalyzer(String)}}} - */ - @Deprecated - CompletableFuture deleteAnalyzer(String name); - - /** - * Deletes an Analyzer - * - * @param name of the Analyzer without database prefix - * @param options AnalyzerDeleteOptions - * @see API Documentation - * @since ArangoDB 3.5.0 - * @deprecated use {@link this#deleteSearchAnalyzer(String, AnalyzerDeleteOptions)}}} - */ - @Deprecated - CompletableFuture deleteAnalyzer(String name, AnalyzerDeleteOptions options); - - /** - * Deletes an Analyzer - * - * @param name of the Analyzer without database prefix - * @throws ArangoDBException - * @see API Documentation - * @since ArangoDB 3.5.0 */ CompletableFuture deleteSearchAnalyzer(String name); @@ -817,7 +765,6 @@ CompletableFuture getDocument(final String id, final Class type, final * * @param name of the Analyzer without database prefix * @param options AnalyzerDeleteOptions - * @throws ArangoDBException * @see API Documentation * @since ArangoDB 3.5.0 */ diff --git a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java b/core/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java similarity index 83% rename from src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java rename to core/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java index 2dea8807c..22d9b791b 100644 --- a/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java +++ b/core/src/main/java/com/arangodb/async/ArangoEdgeCollectionAsync.java @@ -20,11 +20,12 @@ package com.arangodb.async; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.entity.EdgeEntity; import com.arangodb.entity.EdgeUpdateEntity; import com.arangodb.model.*; +import javax.annotation.concurrent.ThreadSafe; import java.util.concurrent.CompletableFuture; /** @@ -33,8 +34,8 @@ * @author Mark Vollmary * @see API Documentation */ -@SuppressWarnings("unused") -public interface ArangoEdgeCollectionAsync extends ArangoSerializationAccessor { +@ThreadSafe +public interface ArangoEdgeCollectionAsync extends ArangoSerdeAccessor { /** * The the handler of the named graph the edge collection is within @@ -53,27 +54,27 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerializationAccessor { /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, VPackSlice or String for Json) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData} * @return information about the edge * @see API Documentation */ - CompletableFuture insertEdge(final T value); + CompletableFuture insertEdge(final Object value); /** * Creates a new edge in the collection * - * @param value A representation of a single edge (POJO, VPackSlice or String for Json) + * @param value A representation of a single edge (POJO or {@link com.arangodb.util.RawData} * @param options Additional options, can be null * @return information about the edge * @see API Documentation */ - CompletableFuture insertEdge(final T value, final EdgeCreateOptions options); + CompletableFuture insertEdge(final Object value, final EdgeCreateOptions options); /** * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO class, VPackSlice or String for Json) + * @param type The type of the edge-document (POJO or {@link com.arangodb.util.RawData} * @return the edge identified by the key * @see API Documentation */ @@ -83,7 +84,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerializationAccessor { * Fetches an existing edge * * @param key The key of the edge - * @param type The type of the edge-document (POJO class, VPackSlice or String for Json) + * @param type The type of the edge-document (POJO or {@link com.arangodb.util.RawData} * @param options Additional options, can be null * @return the edge identified by the key * @see API Documentation @@ -98,7 +99,7 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerializationAccessor { * @return information about the edge * @see API Documentation */ - CompletableFuture replaceEdge(final String key, final T value); + CompletableFuture replaceEdge(final String key, final Object value); /** * Replaces the edge with key with the one in the body, provided there is such a edge and no precondition is @@ -109,9 +110,9 @@ public interface ArangoEdgeCollectionAsync extends ArangoSerializationAccessor { * @return information about the edge * @see API Documentation */ - CompletableFuture replaceEdge( + CompletableFuture replaceEdge( final String key, - final T value, + final Object value, final EdgeReplaceOptions options); /** @@ -123,7 +124,7 @@ CompletableFuture replaceEdge( * @return information about the edge * @see API Documentation */ - CompletableFuture updateEdge(final String key, final T value); + CompletableFuture updateEdge(final String key, final Object value); /** * Partially updates the edge identified by document-key. The value must contain a document with the attributes to @@ -135,9 +136,9 @@ CompletableFuture replaceEdge( * @return information about the edge * @see API Documentation */ - CompletableFuture updateEdge( + CompletableFuture updateEdge( final String key, - final T value, + final Object value, final EdgeUpdateOptions options); /** diff --git a/src/main/java/com/arangodb/async/ArangoGraphAsync.java b/core/src/main/java/com/arangodb/async/ArangoGraphAsync.java similarity index 90% rename from src/main/java/com/arangodb/async/ArangoGraphAsync.java rename to core/src/main/java/com/arangodb/async/ArangoGraphAsync.java index 17cb45a95..ebf014c38 100644 --- a/src/main/java/com/arangodb/async/ArangoGraphAsync.java +++ b/core/src/main/java/com/arangodb/async/ArangoGraphAsync.java @@ -20,12 +20,13 @@ package com.arangodb.async; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.GraphEntity; import com.arangodb.model.GraphCreateOptions; import com.arangodb.model.VertexCollectionCreateOptions; +import javax.annotation.concurrent.ThreadSafe; import java.util.Collection; import java.util.concurrent.CompletableFuture; @@ -35,8 +36,8 @@ * @author Mark Vollmary * @see API Documentation */ -@SuppressWarnings("unused") -public interface ArangoGraphAsync extends ArangoSerializationAccessor { +@ThreadSafe +public interface ArangoGraphAsync extends ArangoSerdeAccessor { /** * The the handler of the database the named graph is within @@ -88,17 +89,20 @@ CompletableFuture createGraph( * Delete an existing graph * * @return void - * @see API Documentation + * @see + * API Documentation */ CompletableFuture drop(); /** * Delete an existing graph including * - * @param dropCollections Drop collections of this graph as well. Collections will only be dropped if they are not used in other + * @param dropCollections Drop collections of this graph as well. Collections will only be dropped if they are + * not used in other * graphs. * @return void - * @see API Documentation + * @see + * API Documentation */ CompletableFuture drop(boolean dropCollections); @@ -106,7 +110,8 @@ CompletableFuture createGraph( * Get a graph from the graph module * * @return the definition content of this graph - * @see API Documentation + * @see + * API Documentation */ CompletableFuture getInfo(); @@ -134,7 +139,7 @@ CompletableFuture createGraph( * Adds a vertex collection to the set of collections of the graph. If the collection does not exist, it will be * created. * - * @param name The name of the collection + * @param name The name of the collection * @param options additional options * @return information about the graph * @see API diff --git a/src/main/java/com/arangodb/async/ArangoRouteAsync.java b/core/src/main/java/com/arangodb/async/ArangoRouteAsync.java similarity index 84% rename from src/main/java/com/arangodb/async/ArangoRouteAsync.java rename to core/src/main/java/com/arangodb/async/ArangoRouteAsync.java index ab384f99b..c2ab2d221 100644 --- a/src/main/java/com/arangodb/async/ArangoRouteAsync.java +++ b/core/src/main/java/com/arangodb/async/ArangoRouteAsync.java @@ -20,8 +20,8 @@ package com.arangodb.async; -import com.arangodb.ArangoSerializationAccessor; -import com.arangodb.velocystream.Response; +import com.arangodb.ArangoSerdeAccessor; +import com.arangodb.internal.InternalResponse; import java.util.concurrent.CompletableFuture; @@ -30,8 +30,7 @@ * * @author Mark Vollmary */ -@SuppressWarnings("unused") -public interface ArangoRouteAsync extends ArangoSerializationAccessor { +public interface ArangoRouteAsync extends ArangoSerdeAccessor { /** * Returns a new {@link ArangoRouteAsync} instance for the given path (relative to the current route) that can be @@ -61,7 +60,7 @@ public interface ArangoRouteAsync extends ArangoSerializationAccessor { ArangoRouteAsync withQueryParam(String key, Object value); /** - * The response body. The body will be serialized to {@link com.arangodb.velocypack.VPackSlice}. + * The response body. * * @param body The response body * @return {@link ArangoRouteAsync} @@ -73,7 +72,7 @@ public interface ArangoRouteAsync extends ArangoSerializationAccessor { * * @return server response */ - CompletableFuture delete(); + CompletableFuture delete(); /** * Performs a GET request to the given URL and returns the server response. @@ -81,7 +80,7 @@ public interface ArangoRouteAsync extends ArangoSerializationAccessor { * @return server response */ - CompletableFuture get(); + CompletableFuture get(); /** * Performs a HEAD request to the given URL and returns the server response. @@ -89,7 +88,7 @@ public interface ArangoRouteAsync extends ArangoSerializationAccessor { * @return server response */ - CompletableFuture head(); + CompletableFuture head(); /** * Performs a PATCH request to the given URL and returns the server response. @@ -97,7 +96,7 @@ public interface ArangoRouteAsync extends ArangoSerializationAccessor { * @return server response */ - CompletableFuture patch(); + CompletableFuture patch(); /** * Performs a POST request to the given URL and returns the server response. @@ -105,7 +104,7 @@ public interface ArangoRouteAsync extends ArangoSerializationAccessor { * @return server response */ - CompletableFuture post(); + CompletableFuture post(); /** * Performs a PUT request to the given URL and returns the server response. @@ -113,6 +112,6 @@ public interface ArangoRouteAsync extends ArangoSerializationAccessor { * @return server response */ - CompletableFuture put(); + CompletableFuture put(); } diff --git a/src/main/java/com/arangodb/async/ArangoSearchAsync.java b/core/src/main/java/com/arangodb/async/ArangoSearchAsync.java similarity index 94% rename from src/main/java/com/arangodb/async/ArangoSearchAsync.java rename to core/src/main/java/com/arangodb/async/ArangoSearchAsync.java index d738012c1..77f112a0d 100644 --- a/src/main/java/com/arangodb/async/ArangoSearchAsync.java +++ b/core/src/main/java/com/arangodb/async/ArangoSearchAsync.java @@ -25,15 +25,17 @@ import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; +import javax.annotation.concurrent.ThreadSafe; import java.util.concurrent.CompletableFuture; /** * Interface for operations on ArangoDB view level for ArangoSearch views. * * @author Mark Vollmary - * @see View API Documentation + * @see View API Documentation * @since ArangoDB 3.4.0 */ +@ThreadSafe public interface ArangoSearchAsync extends ArangoViewAsync { /** @@ -70,7 +72,8 @@ public interface ArangoSearchAsync extends ArangoViewAsync { * @param options properties to change * @return properties of the view @ * @see API + * "https://www.arangodb.com/docs/stable/http/views-arangosearch + * .html#partially-changes-properties-of-an-arangosearch-view">API * Documentation */ CompletableFuture updateProperties(ArangoSearchPropertiesOptions options); diff --git a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java b/core/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java similarity index 72% rename from src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java rename to core/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java index b610a9796..986aa011e 100644 --- a/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java +++ b/core/src/main/java/com/arangodb/async/ArangoVertexCollectionAsync.java @@ -20,11 +20,12 @@ package com.arangodb.async; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.entity.VertexEntity; import com.arangodb.entity.VertexUpdateEntity; import com.arangodb.model.*; +import javax.annotation.concurrent.ThreadSafe; import java.util.concurrent.CompletableFuture; /** @@ -33,8 +34,8 @@ * @author Mark Vollmary * @see API Documentation */ -@SuppressWarnings("unused") -public interface ArangoVertexCollectionAsync extends ArangoSerializationAccessor { +@ThreadSafe +public interface ArangoVertexCollectionAsync extends ArangoSerdeAccessor { /** * The the handler of the named graph the edge collection is within @@ -63,27 +64,29 @@ public interface ArangoVertexCollectionAsync extends ArangoSerializationAccessor /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, VPackSlice or String for Json) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @return information about the vertex - * @see API Documentation + * @see + * API Documentation */ - CompletableFuture insertVertex(final T value); + CompletableFuture insertVertex(final Object value); /** * Creates a new vertex in the collection * - * @param value A representation of a single vertex (POJO, VPackSlice or String for Json) + * @param value A representation of a single vertex (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return information about the vertex - * @see API Documentation + * @see + * API Documentation */ - CompletableFuture insertVertex(final T value, final VertexCreateOptions options); + CompletableFuture insertVertex(final Object value, final VertexCreateOptions options); /** * Fetches an existing vertex * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO class, VPackSlice or String for Json) + * @param type The type of the vertex-document (POJO or {@link com.arangodb.util.RawData}) * @return the vertex identified by the key * @see API Documentation */ @@ -93,7 +96,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerializationAccessor * Fetches an existing vertex * * @param key The key of the vertex - * @param type The type of the vertex-document (POJO class, VPackSlice or String for Json) + * @param type The type of the vertex-document (POJO or {@link com.arangodb.util.RawData}) * @param options Additional options, can be null * @return the vertex identified by the key * @see API Documentation @@ -109,7 +112,7 @@ public interface ArangoVertexCollectionAsync extends ArangoSerializationAccessor * @see API * Documentation */ - CompletableFuture replaceVertex(final String key, final T value); + CompletableFuture replaceVertex(final String key, final Object value); /** * Replaces the vertex with key with the one in the body, provided there is such a vertex and no precondition is @@ -121,9 +124,9 @@ public interface ArangoVertexCollectionAsync extends ArangoSerializationAccessor * @see API * Documentation */ - CompletableFuture replaceVertex( + CompletableFuture replaceVertex( final String key, - final T value, + final Object value, final VertexReplaceOptions options); /** @@ -133,9 +136,10 @@ CompletableFuture replaceVertex( * * @param key The key of the vertex * @return information about the vertex - * @see API Documentation + * @see + * API Documentation */ - CompletableFuture updateVertex(final String key, final T value); + CompletableFuture updateVertex(final String key, final Object value); /** * Partially updates the vertex identified by document-key. The value must contain a document with the attributes to @@ -145,18 +149,20 @@ CompletableFuture replaceVertex( * @param key The key of the vertex * @param options Additional options, can be null * @return information about the vertex - * @see API Documentation + * @see + * API Documentation */ - CompletableFuture updateVertex( + CompletableFuture updateVertex( final String key, - final T value, + final Object value, final VertexUpdateOptions options); /** * Removes a vertex * * @param key The key of the vertex - * @see API Documentation + * @see + * API Documentation */ CompletableFuture deleteVertex(final String key); @@ -165,7 +171,8 @@ CompletableFuture updateVertex( * * @param key The key of the vertex * @param options Additional options, can be null - * @see API Documentation + * @see + * API Documentation */ CompletableFuture deleteVertex(final String key, final VertexDeleteOptions options); diff --git a/src/main/java/com/arangodb/async/ArangoViewAsync.java b/core/src/main/java/com/arangodb/async/ArangoViewAsync.java similarity index 77% rename from src/main/java/com/arangodb/async/ArangoViewAsync.java rename to core/src/main/java/com/arangodb/async/ArangoViewAsync.java index fed3da081..68fa883dc 100644 --- a/src/main/java/com/arangodb/async/ArangoViewAsync.java +++ b/core/src/main/java/com/arangodb/async/ArangoViewAsync.java @@ -20,9 +20,10 @@ package com.arangodb.async; -import com.arangodb.ArangoSerializationAccessor; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.entity.ViewEntity; +import javax.annotation.concurrent.ThreadSafe; import java.util.concurrent.CompletableFuture; /** @@ -32,8 +33,8 @@ * @see View API Documentation * @since ArangoDB 3.4.0 */ -@SuppressWarnings("unused") -public interface ArangoViewAsync extends ArangoSerializationAccessor { +@ThreadSafe +public interface ArangoViewAsync extends ArangoSerdeAccessor { /** * The the handler of the database the collection is within @@ -59,7 +60,8 @@ public interface ArangoViewAsync extends ArangoSerializationAccessor { /** * Deletes the view from the database. * - * @see API Documentation + * @see + * API Documentation */ CompletableFuture drop(); @@ -68,7 +70,8 @@ public interface ArangoViewAsync extends ArangoSerializationAccessor { * * @param newName The new name * @return information about the view - * @see API Documentation + * @see + * API Documentation */ CompletableFuture rename(String newName); @@ -76,7 +79,8 @@ public interface ArangoViewAsync extends ArangoSerializationAccessor { * Returns information about the view. * * @return information about the view - * @see API + * @see + * API * Documentation */ CompletableFuture getInfo(); diff --git a/core/src/main/java/com/arangodb/async/SearchAliasAsync.java b/core/src/main/java/com/arangodb/async/SearchAliasAsync.java new file mode 100644 index 000000000..cfb6d8a84 --- /dev/null +++ b/core/src/main/java/com/arangodb/async/SearchAliasAsync.java @@ -0,0 +1,89 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async; + +import com.arangodb.entity.ViewEntity; +import com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasPropertiesOptions; + +import java.util.concurrent.CompletableFuture; + +/** + * Interface for operations on ArangoDB view level for SearchAlias views. + * + * @author Michele Rastelli + * @see View API Documentation + * @since ArangoDB 3.10 + */ +public interface SearchAliasAsync extends ArangoViewAsync { + + /** + * Creates a view, then returns view information from the server. + * + * @return information about the view + * @see API + * Documentation + */ + CompletableFuture create(); + + /** + * Creates a view with the given {@code options}, then returns view information from the server. + * + * @param options Additional options, can be null + * @return information about the view + * @see API + * Documentation + */ + CompletableFuture create(SearchAliasCreateOptions options); + + /** + * Reads the properties of the specified view. + * + * @return properties of the view + * @see API + * Documentation + */ + CompletableFuture getProperties(); + + /** + * Partially changes properties of the view. + * + * @param options properties to change + * @return properties of the view + * @see API + * Documentation + */ + CompletableFuture updateProperties(SearchAliasPropertiesOptions options); + + /** + * Changes properties of the view. + * + * @param options properties to change + * @return properties of the view + * @see API + * Documentation + */ + CompletableFuture replaceProperties(SearchAliasPropertiesOptions options); + +} diff --git a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java similarity index 60% rename from src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java index 036f16da2..f521ab329 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java +++ b/core/src/main/java/com/arangodb/async/internal/ArangoCollectionAsyncImpl.java @@ -20,17 +20,19 @@ package com.arangodb.async.internal; -import com.arangodb.ArangoDBException; import com.arangodb.async.ArangoCollectionAsync; import com.arangodb.entity.*; import com.arangodb.internal.InternalArangoCollection; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.model.*; +import com.arangodb.util.RawData; import java.util.Collection; import java.util.Objects; import java.util.concurrent.CompletableFuture; +import static com.arangodb.internal.serde.SerdeUtils.constructParametricType; + /** * @author Mark Vollmary * @author Michele Rastelli @@ -44,35 +46,63 @@ public class ArangoCollectionAsyncImpl } @Override - public CompletableFuture> insertDocument(final T value) { - final DocumentCreateOptions options = new DocumentCreateOptions(); - return executor.execute(insertDocumentRequest(value, options), - insertDocumentResponseDeserializer(value, options)); + public CompletableFuture> insertDocument(final Object value) { + return executor.execute(insertDocumentRequest(value, new DocumentCreateOptions()), + constructParametricType(DocumentCreateEntity.class, Void.class)); } @Override + @SuppressWarnings("unchecked") public CompletableFuture> insertDocument( final T value, final DocumentCreateOptions options) { + return insertDocument(value, options, (Class) value.getClass()); + } + + @Override + public CompletableFuture> insertDocument(T value, DocumentCreateOptions options, + Class type) { return executor.execute(insertDocumentRequest(value, options), - insertDocumentResponseDeserializer(value, options)); + constructParametricType(DocumentCreateEntity.class, type)); } @Override - public CompletableFuture>> insertDocuments( - final Collection values) { - final DocumentCreateOptions params = new DocumentCreateOptions(); - return executor.execute(insertDocumentsRequest(values, params), - insertDocumentsResponseDeserializer(values, params)); + public CompletableFuture>> insertDocuments(RawData values) { + return executor + .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), + insertDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture>> insertDocuments(RawData values, + DocumentCreateOptions options) { + return executor + .execute(insertDocumentsRequest(values, options), + insertDocumentsResponseDeserializer((Class) values.getClass())); + } + + @Override + public CompletableFuture>> insertDocuments( + final Collection values) { + return executor + .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), + insertDocumentsResponseDeserializer(Void.class)); } @Override + @SuppressWarnings("unchecked") public CompletableFuture>> insertDocuments( final Collection values, final DocumentCreateOptions options) { - final DocumentCreateOptions params = (options != null ? options : new DocumentCreateOptions()); - return executor.execute(insertDocumentsRequest(values, params), - insertDocumentsResponseDeserializer(values, params)); + return insertDocuments(values, options, (Class) getCollectionContentClass(values)); + } + + @Override + public CompletableFuture>> insertDocuments(Collection values, + DocumentCreateOptions options, Class type) { + return executor + .execute(insertDocumentsRequest(values, options), insertDocumentsResponseDeserializer(type)); } @Override @@ -88,33 +118,29 @@ public CompletableFuture importDocuments( } @Override - public CompletableFuture importDocuments(final String values) { + public CompletableFuture importDocuments(RawData values) { return executor.execute(importDocumentsRequest(values, new DocumentImportOptions()), DocumentImportEntity.class); } @Override - public CompletableFuture importDocuments( - final String values, - final DocumentImportOptions options) { + public CompletableFuture importDocuments(RawData values, DocumentImportOptions options) { return executor.execute(importDocumentsRequest(values, options), DocumentImportEntity.class); } @Override - public CompletableFuture getDocument(final String key, final Class type) throws ArangoDBException { + public CompletableFuture getDocument(final String key, final Class type) { return getDocument(key, type, new DocumentReadOptions()); } @Override - @SuppressWarnings("unchecked") public CompletableFuture getDocument( final String key, final Class type, - final DocumentReadOptions options) throws ArangoDBException { + final DocumentReadOptions options) { DocumentUtil.validateDocumentKey(key); - boolean isCatchException = options != null ? options.isCatchException() : new DocumentReadOptions().isCatchException(); - return (CompletableFuture) executor.execute(getDocumentRequest(key, options), type) - .exceptionally(ExceptionUtil.catchGetDocumentExceptions(isCatchException)); + return executor.execute(getDocumentRequest(key, options), getDocumentResponseDeserializer(type)) + .exceptionally(ExceptionUtil.catchGetDocumentExceptions()); } @Override @@ -129,48 +155,75 @@ public CompletableFuture> getDocuments( final Collection keys, final Class type, final DocumentReadOptions options) { - return executor.execute(getDocumentsRequest(keys, options), getDocumentsResponseDeserializer(type, options)); + return executor.execute(getDocumentsRequest(keys, options), getDocumentsResponseDeserializer(type)); } @Override - public CompletableFuture> replaceDocument(final String key, final T value) { + public CompletableFuture> replaceDocument(final String key, final Object value) { final DocumentReplaceOptions options = new DocumentReplaceOptions(); return executor.execute(replaceDocumentRequest(key, value, options), - replaceDocumentResponseDeserializer(value, options)); + constructParametricType(DocumentUpdateEntity.class, Void.class)); } @Override + @SuppressWarnings("unchecked") public CompletableFuture> replaceDocument( final String key, final T value, final DocumentReplaceOptions options) { + return replaceDocument(key, value, options, (Class) value.getClass()); + } + + @Override + public CompletableFuture> replaceDocument(String key, T value, + DocumentReplaceOptions options, + Class type) { return executor.execute(replaceDocumentRequest(key, value, options), - replaceDocumentResponseDeserializer(value, options)); + constructParametricType(DocumentUpdateEntity.class, type)); } @Override - public CompletableFuture>> replaceDocuments( - final Collection values) { - final DocumentReplaceOptions params = new DocumentReplaceOptions(); - return executor.execute(replaceDocumentsRequest(values, params), - replaceDocumentsResponseDeserializer(values, params)); + public CompletableFuture>> replaceDocuments(RawData values) { + return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), + replaceDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture>> replaceDocuments(RawData values, + DocumentReplaceOptions options) { + return executor.execute(replaceDocumentsRequest(values, options), + replaceDocumentsResponseDeserializer((Class) values.getClass())); + } + + @Override + public CompletableFuture>> replaceDocuments( + final Collection values) { + return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), + replaceDocumentsResponseDeserializer(Void.class)); } @Override + @SuppressWarnings("unchecked") public CompletableFuture>> replaceDocuments( final Collection values, final DocumentReplaceOptions options) { - final DocumentReplaceOptions params = (options != null ? options : new DocumentReplaceOptions()); - return executor.execute(replaceDocumentsRequest(values, params), - replaceDocumentsResponseDeserializer(values, params)); + return replaceDocuments(values, options, (Class) getCollectionContentClass(values)); + } + + @Override + public CompletableFuture>> replaceDocuments(Collection values, + DocumentReplaceOptions options, Class type) { + return executor.execute(replaceDocumentsRequest(values, options), replaceDocumentsResponseDeserializer(type)); } @Override - public CompletableFuture> updateDocument(final String key, final T value) { - return updateDocument(key, value, new DocumentUpdateOptions()); + public CompletableFuture> updateDocument(final String key, final Object value) { + return updateDocument(key, value, new DocumentUpdateOptions(), Void.class); } @Override + @SuppressWarnings("unchecked") public CompletableFuture> updateDocument( final String key, final T value, @@ -179,64 +232,105 @@ public CompletableFuture> updateDocument( } @Override - public CompletableFuture> updateDocument( + public CompletableFuture> updateDocument( final String key, - final T value, + final Object value, final DocumentUpdateOptions options, - final Class returnType) { + final Class returnType) { return executor.execute(updateDocumentRequest(key, value, options), - updateDocumentResponseDeserializer(value, options, returnType)); + constructParametricType(DocumentUpdateEntity.class, returnType)); } @Override - public CompletableFuture>> updateDocuments( - final Collection values) { - return updateDocuments(values, new DocumentUpdateOptions()); + public CompletableFuture>> updateDocuments(RawData values) { + return executor + .execute(updateDocumentsRequest(values, new DocumentUpdateOptions()), + updateDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture>> updateDocuments(RawData values, + DocumentUpdateOptions options) { + return executor + .execute(updateDocumentsRequest(values, options), + updateDocumentsResponseDeserializer((Class) values.getClass())); + } + + @Override + public CompletableFuture>> updateDocuments( + final Collection values) { + return updateDocuments(values, new DocumentUpdateOptions(), Void.class); } @Override + @SuppressWarnings("unchecked") public CompletableFuture>> updateDocuments( final Collection values, final DocumentUpdateOptions options) { - return updateDocuments(values, options, values.isEmpty() ? null : (Class) values.iterator().next().getClass()); + return updateDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override - public CompletableFuture>> updateDocuments( - final Collection values, + public CompletableFuture>> updateDocuments( + final Collection values, final DocumentUpdateOptions options, - final Class returnType) { - final DocumentUpdateOptions params = (options != null ? options : new DocumentUpdateOptions()); - return executor.execute(updateDocumentsRequest(values, params), - updateDocumentsResponseDeserializer(returnType)); + final Class returnType) { + return executor + .execute(updateDocumentsRequest(values, options), updateDocumentsResponseDeserializer(returnType)); } @Override public CompletableFuture> deleteDocument(final String key) { - return executor.execute(deleteDocumentRequest(key, new DocumentDeleteOptions()), - deleteDocumentResponseDeserializer(Void.class)); + return deleteDocument(key, new DocumentDeleteOptions()); + } + + @Override + public CompletableFuture> deleteDocument(String key, DocumentDeleteOptions options) { + return deleteDocument(key, options, Void.class); } @Override public CompletableFuture> deleteDocument( final String key, - final Class type, - final DocumentDeleteOptions options) { - return executor.execute(deleteDocumentRequest(key, options), deleteDocumentResponseDeserializer(type)); + final DocumentDeleteOptions options, + final Class type) { + return executor.execute(deleteDocumentRequest(key, options), + constructParametricType(DocumentDeleteEntity.class, type)); } @Override - public CompletableFuture>> deleteDocuments( - final Collection values) { + public CompletableFuture>> deleteDocuments(RawData values) { return executor.execute(deleteDocumentsRequest(values, new DocumentDeleteOptions()), deleteDocumentsResponseDeserializer(Void.class)); } + @Override + @SuppressWarnings("unchecked") + public CompletableFuture>> deleteDocuments(RawData values, + DocumentDeleteOptions options) { + return executor.execute(deleteDocumentsRequest(values, options), + deleteDocumentsResponseDeserializer((Class) values.getClass())); + } + + @Override + public CompletableFuture>> deleteDocuments( + final Collection values) { + return deleteDocuments(values, new DocumentDeleteOptions(), Void.class); + } + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture>> deleteDocuments(Collection values, + DocumentDeleteOptions options) { + return deleteDocuments(values, options, (Class) getCollectionContentClass(values)); + } + @Override public CompletableFuture>> deleteDocuments( final Collection values, - final Class type, - final DocumentDeleteOptions options) { + final DocumentDeleteOptions options, + final Class type) { return executor.execute(deleteDocumentsRequest(values, options), deleteDocumentsResponseDeserializer(type)); } @@ -247,9 +341,8 @@ public CompletableFuture documentExists(final String key) { @Override public CompletableFuture documentExists(final String key, final DocumentExistsOptions options) { - boolean isCatchException = options != null ? options.isCatchException() : new DocumentExistsOptions().isCatchException(); return executor.execute(documentExistsRequest(key, options), response -> response) - .exceptionally(ExceptionUtil.catchGetDocumentExceptions(isCatchException)) + .exceptionally(ExceptionUtil.catchGetDocumentExceptions()) .thenApply(Objects::nonNull); } @@ -258,6 +351,11 @@ public CompletableFuture getIndex(final String id) { return executor.execute(getIndexRequest(id), IndexEntity.class); } + @Override + public CompletableFuture getInvertedIndex(String id) { + return executor.execute(getIndexRequest(id), InvertedIndexEntity.class); + } + @Override public CompletableFuture deleteIndex(final String id) { return executor.execute(deleteIndexRequest(id), deleteIndexResponseDeserializer()); @@ -291,6 +389,7 @@ public CompletableFuture ensureGeoIndex(final Iterable fiel return executor.execute(createGeoIndexRequest(fields, options), IndexEntity.class); } + @Deprecated @Override public CompletableFuture ensureFulltextIndex( final Iterable fields, @@ -310,11 +409,21 @@ public CompletableFuture ensureZKDIndex( return executor.execute(createZKDIndexRequest(fields, options), IndexEntity.class); } + @Override + public CompletableFuture ensureInvertedIndex(InvertedIndexOptions options) { + return executor.execute(createInvertedIndexRequest(options), InvertedIndexEntity.class); + } + @Override public CompletableFuture> getIndexes() { return executor.execute(getIndexesRequest(), getIndexesResponseDeserializer()); } + @Override + public CompletableFuture> getInvertedIndexes() { + return executor.execute(getIndexesRequest(), getInvertedIndexesResponseDeserializer()); + } + @Override public CompletableFuture exists() { return getInfo().thenApply(Objects::nonNull).exceptionally(Objects::isNull); @@ -360,16 +469,6 @@ public CompletableFuture drop(final boolean isSystem) { return executor.execute(dropRequest(isSystem), Void.class); } - @Override - public CompletableFuture load() { - return executor.execute(loadRequest(), CollectionEntity.class); - } - - @Override - public CompletableFuture unload() { - return executor.execute(unloadRequest(), CollectionEntity.class); - } - @Override public CompletableFuture getInfo() { return executor.execute(getInfoRequest(), CollectionEntity.class); diff --git a/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java similarity index 91% rename from src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java index 14988eca3..e8861a49e 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java +++ b/core/src/main/java/com/arangodb/async/internal/ArangoCursorAsyncImpl.java @@ -21,10 +21,10 @@ package com.arangodb.async.internal; import com.arangodb.async.ArangoCursorAsync; -import com.arangodb.entity.CursorEntity; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; import com.arangodb.internal.cursor.ArangoCursorImpl; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; import java.util.Spliterator; import java.util.Spliterators; @@ -37,7 +37,7 @@ public class ArangoCursorAsyncImpl extends ArangoCursorImpl implements ArangoCursorAsync { ArangoCursorAsyncImpl(final InternalArangoDatabase db, final ArangoCursorExecute execute, - final Class type, final CursorEntity result) { + final Class type, final InternalCursorEntity result) { super(db, execute, type, result); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java similarity index 76% rename from src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java index 170e4d1a7..12e946976 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java +++ b/core/src/main/java/com/arangodb/async/internal/ArangoDBAsyncImpl.java @@ -20,29 +20,23 @@ package com.arangodb.async.internal; -import com.arangodb.ArangoDBException; import com.arangodb.ArangoMetrics; import com.arangodb.DbName; +import com.arangodb.Request; +import com.arangodb.Response; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.async.internal.velocystream.VstCommunicationAsync; import com.arangodb.entity.*; -import com.arangodb.internal.*; -import com.arangodb.internal.net.CommunicationProtocol; -import com.arangodb.internal.net.HostHandler; -import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; -import com.arangodb.internal.velocystream.VstCommunication; -import com.arangodb.internal.velocystream.VstCommunicationSync; -import com.arangodb.internal.velocystream.VstProtocol; -import com.arangodb.internal.velocystream.internal.VstConnectionSync; +import com.arangodb.internal.ArangoExecutorSync; +import com.arangodb.internal.ArangoMetricsImpl; +import com.arangodb.internal.InternalArangoDB; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.*; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.DBCreateOptions; import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,32 +56,22 @@ public class ArangoDBAsyncImpl extends InternalArangoDB imp private final HostHandler syncHostHandler; public ArangoDBAsyncImpl( - final VstCommunicationAsync.Builder asyncCommBuilder, - final ArangoSerializationFactory util, - final VstCommunicationSync.Builder syncCommBuilder, + final ArangoConfig config, final HostResolver asyncHostResolver, final HostResolver syncHostResolver, + final AsyncProtocolProvider asyncProtocolProvider, + final ProtocolProvider protocolProvider, final HostHandler asyncHostHandler, - final HostHandler syncHostHandler, - final ArangoContext context, - final int responseQueueTimeSamples, - final int timeoutMs + final HostHandler syncHostHandler ) { - - super(new ArangoExecutorAsync(asyncCommBuilder.build(util.get(Serializer.INTERNAL)), util, new DocumentCache(), - new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), util, context); - - final VstCommunication cacheCom = syncCommBuilder.build(util.get(Serializer.INTERNAL)); - - cp = new VstProtocol(cacheCom); + super(new ArangoExecutorAsync(asyncProtocolProvider.createCommunication(config, asyncHostHandler), config), config.getInternalSerde()); + cp = protocolProvider.createProtocol(config, syncHostHandler); this.asyncHostHandler = asyncHostHandler; this.syncHostHandler = syncHostHandler; - ArangoExecutorSync arangoExecutorSync = new ArangoExecutorSync(cp, util, new DocumentCache(), - new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs); - asyncHostResolver.init(arangoExecutorSync, util.get(Serializer.INTERNAL)); - syncHostResolver.init(arangoExecutorSync, util.get(Serializer.INTERNAL)); - + ArangoExecutorSync arangoExecutorSync = new ArangoExecutorSync(cp, config); + asyncHostResolver.init(arangoExecutorSync, config.getInternalSerde()); + syncHostResolver.init(arangoExecutorSync, config.getInternalSerde()); } @Override @@ -96,7 +80,7 @@ protected ArangoExecutorAsync executor() { } @Override - public void shutdown() throws ArangoDBException { + public void shutdown() { try { executor.disconnect(); } finally { @@ -217,13 +201,8 @@ public CompletableFuture grantDefaultCollectionAccess(final String user, f } @Override - public CompletableFuture execute(final Request request) { - return executor.execute(request, response -> response); - } - - @Override - public CompletableFuture getLogs(final LogOptions options) { - return executor.execute(getLogsRequest(options), LogEntity.class); + public CompletableFuture> execute(Request request, Class type) { + return executor.execute(executeRequest(request), responseDeserializer(type)); } @Override @@ -240,4 +219,10 @@ public CompletableFuture getLogLevel() { public CompletableFuture setLogLevel(final LogLevelEntity entity) { return executor.execute(setLogLevelRequest(entity), LogLevelEntity.class); } + + @Override + public CompletableFuture> getQueryOptimizerRules() { + return executor.execute(getQueryOptimizerRulesRequest(), SerdeUtils.constructListType(QueryOptimizerRule.class)); + } + } diff --git a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java similarity index 82% rename from src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java index 61fed58d9..b8ab7b0aa 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java +++ b/core/src/main/java/com/arangodb/async/internal/ArangoDatabaseAsyncImpl.java @@ -22,37 +22,20 @@ import com.arangodb.ArangoDBException; import com.arangodb.DbName; -import com.arangodb.async.ArangoCollectionAsync; -import com.arangodb.async.ArangoCursorAsync; -import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.async.ArangoGraphAsync; -import com.arangodb.async.ArangoRouteAsync; -import com.arangodb.async.ArangoSearchAsync; -import com.arangodb.async.ArangoViewAsync; +import com.arangodb.async.*; import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.AnalyzerEntity; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.ArangoErrors; import com.arangodb.internal.InternalArangoDatabase; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.util.DocumentUtil; -import com.arangodb.model.AqlFunctionCreateOptions; -import com.arangodb.model.AqlFunctionDeleteOptions; -import com.arangodb.model.AqlFunctionGetOptions; -import com.arangodb.model.AqlQueryExplainOptions; -import com.arangodb.model.AqlQueryOptions; -import com.arangodb.model.CollectionCreateOptions; -import com.arangodb.model.CollectionsReadOptions; -import com.arangodb.model.DocumentReadOptions; -import com.arangodb.model.GraphCreateOptions; -import com.arangodb.model.StreamTransactionOptions; -import com.arangodb.model.TransactionOptions; -import com.arangodb.model.TraversalOptions; +import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import com.arangodb.velocypack.Type; -import com.arangodb.velocystream.Request; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; +import com.arangodb.internal.InternalRequest; import java.util.Collection; import java.util.Collections; @@ -61,6 +44,8 @@ import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; +import static com.arangodb.internal.serde.SerdeUtils.constructListType; + /** * @author Mark Vollmary * @author Michele Rastelli @@ -194,9 +179,10 @@ public CompletableFuture> query( final Map bindVars, final AqlQueryOptions options, final Class type) { - final Request request = queryRequest(query, bindVars, options); + final InternalRequest request = queryRequest(query, bindVars, options); final HostHandle hostHandle = new HostHandle(); - final CompletableFuture execution = executor.execute(request, CursorEntity.class, hostHandle); + final CompletableFuture execution = executor.execute(request, + InternalCursorEntity.class, hostHandle); return execution.thenApply(result -> createCursor(result, type, options, hostHandle)); } @@ -224,23 +210,28 @@ public CompletableFuture> query(final String query, fin @Override public CompletableFuture> cursor(final String cursorId, final Class type) { final HostHandle hostHandle = new HostHandle(); - final CompletableFuture execution = executor.execute(queryNextRequest(cursorId, null, null), CursorEntity.class, hostHandle); + final CompletableFuture execution = executor.execute(queryNextRequest(cursorId, null, + null), InternalCursorEntity.class, hostHandle); return execution.thenApply(result -> createCursor(result, type, null, hostHandle)); } private ArangoCursorAsync createCursor( - final CursorEntity result, + final InternalCursorEntity result, final Class type, final AqlQueryOptions options, final HostHandle hostHandle) { return new ArangoCursorAsyncImpl<>(this, new ArangoCursorExecute() { @Override - public CursorEntity next(final String id, Map meta) { - final CompletableFuture result = executor.execute(queryNextRequest(id, options, meta), - CursorEntity.class, hostHandle); + public InternalCursorEntity next(final String id, Map meta) { + final CompletableFuture result = executor.execute(queryNextRequest(id, options, + meta), + InternalCursorEntity.class, hostHandle); try { return result.get(); - } catch (InterruptedException | ExecutionException e) { + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ArangoDBException(e); + } catch (ExecutionException e) { throw new ArangoDBException(e); } } @@ -249,7 +240,10 @@ public CursorEntity next(final String id, Map meta) { public void close(final String id, Map meta) { try { executor.execute(queryCloseRequest(id, options, meta), Void.class, hostHandle).get(); - } catch (InterruptedException | ExecutionException e) { + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ArangoDBException(e); + } catch (ExecutionException e) { throw new ArangoDBException(e); } } @@ -298,14 +292,14 @@ public CompletableFuture setQueryTrackingProperti @Override public CompletableFuture> getCurrentlyRunningQueries() { - return executor.execute(getCurrentlyRunningQueriesRequest(), new Type>() { - }.getType()); + return executor.execute(getCurrentlyRunningQueriesRequest(), + constructListType(QueryEntity.class)); } @Override public CompletableFuture> getSlowQueries() { - return executor.execute(getSlowQueriesRequest(), new Type>() { - }.getType()); + return executor.execute(getSlowQueriesRequest(), + constructListType(QueryEntity.class)); } @Override @@ -402,24 +396,15 @@ public CompletableFuture getInfo() { } @Override - public CompletableFuture> executeTraversal( - final Class vertexClass, - final Class edgeClass, - final TraversalOptions options) { - final Request request = executeTraversalRequest(options); - return executor.execute(request, executeTraversalResponseDeserializer(vertexClass, edgeClass)); - } - - @Override - public CompletableFuture getDocument(final String id, final Class type) throws ArangoDBException { + public CompletableFuture getDocument(final String id, final Class type) { DocumentUtil.validateDocumentId(id); final String[] split = id.split("/"); return collection(split[0]).getDocument(split[1], type); } @Override - public CompletableFuture getDocument(final String id, final Class type, final DocumentReadOptions options) - throws ArangoDBException { + public CompletableFuture getDocument(final String id, final Class type, + final DocumentReadOptions options) { DocumentUtil.validateDocumentId(id); final String[] split = id.split("/"); return collection(split[0]).getDocument(split[1], type, options); @@ -450,19 +435,25 @@ public ArangoSearchAsync arangoSearch(final String name) { return new ArangoSearchAsyncImpl(this, name); } + @Override + public SearchAliasAsync searchAlias(String name) { + return new SearchAliasAsyncImpl(this, name); + } + @Override public CompletableFuture createView(final String name, final ViewType type) { return executor.execute(createViewRequest(name, type), ViewEntity.class); } @Override - public CompletableFuture createArangoSearch(final String name, final ArangoSearchCreateOptions options) { + public CompletableFuture createArangoSearch(final String name, + final ArangoSearchCreateOptions options) { return executor.execute(createArangoSearchRequest(name, options), ViewEntity.class); } @Override - public CompletableFuture createAnalyzer(AnalyzerEntity options) { - return executor.execute(createAnalyzerRequest(options), AnalyzerEntity.class); + public CompletableFuture createSearchAlias(String name, SearchAliasCreateOptions options) { + return executor.execute(createSearchAliasRequest(name, options), ViewEntity.class); } @Override @@ -470,45 +461,24 @@ public CompletableFuture createSearchAnalyzer(SearchAnalyzer ana return executor.execute(createAnalyzerRequest(analyzer), SearchAnalyzer.class); } - @Override - public CompletableFuture getAnalyzer(String name) { - return executor.execute(getAnalyzerRequest(name), AnalyzerEntity.class); - } - @Override public CompletableFuture getSearchAnalyzer(String name) { return executor.execute(getAnalyzerRequest(name), SearchAnalyzer.class); } - @Override - public CompletableFuture> getAnalyzers() { - return executor.execute(getAnalyzersRequest(), getAnalyzersResponseDeserializer()); - } - @Override public CompletableFuture> getSearchAnalyzers() { return executor.execute(getAnalyzersRequest(), getSearchAnalyzersResponseDeserializer()); } - @Override - public CompletableFuture deleteAnalyzer(String name) { - return executor.execute(deleteAnalyzerRequest(name, null), Void.class); - } - - @Override - public CompletableFuture deleteAnalyzer(String name, AnalyzerDeleteOptions options) { - return executor.execute(deleteAnalyzerRequest(name, options), Void.class); - } - @Override public CompletableFuture deleteSearchAnalyzer(String name) { - return deleteAnalyzer(name); + return deleteSearchAnalyzer(name, null); } @Override public CompletableFuture deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options) { - return deleteAnalyzer(name, options); + return executor.execute(deleteAnalyzerRequest(name, options), Void.class); } - } diff --git a/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java similarity index 71% rename from src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java index 4ea3ee725..05cb56af3 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java +++ b/core/src/main/java/com/arangodb/async/internal/ArangoEdgeCollectionAsyncImpl.java @@ -32,7 +32,8 @@ * @author Mark Vollmary */ public class ArangoEdgeCollectionAsyncImpl extends - InternalArangoEdgeCollection + InternalArangoEdgeCollection implements ArangoEdgeCollectionAsync { ArangoEdgeCollectionAsyncImpl(final ArangoGraphAsyncImpl graph, final String name) { @@ -40,14 +41,14 @@ public class ArangoEdgeCollectionAsyncImpl extends } @Override - public CompletableFuture insertEdge(final T value) { + public CompletableFuture insertEdge(final Object value) { return executor.execute(insertEdgeRequest(value, new EdgeCreateOptions()), - insertEdgeResponseDeserializer(value)); + insertEdgeResponseDeserializer()); } @Override - public CompletableFuture insertEdge(final T value, final EdgeCreateOptions options) { - return executor.execute(insertEdgeRequest(value, options), insertEdgeResponseDeserializer(value)); + public CompletableFuture insertEdge(final Object value, final EdgeCreateOptions options) { + return executor.execute(insertEdgeRequest(value, options), insertEdgeResponseDeserializer()); } @Override @@ -56,38 +57,38 @@ public CompletableFuture getEdge(final String key, final Class type) { } @Override - public CompletableFuture getEdge(final String key, final Class type, final GraphDocumentReadOptions options) { - boolean isCatchException = options != null ? options.isCatchException() : new GraphDocumentReadOptions().isCatchException(); + public CompletableFuture getEdge(final String key, final Class type, + final GraphDocumentReadOptions options) { return executor.execute(getEdgeRequest(key, options), getEdgeResponseDeserializer(type)) - .exceptionally(ExceptionUtil.catchGetDocumentExceptions(isCatchException)); + .exceptionally(ExceptionUtil.catchGetDocumentExceptions()); } @Override - public CompletableFuture replaceEdge(final String key, final T value) { + public CompletableFuture replaceEdge(final String key, final Object value) { return executor.execute(replaceEdgeRequest(key, value, new EdgeReplaceOptions()), - replaceEdgeResponseDeserializer(value)); + replaceEdgeResponseDeserializer()); } @Override - public CompletableFuture replaceEdge( + public CompletableFuture replaceEdge( final String key, - final T value, + final Object value, final EdgeReplaceOptions options) { - return executor.execute(replaceEdgeRequest(key, value, options), replaceEdgeResponseDeserializer(value)); + return executor.execute(replaceEdgeRequest(key, value, options), replaceEdgeResponseDeserializer()); } @Override - public CompletableFuture updateEdge(final String key, final T value) { + public CompletableFuture updateEdge(final String key, final Object value) { return executor.execute(updateEdgeRequest(key, value, new EdgeUpdateOptions()), - updateEdgeResponseDeserializer(value)); + updateEdgeResponseDeserializer()); } @Override - public CompletableFuture updateEdge( + public CompletableFuture updateEdge( final String key, - final T value, + final Object value, final EdgeUpdateOptions options) { - return executor.execute(updateEdgeRequest(key, value, options), updateEdgeResponseDeserializer(value)); + return executor.execute(updateEdgeRequest(key, value, options), updateEdgeResponseDeserializer()); } @Override diff --git a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java b/core/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java similarity index 62% rename from src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java rename to core/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java index 58d7659c5..7c85ef495 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java +++ b/core/src/main/java/com/arangodb/async/internal/ArangoExecutorAsync.java @@ -21,13 +21,11 @@ package com.arangodb.async.internal; import com.arangodb.ArangoDBException; -import com.arangodb.async.internal.velocystream.VstCommunicationAsync; import com.arangodb.internal.ArangoExecutor; -import com.arangodb.internal.DocumentCache; -import com.arangodb.internal.QueueTimeMetricsImpl; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.AsyncCommunication; import com.arangodb.internal.net.HostHandle; -import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.velocystream.Request; import java.io.IOException; import java.lang.reflect.Type; @@ -41,34 +39,33 @@ */ public class ArangoExecutorAsync extends ArangoExecutor { - private final VstCommunicationAsync communication; + private final AsyncCommunication communication; private final ExecutorService outgoingExecutor = Executors.newSingleThreadExecutor(); - public ArangoExecutorAsync(final VstCommunicationAsync communication, final ArangoSerializationFactory util, - final DocumentCache documentCache, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { - super(util, documentCache, qtMetrics, timeoutMs); + public ArangoExecutorAsync(final AsyncCommunication communication, final ArangoConfig config) { + super(config); this.communication = communication; } - public CompletableFuture execute(final Request request, final Type type) { - return execute(request, (response) -> createResult(type, response)); + public CompletableFuture execute(final InternalRequest request, final Type type) { + return execute(request, response -> createResult(type, response)); } - public CompletableFuture execute(final Request request, final Type type, final HostHandle hostHandle) { - return execute(request, (response) -> createResult(type, response), hostHandle); + public CompletableFuture execute(final InternalRequest request, final Type type, final HostHandle hostHandle) { + return execute(request, response -> createResult(type, response), hostHandle); } - public CompletableFuture execute(final Request request, final ResponseDeserializer responseDeserializer) { + public CompletableFuture execute(final InternalRequest request, final ResponseDeserializer responseDeserializer) { return execute(request, responseDeserializer, null); } private CompletableFuture execute( - final Request request, + final InternalRequest request, final ResponseDeserializer responseDeserializer, final HostHandle hostHandle) { return CompletableFuture.completedFuture(null) - .thenComposeAsync((it) -> communication.execute(interceptRequest(request), hostHandle), outgoingExecutor) + .thenComposeAsync(it -> communication.execute(interceptRequest(request), hostHandle), outgoingExecutor) .thenApplyAsync(response -> { interceptResponse(response); return responseDeserializer.deserialize(response); diff --git a/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java similarity index 97% rename from src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java index 23777f933..c16a32aaf 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java +++ b/core/src/main/java/com/arangodb/async/internal/ArangoGraphAsyncImpl.java @@ -87,7 +87,8 @@ public CompletableFuture addVertexCollection(final String name) { } @Override - public CompletableFuture addVertexCollection(final String name, final VertexCollectionCreateOptions options) { + public CompletableFuture addVertexCollection(final String name, + final VertexCollectionCreateOptions options) { return executor.execute(addVertexCollectionRequest(name, options), addVertexCollectionResponseDeserializer()); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java similarity index 83% rename from src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java index d4af273e9..57270220d 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java +++ b/core/src/main/java/com/arangodb/async/internal/ArangoRouteAsyncImpl.java @@ -22,8 +22,8 @@ import com.arangodb.async.ArangoRouteAsync; import com.arangodb.internal.InternalArangoRoute; -import com.arangodb.velocystream.RequestType; -import com.arangodb.velocystream.Response; +import com.arangodb.internal.RequestType; +import com.arangodb.internal.InternalResponse; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -66,37 +66,37 @@ public ArangoRouteAsync withBody(final Object body) { return this; } - private CompletableFuture request(final RequestType requestType) { + private CompletableFuture request(final RequestType requestType) { return executor.execute(createRequest(requestType), response -> response); } @Override - public CompletableFuture delete() { + public CompletableFuture delete() { return request(RequestType.DELETE); } @Override - public CompletableFuture get() { + public CompletableFuture get() { return request(RequestType.GET); } @Override - public CompletableFuture head() { + public CompletableFuture head() { return request(RequestType.HEAD); } @Override - public CompletableFuture patch() { + public CompletableFuture patch() { return request(RequestType.PATCH); } @Override - public CompletableFuture post() { + public CompletableFuture post() { return request(RequestType.POST); } @Override - public CompletableFuture put() { + public CompletableFuture put() { return request(RequestType.PUT); } diff --git a/src/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoSearchAsyncImpl.java diff --git a/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java similarity index 73% rename from src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java index e988b6436..a5e490850 100644 --- a/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java +++ b/core/src/main/java/com/arangodb/async/internal/ArangoVertexCollectionAsyncImpl.java @@ -32,7 +32,8 @@ * @author Mark Vollmary */ public class ArangoVertexCollectionAsyncImpl extends - InternalArangoVertexCollection + InternalArangoVertexCollection implements ArangoVertexCollectionAsync { ArangoVertexCollectionAsyncImpl(final ArangoGraphAsyncImpl graph, final String name) { @@ -45,14 +46,14 @@ public CompletableFuture drop() { } @Override - public CompletableFuture insertVertex(final T value) { + public CompletableFuture insertVertex(final Object value) { return executor.execute(insertVertexRequest(value, new VertexCreateOptions()), - insertVertexResponseDeserializer(value)); + insertVertexResponseDeserializer()); } @Override - public CompletableFuture insertVertex(final T value, final VertexCreateOptions options) { - return executor.execute(insertVertexRequest(value, options), insertVertexResponseDeserializer(value)); + public CompletableFuture insertVertex(final Object value, final VertexCreateOptions options) { + return executor.execute(insertVertexRequest(value, options), insertVertexResponseDeserializer()); } @Override @@ -65,37 +66,36 @@ public CompletableFuture getVertex( final String key, final Class type, final GraphDocumentReadOptions options) { - boolean isCatchException = options != null ? options.isCatchException() : new GraphDocumentReadOptions().isCatchException(); return executor.execute(getVertexRequest(key, options), getVertexResponseDeserializer(type)) - .exceptionally(ExceptionUtil.catchGetDocumentExceptions(isCatchException)); + .exceptionally(ExceptionUtil.catchGetDocumentExceptions()); } @Override - public CompletableFuture replaceVertex(final String key, final T value) { + public CompletableFuture replaceVertex(final String key, final Object value) { return executor.execute(replaceVertexRequest(key, value, new VertexReplaceOptions()), - replaceVertexResponseDeserializer(value)); + replaceVertexResponseDeserializer()); } @Override - public CompletableFuture replaceVertex( + public CompletableFuture replaceVertex( final String key, - final T value, + final Object value, final VertexReplaceOptions options) { - return executor.execute(replaceVertexRequest(key, value, options), replaceVertexResponseDeserializer(value)); + return executor.execute(replaceVertexRequest(key, value, options), replaceVertexResponseDeserializer()); } @Override - public CompletableFuture updateVertex(final String key, final T value) { + public CompletableFuture updateVertex(final String key, final Object value) { return executor.execute(updateVertexRequest(key, value, new VertexUpdateOptions()), - updateVertexResponseDeserializer(value)); + updateVertexResponseDeserializer()); } @Override - public CompletableFuture updateVertex( + public CompletableFuture updateVertex( final String key, - final T value, + final Object value, final VertexUpdateOptions options) { - return executor.execute(updateVertexRequest(key, value, options), updateVertexResponseDeserializer(value)); + return executor.execute(updateVertexRequest(key, value, options), updateVertexResponseDeserializer()); } @Override diff --git a/src/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java similarity index 100% rename from src/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java rename to core/src/main/java/com/arangodb/async/internal/ArangoViewAsyncImpl.java diff --git a/src/main/java/com/arangodb/async/internal/ExceptionUtil.java b/core/src/main/java/com/arangodb/async/internal/ExceptionUtil.java similarity index 86% rename from src/main/java/com/arangodb/async/internal/ExceptionUtil.java rename to core/src/main/java/com/arangodb/async/internal/ExceptionUtil.java index b76cdc21d..422e779ed 100644 --- a/src/main/java/com/arangodb/async/internal/ExceptionUtil.java +++ b/core/src/main/java/com/arangodb/async/internal/ExceptionUtil.java @@ -1,4 +1,4 @@ -package com.arangodb.async.internal;/* +/* * DISCLAIMER * * Copyright 2016 ArangoDB GmbH, Cologne, Germany @@ -18,6 +18,7 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ +package com.arangodb.async.internal; import com.arangodb.ArangoDBException; @@ -28,7 +29,11 @@ * @author Michele Rastelli */ class ExceptionUtil { - static Function catchGetDocumentExceptions(Boolean isCatchException) { + + private ExceptionUtil() { + } + + static Function catchGetDocumentExceptions() { return throwable -> { if (throwable instanceof CompletionException) { if (throwable.getCause() instanceof ArangoDBException) { @@ -39,8 +44,8 @@ static Function catchGetDocumentExceptions(Boolean isCatchExce throw (CompletionException) throwable; } - if ((arangoDBException.getResponseCode() != null && (arangoDBException.getResponseCode() == 404 || arangoDBException.getResponseCode() == 304 - || arangoDBException.getResponseCode() == 412)) && isCatchException) { + if ((arangoDBException.getResponseCode() != null && + (arangoDBException.getResponseCode() == 404 || arangoDBException.getResponseCode() == 304 || arangoDBException.getResponseCode() == 412))) { return null; } } diff --git a/core/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java b/core/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java new file mode 100644 index 000000000..d5e4cbd4f --- /dev/null +++ b/core/src/main/java/com/arangodb/async/internal/SearchAliasAsyncImpl.java @@ -0,0 +1,87 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.async.internal; + +import com.arangodb.async.SearchAliasAsync; +import com.arangodb.entity.ViewEntity; +import com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity; +import com.arangodb.internal.InternalSearchAlias; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasPropertiesOptions; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +public class SearchAliasAsyncImpl + extends InternalSearchAlias + implements SearchAliasAsync { + + SearchAliasAsyncImpl(final ArangoDatabaseAsyncImpl db, final String name) { + super(db, name); + } + + @Override + public CompletableFuture exists() { + return getInfo().thenApply(Objects::nonNull).exceptionally(Objects::isNull); + } + + @Override + public CompletableFuture drop() { + return executor.execute(dropRequest(), Void.class); + } + + @Override + public synchronized CompletableFuture rename(final String newName) { + return executor.execute(renameRequest(newName), ViewEntity.class); + } + + @Override + public CompletableFuture getInfo() { + return executor.execute(getInfoRequest(), ViewEntity.class); + } + + @Override + public CompletableFuture create() { + return create(new SearchAliasCreateOptions()); + } + + @Override + public CompletableFuture create(final SearchAliasCreateOptions options) { + return db().createSearchAlias(name(), options); + } + + @Override + public CompletableFuture getProperties() { + return executor.execute(getPropertiesRequest(), SearchAliasPropertiesEntity.class); + } + + @Override + public CompletableFuture updateProperties(final SearchAliasPropertiesOptions options) { + return executor.execute(updatePropertiesRequest(options), SearchAliasPropertiesEntity.class); + } + + @Override + public CompletableFuture replaceProperties( + final SearchAliasPropertiesOptions options) { + return executor.execute(replacePropertiesRequest(options), SearchAliasPropertiesEntity.class); + } + +} diff --git a/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java b/core/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java similarity index 69% rename from src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java rename to core/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java index 4648e5c0c..026453645 100644 --- a/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java +++ b/core/src/main/java/com/arangodb/async/internal/utils/CompletableFutureUtils.java @@ -1,17 +1,9 @@ package com.arangodb.async.internal.utils; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.concurrent.*; public class CompletableFutureUtils { - private CompletableFutureUtils() { - } - private static final ScheduledExecutorService timeoutScheduler = Executors.newSingleThreadScheduledExecutor(r -> { Thread t = Executors.defaultThreadFactory().newThread(r); t.setDaemon(true); @@ -19,7 +11,11 @@ private CompletableFutureUtils() { } ); - public static CompletableFuture orTimeout(CompletableFuture completableFuture, long timeout, TimeUnit unit) { + private CompletableFutureUtils() { + } + + public static CompletableFuture orTimeout(CompletableFuture completableFuture, long timeout, + TimeUnit unit) { ScheduledFuture timeoutTask = timeoutScheduler.schedule(() -> completableFuture.completeExceptionally(new TimeoutException()), timeout, unit); completableFuture.whenComplete((v, e) -> timeoutTask.cancel(false)); diff --git a/core/src/main/java/com/arangodb/config/ArangoConfigProperties.java b/core/src/main/java/com/arangodb/config/ArangoConfigProperties.java new file mode 100644 index 000000000..5ef63676f --- /dev/null +++ b/core/src/main/java/com/arangodb/config/ArangoConfigProperties.java @@ -0,0 +1,100 @@ +package com.arangodb.config; + +import com.arangodb.Protocol; +import com.arangodb.entity.LoadBalancingStrategy; +import com.arangodb.internal.config.ArangoConfigPropertiesImpl; + +import java.util.List; +import java.util.Optional; + +public interface ArangoConfigProperties { + + /** + * Reads properties from file arangodb.properties. + * Properties must be prefixed with @{code "arangodb"}, eg. @{code "arangodb.hosts=localhost:8529"}. + */ + static ArangoConfigProperties fromFile() { + return new ArangoConfigPropertiesImpl(); + } + + /** + * Reads properties from file {@code fileName}. + * Properties must be prefixed with @{code "arangodb"}, eg. @{code "arangodb.hosts=localhost:8529"}. + */ + static ArangoConfigProperties fromFile(final String fileName) { + return new ArangoConfigPropertiesImpl(fileName); + } + + /** + * Reads properties from file {@code fileName}. + * Properties must be prefixed with @{code prefix}, eg. @{code ".hosts=localhost:8529"}. + */ + static ArangoConfigProperties fromFile(final String fileName, final String prefix) { + return new ArangoConfigPropertiesImpl(fileName, prefix); + } + + default Optional> getHosts() { + return Optional.empty(); + } + + default Optional getProtocol() { + return Optional.empty(); + } + + default Optional getUser() { + return Optional.empty(); + } + + default Optional getPassword() { + return Optional.empty(); + } + + default Optional getJwt() { + return Optional.empty(); + } + + default Optional getTimeout() { + return Optional.empty(); + } + + default Optional getUseSsl() { + return Optional.empty(); + } + + default Optional getVerifyHost() { + return Optional.empty(); + } + + default Optional getChunkSize() { + return Optional.empty(); + } + + default Optional getMaxConnections() { + return Optional.empty(); + } + + default Optional getConnectionTtl() { + return Optional.empty(); + } + + default Optional getKeepAliveInterval() { + return Optional.empty(); + } + + default Optional getAcquireHostList() { + return Optional.empty(); + } + + default Optional getAcquireHostListInterval() { + return Optional.empty(); + } + + default Optional getLoadBalancingStrategy() { + return Optional.empty(); + } + + default Optional getResponseQueueTimeSamples() { + return Optional.empty(); + } + +} diff --git a/src/main/java/com/arangodb/internal/net/HostDescription.java b/core/src/main/java/com/arangodb/config/HostDescription.java similarity index 54% rename from src/main/java/com/arangodb/internal/net/HostDescription.java rename to core/src/main/java/com/arangodb/config/HostDescription.java index 53d54b10b..2e26177ed 100644 --- a/src/main/java/com/arangodb/internal/net/HostDescription.java +++ b/core/src/main/java/com/arangodb/config/HostDescription.java @@ -18,16 +18,35 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.net; +package com.arangodb.config; + +import java.util.Objects; /** * @author Mark Vollmary + * @author Michele Rastelli */ public class HostDescription { private final String host; private final int port; + /** + * Factory method used by MicroProfile Config as + * automatic converter. + * + * @param value hostname:port + * @return Host + */ + public static HostDescription parse(CharSequence value) { + Objects.requireNonNull(value); + final String[] split = value.toString().split(":"); + if (split.length != 2) { + throw new IllegalArgumentException("Could not parse host. Expected hostname:port, but got: " + value); + } + return new HostDescription(split[0], Integer.parseInt(split[1])); + } + public HostDescription(final String host, final int port) { super(); this.host = host; @@ -48,34 +67,15 @@ public String toString() { } @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((host == null) ? 0 : host.hashCode()); - result = prime * result + port; - return result; + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + HostDescription that = (HostDescription) o; + return port == that.port && Objects.equals(host, that.host); } @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final HostDescription other = (HostDescription) obj; - if (host == null) { - if (other.host != null) { - return false; - } - } else if (!host.equals(other.host)) { - return false; - } - return port == other.port; + public int hashCode() { + return Objects.hash(host, port); } - } diff --git a/core/src/main/java/com/arangodb/entity/AbstractBaseDocument.java b/core/src/main/java/com/arangodb/entity/AbstractBaseDocument.java new file mode 100644 index 000000000..cce54a832 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/AbstractBaseDocument.java @@ -0,0 +1,154 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.arangodb.internal.DocumentFields; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +abstract class AbstractBaseDocument { + + private static final String[] META_PROPS = new String[]{ + DocumentFields.ID, + DocumentFields.KEY, + DocumentFields.REV + }; + private final HashMap properties; + + AbstractBaseDocument() { + properties = new HashMap<>(); + } + + AbstractBaseDocument(final String key) { + this(); + setKey(key); + } + + AbstractBaseDocument(final Map properties) { + this(); + setProperties(properties); + } + + @JsonIgnore + public String getId() { + return (String) getAttribute(DocumentFields.ID); + } + + public void setId(final String id) { + addAttribute(DocumentFields.ID, id); + } + + @JsonIgnore + public String getKey() { + return (String) getAttribute(DocumentFields.KEY); + } + + public void setKey(final String key) { + addAttribute(DocumentFields.KEY, key); + } + + @JsonIgnore + public String getRevision() { + return (String) getAttribute(DocumentFields.REV); + } + + public void setRevision(final String rev) { + addAttribute(DocumentFields.REV, rev); + } + + @JsonInclude + @JsonAnyGetter + public Map getProperties() { + return Collections.unmodifiableMap(properties); + } + + public void setProperties(final Map props) { + for (String f : getMetaProps()) { + requireString(f, props.get(f)); + } + this.properties.putAll(props); + } + + public Object getAttribute(final String key) { + return properties.get(key); + } + + @JsonInclude + @JsonAnySetter + public void addAttribute(final String key, final Object value) { + for (String f : getMetaProps()) { + if (f.equals(key)) { + requireString(key, value); + } + } + properties.put(key, value); + } + + public void updateAttribute(final String key, final Object value) { + if (properties.containsKey(key)) { + addAttribute(key, value); + } + } + + public void removeAttribute(final String key) { + properties.remove(key); + } + + protected String[] getMetaProps() { + return META_PROPS; + } + + private void requireString(final String k, final Object v) { + if (v != null && !(v instanceof String)) { + throw new IllegalArgumentException(k + " must be a String"); + } + } + + String stringify() { + return "{" + + "properties=" + properties + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AbstractBaseDocument that = (AbstractBaseDocument) o; + return Objects.equals(properties, that.properties); + } + + @Override + public int hashCode() { + return Objects.hash(properties); + } +} diff --git a/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java b/core/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java similarity index 95% rename from src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java rename to core/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java index b913a267c..2f586a268 100644 --- a/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java +++ b/core/src/main/java/com/arangodb/entity/AqlExecutionExplainEntity.java @@ -26,9 +26,35 @@ * @author Mark Vollmary * @see API Documentation */ -public class AqlExecutionExplainEntity implements Entity { +public final class AqlExecutionExplainEntity { - public static class ExecutionPlan { + private ExecutionPlan plan; + private Collection plans; + private Collection warnings; + private ExecutionStats stats; + private Boolean cacheable; + + public ExecutionPlan getPlan() { + return plan; + } + + public Collection getPlans() { + return plans; + } + + public Collection getWarnings() { + return warnings; + } + + public ExecutionStats getStats() { + return stats; + } + + public Boolean getCacheable() { + return cacheable; + } + + public static final class ExecutionPlan { private Collection nodes; private Collection rules; private Collection collections; @@ -61,7 +87,7 @@ public Integer getEstimatedNrItems() { } } - public static class ExecutionNode { + public static final class ExecutionNode { private String type; private Collection dependencies; private Long id; @@ -179,7 +205,7 @@ public Boolean getReverse() { } } - public static class ExecutionVariable { + public static final class ExecutionVariable { private Long id; private String name; @@ -192,7 +218,7 @@ public String getName() { } } - public static class ExecutionExpression { + public static final class ExecutionExpression { private String type; private String name; private Long id; @@ -235,7 +261,7 @@ public Collection getSubNodes() { } } - public static class ExecutionCollection { + public static final class ExecutionCollection { private String name; private String type; @@ -248,7 +274,7 @@ public String getType() { } } - public static class ExecutionStats { + public static final class ExecutionStats { private Integer rulesExecuted; private Integer rulesSkipped; private Integer plansCreated; @@ -267,30 +293,4 @@ public Integer getPlansCreated() { } - private ExecutionPlan plan; - private Collection plans; - private Collection warnings; - private ExecutionStats stats; - private Boolean cacheable; - - public ExecutionPlan getPlan() { - return plan; - } - - public Collection getPlans() { - return plans; - } - - public Collection getWarnings() { - return warnings; - } - - public ExecutionStats getStats() { - return stats; - } - - public Boolean getCacheable() { - return cacheable; - } - } diff --git a/src/main/java/com/arangodb/entity/AqlFunctionEntity.java b/core/src/main/java/com/arangodb/entity/AqlFunctionEntity.java similarity index 97% rename from src/main/java/com/arangodb/entity/AqlFunctionEntity.java rename to core/src/main/java/com/arangodb/entity/AqlFunctionEntity.java index 57f5d78c4..cd0d52f5f 100644 --- a/src/main/java/com/arangodb/entity/AqlFunctionEntity.java +++ b/core/src/main/java/com/arangodb/entity/AqlFunctionEntity.java @@ -26,7 +26,7 @@ * "https://www.arangodb.com/docs/stable/http/aql-user-functions.html#return-registered-aql-user-functions">API * Documentation */ -public class AqlFunctionEntity implements Entity { +public final class AqlFunctionEntity { private String name; private String code; diff --git a/src/main/java/com/arangodb/entity/AqlParseEntity.java b/core/src/main/java/com/arangodb/entity/AqlParseEntity.java similarity index 95% rename from src/main/java/com/arangodb/entity/AqlParseEntity.java rename to core/src/main/java/com/arangodb/entity/AqlParseEntity.java index f5f16e059..b50ae51e1 100644 --- a/src/main/java/com/arangodb/entity/AqlParseEntity.java +++ b/core/src/main/java/com/arangodb/entity/AqlParseEntity.java @@ -26,9 +26,25 @@ * @author Mark Vollmary * @see API Documentation */ -public class AqlParseEntity implements Entity { +public final class AqlParseEntity { - public static class AstNode { + private Collection collections; + private Collection bindVars; + private Collection ast; + + public Collection getCollections() { + return collections; + } + + public Collection getBindVars() { + return bindVars; + } + + public Collection getAst() { + return ast; + } + + public static final class AstNode { private String type; private Collection subNodes; private String name; @@ -57,20 +73,4 @@ public Object getValue() { } - private Collection collections; - private Collection bindVars; - private Collection ast; - - public Collection getCollections() { - return collections; - } - - public Collection getBindVars() { - return bindVars; - } - - public Collection getAst() { - return ast; - } - } diff --git a/src/main/java/com/arangodb/entity/ArangoDBEngine.java b/core/src/main/java/com/arangodb/entity/ArangoDBEngine.java similarity index 85% rename from src/main/java/com/arangodb/entity/ArangoDBEngine.java rename to core/src/main/java/com/arangodb/entity/ArangoDBEngine.java index 37ea0bfc8..9c35da0c7 100644 --- a/src/main/java/com/arangodb/entity/ArangoDBEngine.java +++ b/core/src/main/java/com/arangodb/entity/ArangoDBEngine.java @@ -22,14 +22,11 @@ /** * @author Michele Rastelli - * @see API + * @see + * API * Documentation */ -public class ArangoDBEngine implements Entity { - - public enum StorageEngineName { - mmfiles, rocksdb - } +public final class ArangoDBEngine { private StorageEngineName name; @@ -44,4 +41,8 @@ public StorageEngineName getName() { return name; } + public enum StorageEngineName { + mmfiles, rocksdb + } + } diff --git a/src/main/java/com/arangodb/entity/ArangoDBVersion.java b/core/src/main/java/com/arangodb/entity/ArangoDBVersion.java similarity index 96% rename from src/main/java/com/arangodb/entity/ArangoDBVersion.java rename to core/src/main/java/com/arangodb/entity/ArangoDBVersion.java index db339bd88..878980e32 100644 --- a/src/main/java/com/arangodb/entity/ArangoDBVersion.java +++ b/core/src/main/java/com/arangodb/entity/ArangoDBVersion.java @@ -25,7 +25,7 @@ * @see API * Documentation */ -public class ArangoDBVersion implements Entity { +public final class ArangoDBVersion { private String server; private String version; diff --git a/core/src/main/java/com/arangodb/entity/BaseDocument.java b/core/src/main/java/com/arangodb/entity/BaseDocument.java new file mode 100644 index 000000000..0e8860e74 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/BaseDocument.java @@ -0,0 +1,48 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import java.util.Map; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +public class BaseDocument extends AbstractBaseDocument { + + public BaseDocument() { + super(); + } + + public BaseDocument(final String key) { + super(key); + } + + public BaseDocument(final Map properties) { + super(properties); + } + + @Override + public String toString() { + return "BaseDocument" + stringify(); + } + +} diff --git a/core/src/main/java/com/arangodb/entity/BaseEdgeDocument.java b/core/src/main/java/com/arangodb/entity/BaseEdgeDocument.java new file mode 100644 index 000000000..46abcc246 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/BaseEdgeDocument.java @@ -0,0 +1,90 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.arangodb.internal.DocumentFields; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.util.Map; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +public class BaseEdgeDocument extends BaseDocument { + + private static final String[] META_PROPS = new String[]{ + DocumentFields.ID, + DocumentFields.KEY, + DocumentFields.REV, + DocumentFields.FROM, + DocumentFields.TO + }; + + public BaseEdgeDocument() { + super(); + } + + public BaseEdgeDocument(final String from, final String to) { + super(); + setFrom(from); + setTo(to); + } + + public BaseEdgeDocument(final String key, final String from, final String to) { + super(key); + setFrom(from); + setTo(to); + } + + public BaseEdgeDocument(final Map properties) { + super(properties); + } + + @JsonIgnore + public String getFrom() { + return (String) getAttribute(DocumentFields.FROM); + } + + public void setFrom(final String from) { + addAttribute(DocumentFields.FROM, from); + } + + @JsonIgnore + public String getTo() { + return (String) getAttribute(DocumentFields.TO); + } + + public void setTo(final String to) { + addAttribute(DocumentFields.TO, to); + } + + @Override + protected String[] getMetaProps() { + return META_PROPS; + } + + @Override + public String toString() { + return "BaseEdgeDocument" + stringify(); + } + +} diff --git a/src/main/java/com/arangodb/entity/CollectionEntity.java b/core/src/main/java/com/arangodb/entity/CollectionEntity.java similarity index 78% rename from src/main/java/com/arangodb/entity/CollectionEntity.java rename to core/src/main/java/com/arangodb/entity/CollectionEntity.java index 846ed76fa..bff127761 100644 --- a/src/main/java/com/arangodb/entity/CollectionEntity.java +++ b/core/src/main/java/com/arangodb/entity/CollectionEntity.java @@ -21,35 +21,29 @@ package com.arangodb.entity; import com.arangodb.model.CollectionSchema; +import com.arangodb.model.ComputedValue; + +import java.util.List; /** * @author Mark Vollmary * @see API Documentation */ -public class CollectionEntity implements Entity { +public class CollectionEntity { private String id; private String name; private Boolean waitForSync; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Boolean isVolatile; private Boolean isSystem; private CollectionStatus status; private CollectionType type; private CollectionSchema schema; + private List computedValues; public CollectionEntity() { super(); } - /** - * @deprecated Accessing collections by their internal ID instead of accessing them by name is deprecated and highly - * discouraged. This functionality may be removed in future versions of ArangoDB. - */ - @Deprecated public String getId() { return id; } @@ -62,14 +56,6 @@ public Boolean getWaitForSync() { return waitForSync; } - /** - * @deprecated MMFiles only - */ - @Deprecated - public Boolean getIsVolatile() { - return isVolatile; - } - public Boolean getIsSystem() { return isSystem; } @@ -90,4 +76,12 @@ public CollectionSchema getSchema() { return schema; } + /** + * @return A list of computed values. + * @since ArangoDB 3.10 + */ + public List getComputedValues() { + return computedValues; + } + } diff --git a/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java b/core/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java similarity index 53% rename from src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java rename to core/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java index 8a1809152..9e9388bc3 100644 --- a/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java +++ b/core/src/main/java/com/arangodb/entity/CollectionPropertiesEntity.java @@ -27,86 +27,19 @@ * @see API * Documentation */ -public class CollectionPropertiesEntity extends CollectionEntity { +public final class CollectionPropertiesEntity extends CollectionEntity { - /** - * @deprecated MMFiles only - */ - @Deprecated - private Boolean doCompact; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Long journalSize; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Integer indexBuckets; private KeyOptions keyOptions; private Long count; private Integer numberOfShards; private Collection shardKeys; - private final ReplicationFactor replicationFactor; - private final MinReplicationFactor minReplicationFactor; + private ReplicationFactor replicationFactor; private Integer writeConcern; private String shardingStrategy; // cluster option private String smartJoinAttribute; // enterprise option public CollectionPropertiesEntity() { super(); - replicationFactor = new ReplicationFactor(); - minReplicationFactor = new MinReplicationFactor(); - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public Boolean getDoCompact() { - return doCompact; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public void setDoCompact(final Boolean doCompact) { - this.doCompact = doCompact; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public Long getJournalSize() { - return journalSize; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public void setJournalSize(final Long journalSize) { - this.journalSize = journalSize; - } - - - /** - * @deprecated MMFiles only - */ - @Deprecated - public Integer getIndexBuckets() { - return indexBuckets; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public void setIndexBuckets(final Integer indexBuckets) { - this.indexBuckets = indexBuckets; } public KeyOptions getKeyOptions() { @@ -148,28 +81,12 @@ public void setShardKeys(final Collection shardKeys) { this.shardKeys = shardKeys; } - public Integer getReplicationFactor() { - return replicationFactor.getReplicationFactor(); - } - - public void setReplicationFactor(final Integer replicationFactor) { - this.replicationFactor.setReplicationFactor(replicationFactor); - } - - /** - * @deprecated use {@link #getWriteConcern()} instead - */ - @Deprecated - public Integer getMinReplicationFactor() { - return minReplicationFactor.getMinReplicationFactor(); + public ReplicationFactor getReplicationFactor() { + return replicationFactor; } - /** - * @deprecated use {@link #setWriteConcern(Integer)} instead - */ - @Deprecated - public void setMinReplicationFactor(final Integer minReplicationFactor) { - this.minReplicationFactor.setMinReplicationFactor(minReplicationFactor); + public void setReplicationFactor(final ReplicationFactor replicationFactor) { + this.replicationFactor = replicationFactor; } public Integer getWriteConcern() { @@ -180,17 +97,6 @@ public void setWriteConcern(final Integer writeConcern) { this.writeConcern = writeConcern; } - /** - * @return whether the collection is a satellite collection. Only in an enterprise cluster setup (else returning null). - */ - public Boolean getSatellite() { - return this.replicationFactor.getSatellite(); - } - - public void setSatellite(final Boolean satellite) { - this.replicationFactor.setSatellite(satellite); - } - public String getShardingStrategy() { return shardingStrategy; } diff --git a/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java b/core/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java similarity index 90% rename from src/main/java/com/arangodb/entity/CollectionRevisionEntity.java rename to core/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java index d04ec000d..645849eba 100644 --- a/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java +++ b/core/src/main/java/com/arangodb/entity/CollectionRevisionEntity.java @@ -1,36 +1,36 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public class CollectionRevisionEntity extends CollectionEntity { - - private String revision; - - public String getRevision() { - return revision; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class CollectionRevisionEntity extends CollectionEntity { + + private String revision; + + public String getRevision() { + return revision; + } + +} diff --git a/src/main/java/com/arangodb/entity/CollectionStatus.java b/core/src/main/java/com/arangodb/entity/CollectionStatus.java similarity index 79% rename from src/main/java/com/arangodb/entity/CollectionStatus.java rename to core/src/main/java/com/arangodb/entity/CollectionStatus.java index 08816ddc1..b3d30f5d6 100644 --- a/src/main/java/com/arangodb/entity/CollectionStatus.java +++ b/core/src/main/java/com/arangodb/entity/CollectionStatus.java @@ -25,27 +25,7 @@ */ public enum CollectionStatus { - /** - * @deprecated MMFiles only - */ - @Deprecated - NEW_BORN_COLLECTION(1), - - /** - * @deprecated MMFiles only - */ - @Deprecated - UNLOADED(2), - - LOADED(3), - - /** - * @deprecated MMFiles only - */ - @Deprecated - IN_THE_PROCESS_OF_BEING_UNLOADED(4), - - DELETED(5); + LOADED(3), DELETED(5); private final int status; @@ -53,10 +33,6 @@ public enum CollectionStatus { this.status = status; } - public int getStatus() { - return status; - } - public static CollectionStatus fromStatus(final int status) { for (final CollectionStatus cStatus : CollectionStatus.values()) { if (cStatus.status == status) { @@ -66,4 +42,8 @@ public static CollectionStatus fromStatus(final int status) { return null; } + public int getStatus() { + return status; + } + } diff --git a/src/main/java/com/arangodb/entity/CollectionType.java b/core/src/main/java/com/arangodb/entity/CollectionType.java similarity index 100% rename from src/main/java/com/arangodb/entity/CollectionType.java rename to core/src/main/java/com/arangodb/entity/CollectionType.java index af6f56797..7d771b67d 100644 --- a/src/main/java/com/arangodb/entity/CollectionType.java +++ b/core/src/main/java/com/arangodb/entity/CollectionType.java @@ -33,10 +33,6 @@ public enum CollectionType { this.type = type; } - public int getType() { - return type; - } - public static CollectionType fromType(final int type) { for (final CollectionType cType : CollectionType.values()) { if (cType.type == type) { @@ -45,4 +41,8 @@ public static CollectionType fromType(final int type) { } return null; } + + public int getType() { + return type; + } } diff --git a/core/src/main/java/com/arangodb/entity/CursorStats.java b/core/src/main/java/com/arangodb/entity/CursorStats.java new file mode 100644 index 000000000..58f99dc38 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/CursorStats.java @@ -0,0 +1,26 @@ +package com.arangodb.entity; + +import com.fasterxml.jackson.annotation.JsonAnySetter; + +import java.util.HashMap; +import java.util.Map; + +public final class CursorStats { + + private Long fullCount; + private final Map properties = new HashMap<>(); + + @JsonAnySetter + public void add(String key, Object value) { + properties.put(key, value); + } + + public Long getFullCount() { + return fullCount; + } + + public Object get(String key) { + return properties.get(key); + } + +} diff --git a/core/src/main/java/com/arangodb/entity/CursorWarning.java b/core/src/main/java/com/arangodb/entity/CursorWarning.java new file mode 100644 index 000000000..72dc8ff1c --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/CursorWarning.java @@ -0,0 +1,16 @@ +package com.arangodb.entity; + +public final class CursorWarning { + + private Integer code; + private String message; + + public Integer getCode() { + return code; + } + + public String getMessage() { + return message; + } + +} diff --git a/src/main/java/com/arangodb/entity/DatabaseEntity.java b/core/src/main/java/com/arangodb/entity/DatabaseEntity.java similarity index 82% rename from src/main/java/com/arangodb/entity/DatabaseEntity.java rename to core/src/main/java/com/arangodb/entity/DatabaseEntity.java index 975065f50..3b996d033 100644 --- a/src/main/java/com/arangodb/entity/DatabaseEntity.java +++ b/core/src/main/java/com/arangodb/entity/DatabaseEntity.java @@ -24,19 +24,18 @@ * @author Mark Vollmary * @see API Documentation */ -public class DatabaseEntity implements Entity { +public final class DatabaseEntity { private String id; private String name; private String path; private Boolean isSystem; - private final ReplicationFactor replicationFactor; + private ReplicationFactor replicationFactor; private Integer writeConcern; private String sharding; public DatabaseEntity() { super(); - replicationFactor = new ReplicationFactor(); } /** @@ -71,8 +70,8 @@ public Boolean getIsSystem() { * @return the default replication factor for collections in this database * @since ArangoDB 3.6.0 */ - public Integer getReplicationFactor() { - return replicationFactor.getReplicationFactor(); + public ReplicationFactor getReplicationFactor() { + return replicationFactor; } /** @@ -87,14 +86,6 @@ public Integer getWriteConcern() { return writeConcern; } - /** - * @return whether the collection is a satellite collection. Only in an enterprise cluster setup (else returning null). - * @since ArangoDB 3.6.0 - */ - public Boolean getSatellite() { - return this.replicationFactor.getSatellite(); - } - /** * @return information about the default sharding method for collections created in this database * @since ArangoDB 3.6.0 diff --git a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java b/core/src/main/java/com/arangodb/entity/DocumentCreateEntity.java similarity index 89% rename from src/main/java/com/arangodb/entity/DocumentCreateEntity.java rename to core/src/main/java/com/arangodb/entity/DocumentCreateEntity.java index 9469325bf..58e58e996 100644 --- a/src/main/java/com/arangodb/entity/DocumentCreateEntity.java +++ b/core/src/main/java/com/arangodb/entity/DocumentCreateEntity.java @@ -20,18 +20,16 @@ package com.arangodb.entity; -import com.arangodb.velocypack.annotations.Expose; +import com.arangodb.internal.serde.UserData; /** * @author Mark Vollmary * @see API * Documentation */ -public class DocumentCreateEntity extends DocumentEntity { +public final class DocumentCreateEntity extends DocumentEntity { - @Expose(deserialize = false) private T newDocument; - @Expose(deserialize = false) private T oldDocument; public DocumentCreateEntity() { @@ -45,6 +43,7 @@ public T getNew() { return newDocument; } + @UserData public void setNew(final T newDocument) { this.newDocument = newDocument; } @@ -57,6 +56,7 @@ public T getOld() { return oldDocument; } + @UserData public void setOld(final T oldDocument) { this.oldDocument = oldDocument; } diff --git a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java b/core/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java similarity index 86% rename from src/main/java/com/arangodb/entity/DocumentDeleteEntity.java rename to core/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java index 336ec53c1..26af4f671 100644 --- a/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java +++ b/core/src/main/java/com/arangodb/entity/DocumentDeleteEntity.java @@ -1,50 +1,50 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.arangodb.velocypack.annotations.Expose; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public class DocumentDeleteEntity extends DocumentEntity { - - @Expose(deserialize = false) - private T oldDocument; - - public DocumentDeleteEntity() { - super(); - } - - /** - * @return If the query parameter returnOld is true, then the complete previous revision of the document is - * returned. - */ - public T getOld() { - return oldDocument; - } - - public void setOld(final T oldDocument) { - this.oldDocument = oldDocument; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.arangodb.internal.serde.UserData; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class DocumentDeleteEntity extends DocumentEntity { + + private T oldDocument; + + public DocumentDeleteEntity() { + super(); + } + + /** + * @return If the query parameter returnOld is true, then the complete previous revision of the document is + * returned. + */ + public T getOld() { + return oldDocument; + } + + @UserData + public void setOld(final T oldDocument) { + this.oldDocument = oldDocument; + } +} diff --git a/src/main/java/com/arangodb/entity/DocumentEntity.java b/core/src/main/java/com/arangodb/entity/DocumentEntity.java similarity index 74% rename from src/main/java/com/arangodb/entity/DocumentEntity.java rename to core/src/main/java/com/arangodb/entity/DocumentEntity.java index 1b973e32d..56cc8545b 100644 --- a/src/main/java/com/arangodb/entity/DocumentEntity.java +++ b/core/src/main/java/com/arangodb/entity/DocumentEntity.java @@ -20,16 +20,24 @@ package com.arangodb.entity; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * @author Mark Vollmary */ -public class DocumentEntity implements Entity { +public class DocumentEntity { - @Key + @JsonProperty("_key") + @JsonInclude(JsonInclude.Include.NON_NULL) private String key; - @Id + + @JsonProperty("_id") + @JsonInclude(JsonInclude.Include.NON_NULL) private String id; - @Rev + + @JsonProperty("_rev") + @JsonInclude(JsonInclude.Include.NON_NULL) private String rev; public DocumentEntity() { diff --git a/src/main/java/com/arangodb/entity/DocumentImportEntity.java b/core/src/main/java/com/arangodb/entity/DocumentImportEntity.java similarity index 98% rename from src/main/java/com/arangodb/entity/DocumentImportEntity.java rename to core/src/main/java/com/arangodb/entity/DocumentImportEntity.java index bd57c65fc..b4f6a469f 100644 --- a/src/main/java/com/arangodb/entity/DocumentImportEntity.java +++ b/core/src/main/java/com/arangodb/entity/DocumentImportEntity.java @@ -26,7 +26,7 @@ /** * @author Mark Vollmary */ -public class DocumentImportEntity implements Entity { +public final class DocumentImportEntity { private Integer created; private Integer errors; diff --git a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java b/core/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java similarity index 83% rename from src/main/java/com/arangodb/entity/DocumentUpdateEntity.java rename to core/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java index 009468000..0fa122454 100644 --- a/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java +++ b/core/src/main/java/com/arangodb/entity/DocumentUpdateEntity.java @@ -1,72 +1,72 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.arangodb.velocypack.annotations.Expose; -import com.arangodb.velocypack.annotations.SerializedName; - -/** - * @param - * @author Mark Vollmary - * @see API - * Documentation - */ -public class DocumentUpdateEntity extends DocumentEntity { - - @SerializedName("_oldRev") - private String oldRev; - @Expose(deserialize = false) - private T newDocument; - @Expose(deserialize = false) - private T oldDocument; - - public DocumentUpdateEntity() { - super(); - } - - public String getOldRev() { - return oldRev; - } - - /** - * @return If the query parameter returnNew is true, then the complete new document is returned. - */ - public T getNew() { - return newDocument; - } - - public void setNew(final T newDocument) { - this.newDocument = newDocument; - } - - /** - * @return If the query parameter returnOld is true, then the complete previous revision of the document is - * returned. - */ - public T getOld() { - return oldDocument; - } - - public void setOld(final T oldDocument) { - this.oldDocument = oldDocument; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.arangodb.internal.serde.UserData; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class DocumentUpdateEntity extends DocumentEntity { + + @JsonProperty("_oldRev") + private String oldRev; + private T newDocument; + private T oldDocument; + + public DocumentUpdateEntity() { + super(); + } + + public String getOldRev() { + return oldRev; + } + + /** + * @return If the query parameter returnNew is true, then the complete new document is returned. + */ + public T getNew() { + return newDocument; + } + + @UserData + public void setNew(final T newDocument) { + this.newDocument = newDocument; + } + + /** + * @return If the query parameter returnOld is true, then the complete previous revision of the document is + * returned. + */ + public T getOld() { + return oldDocument; + } + + @UserData + public void setOld(final T oldDocument) { + this.oldDocument = oldDocument; + } + +} diff --git a/src/main/java/com/arangodb/entity/EdgeDefinition.java b/core/src/main/java/com/arangodb/entity/EdgeDefinition.java similarity index 85% rename from src/main/java/com/arangodb/entity/EdgeDefinition.java rename to core/src/main/java/com/arangodb/entity/EdgeDefinition.java index 140e01567..45b76c795 100644 --- a/src/main/java/com/arangodb/entity/EdgeDefinition.java +++ b/core/src/main/java/com/arangodb/entity/EdgeDefinition.java @@ -1,84 +1,92 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import java.util.Arrays; -import java.util.Collection; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class EdgeDefinition { - - private String collection; - private Collection from; - private Collection to; - private Options options; - - public String getCollection() { - return collection; - } - - public EdgeDefinition collection(final String collection) { - this.collection = collection; - return this; - } - - public Collection getFrom() { - return from; - } - - public EdgeDefinition from(final String... from) { - this.from = Arrays.asList(from); - return this; - } - - public Collection getTo() { - return to; - } - - public EdgeDefinition to(final String... to) { - this.to = Arrays.asList(to); - return this; - } - - public Collection getSatellites() { - return options.satellites; - } - - /** - * @param satellites collection names that will be used to create SatelliteCollections - * for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only). Each array element - * must be a valid collection name. The collection type cannot be modified later. - * @return this - * @since ArangoDB 3.9.0 - */ - public EdgeDefinition satellites(final String... satellites) { - options = new Options(); - options.satellites = Arrays.asList(satellites); - return this; - } - - public static class Options { - private Collection satellites; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class EdgeDefinition { + + private final Options options = new Options(); + private String collection; + private Collection from; + private Collection to; + + public String getCollection() { + return collection; + } + + public EdgeDefinition collection(final String collection) { + this.collection = collection; + return this; + } + + public Collection getFrom() { + return from; + } + + public EdgeDefinition from(final String... from) { + this.from = Arrays.asList(from); + return this; + } + + public Collection getTo() { + return to; + } + + public EdgeDefinition to(final String... to) { + this.to = Arrays.asList(to); + return this; + } + + public Collection getSatellites() { + return options.satellites; + } + + public Options getOptions() { + return options; + } + + /** + * @param satellites collection names that will be used to create SatelliteCollections + * for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only). Each array element + * must be a valid collection name. The collection type cannot be modified later. + * @return this + * @since ArangoDB 3.9.0 + */ + public EdgeDefinition satellites(final String... satellites) { + options.satellites = Arrays.asList(satellites); + return this; + } + + public static final class Options { + private Collection satellites = Collections.emptyList(); + + public Collection getSatellites() { + return satellites; + } + } +} diff --git a/src/main/java/com/arangodb/entity/EdgeEntity.java b/core/src/main/java/com/arangodb/entity/EdgeEntity.java similarity index 90% rename from src/main/java/com/arangodb/entity/EdgeEntity.java rename to core/src/main/java/com/arangodb/entity/EdgeEntity.java index c62f7d131..39d9017db 100644 --- a/src/main/java/com/arangodb/entity/EdgeEntity.java +++ b/core/src/main/java/com/arangodb/entity/EdgeEntity.java @@ -1,32 +1,32 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public class EdgeEntity extends DocumentEntity { - - public EdgeEntity() { - super(); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public final class EdgeEntity extends DocumentEntity { + + public EdgeEntity() { + super(); + } + +} diff --git a/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java b/core/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java similarity index 84% rename from src/main/java/com/arangodb/entity/EdgeUpdateEntity.java rename to core/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java index f872666a3..495cf229d 100644 --- a/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java +++ b/core/src/main/java/com/arangodb/entity/EdgeUpdateEntity.java @@ -1,42 +1,42 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.arangodb.velocypack.annotations.SerializedName; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class EdgeUpdateEntity extends DocumentEntity { - - @SerializedName("_oldRev") - private String oldRev; - - public EdgeUpdateEntity() { - super(); - } - - public String getOldRev() { - return oldRev; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class EdgeUpdateEntity extends DocumentEntity { + + @JsonProperty("_oldRev") + private String oldRev; + + public EdgeUpdateEntity() { + super(); + } + + public String getOldRev() { + return oldRev; + } + +} diff --git a/src/main/java/com/arangodb/entity/ErrorEntity.java b/core/src/main/java/com/arangodb/entity/ErrorEntity.java similarity index 96% rename from src/main/java/com/arangodb/entity/ErrorEntity.java rename to core/src/main/java/com/arangodb/entity/ErrorEntity.java index 48a1c582b..5677d2301 100644 --- a/src/main/java/com/arangodb/entity/ErrorEntity.java +++ b/core/src/main/java/com/arangodb/entity/ErrorEntity.java @@ -25,7 +25,7 @@ /** * @author Mark Vollmary */ -public class ErrorEntity implements Serializable, Entity { +public final class ErrorEntity implements Serializable { private static final long serialVersionUID = -5918898261563691261L; diff --git a/src/main/java/com/arangodb/entity/GraphEntity.java b/core/src/main/java/com/arangodb/entity/GraphEntity.java similarity index 81% rename from src/main/java/com/arangodb/entity/GraphEntity.java rename to core/src/main/java/com/arangodb/entity/GraphEntity.java index 96dcc3299..07145ee60 100644 --- a/src/main/java/com/arangodb/entity/GraphEntity.java +++ b/core/src/main/java/com/arangodb/entity/GraphEntity.java @@ -26,7 +26,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class GraphEntity implements Entity { +public final class GraphEntity { private String name; /** @@ -40,7 +40,6 @@ public class GraphEntity implements Entity { private Integer numberOfShards; private String smartGraphAttribute; private ReplicationFactor replicationFactor; - private Integer minReplicationFactor; private Integer writeConcern; public String getName() { @@ -67,20 +66,8 @@ public Integer getNumberOfShards() { return numberOfShards; } - public Integer getReplicationFactor() { - return replicationFactor.getReplicationFactor(); - } - - public Boolean getSatellite() { - return this.replicationFactor.getSatellite(); - } - - /** - * @deprecated use {@link #getWriteConcern()} instead - */ - @Deprecated - public Integer getMinReplicationFactor() { - return minReplicationFactor; + public ReplicationFactor getReplicationFactor() { + return replicationFactor; } public Integer getWriteConcern() { diff --git a/src/main/java/com/arangodb/entity/IndexEntity.java b/core/src/main/java/com/arangodb/entity/IndexEntity.java similarity index 85% rename from src/main/java/com/arangodb/entity/IndexEntity.java rename to core/src/main/java/com/arangodb/entity/IndexEntity.java index b359a5146..06bf9c65f 100644 --- a/src/main/java/com/arangodb/entity/IndexEntity.java +++ b/core/src/main/java/com/arangodb/entity/IndexEntity.java @@ -25,7 +25,7 @@ /** * @author Mark Vollmary */ -public class IndexEntity implements Entity { +public final class IndexEntity { private String id; private String name; @@ -42,6 +42,9 @@ public class IndexEntity implements Entity { private Integer expireAfter; private Boolean inBackground; private Boolean estimates; + private Boolean cacheEnabled; + private Collection storedValues; + private Boolean legacyPolygons; public IndexEntity() { super(); @@ -107,4 +110,16 @@ public Boolean getEstimates() { return estimates; } + public Boolean getCacheEnabled() { + return cacheEnabled; + } + + public Collection getStoredValues() { + return storedValues; + } + + public Boolean getLegacyPolygons() { + return legacyPolygons; + } + } diff --git a/src/main/java/com/arangodb/entity/IndexType.java b/core/src/main/java/com/arangodb/entity/IndexType.java similarity index 72% rename from src/main/java/com/arangodb/entity/IndexType.java rename to core/src/main/java/com/arangodb/entity/IndexType.java index 062f35ff1..d3303b5f5 100644 --- a/src/main/java/com/arangodb/entity/IndexType.java +++ b/core/src/main/java/com/arangodb/entity/IndexType.java @@ -1,29 +1,59 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - * @author Heiko Kernbach - */ -public enum IndexType { - primary, hash, skiplist, persistent, geo, geo1, geo2, fulltext, edge, ttl, zkd -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + * @author Heiko Kernbach + */ +public enum IndexType { + + primary, + + hash, + + skiplist, + + persistent, + + geo, + + geo1, + + geo2, + + /** + * @deprecated since ArangoDB 3.10, use ArangoSearch or Inverted indexes instead. + */ + @Deprecated + fulltext, + + edge, + + ttl, + + zkd, + + /** + * @since ArangoDB 3.10 + */ + inverted +} diff --git a/core/src/main/java/com/arangodb/entity/InvertedIndexEntity.java b/core/src/main/java/com/arangodb/entity/InvertedIndexEntity.java new file mode 100644 index 000000000..c6e184615 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/InvertedIndexEntity.java @@ -0,0 +1,152 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.arangodb.entity.arangosearch.AnalyzerFeature; +import com.arangodb.entity.arangosearch.ConsolidationPolicy; +import com.arangodb.entity.arangosearch.StoredValue; + +import java.util.Collection; +import java.util.Set; + +/** + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public final class InvertedIndexEntity { + + private String id; + private Boolean isNewlyCreated; + private Boolean unique; + private Boolean sparse; + private Long version; + private Integer code; + private IndexType type; + private String name; + private Collection fields; + private Boolean searchField; + private Collection storedValues; + private InvertedIndexPrimarySort primarySort; + private String analyzer; + private Set features; + private Boolean includeAllFields; + private Boolean trackListPositions; + private Long cleanupIntervalStep; + private Long commitIntervalMsec; + private Long consolidationIntervalMsec; + private ConsolidationPolicy consolidationPolicy; + private Long writebufferIdle; + private Long writebufferActive; + private Long writebufferSizeMax; + + public String getId() { + return id; + } + + public Boolean getIsNewlyCreated() { + return isNewlyCreated; + } + + public Boolean getUnique() { + return unique; + } + + public Boolean getSparse() { + return sparse; + } + + public Long getVersion() { + return version; + } + + public Integer getCode() { + return code; + } + + public IndexType getType() { + return type; + } + + public String getName() { + return name; + } + + public Collection getFields() { + return fields; + } + + public Boolean getSearchField() { + return searchField; + } + + public Collection getStoredValues() { + return storedValues; + } + + public InvertedIndexPrimarySort getPrimarySort() { + return primarySort; + } + + public String getAnalyzer() { + return analyzer; + } + + public Set getFeatures() { + return features; + } + + public Boolean getIncludeAllFields() { + return includeAllFields; + } + + public Boolean getTrackListPositions() { + return trackListPositions; + } + + public Long getCleanupIntervalStep() { + return cleanupIntervalStep; + } + + public Long getCommitIntervalMsec() { + return commitIntervalMsec; + } + + public Long getConsolidationIntervalMsec() { + return consolidationIntervalMsec; + } + + public ConsolidationPolicy getConsolidationPolicy() { + return consolidationPolicy; + } + + public Long getWritebufferIdle() { + return writebufferIdle; + } + + public Long getWritebufferActive() { + return writebufferActive; + } + + public Long getWritebufferSizeMax() { + return writebufferSizeMax; + } +} diff --git a/core/src/main/java/com/arangodb/entity/InvertedIndexField.java b/core/src/main/java/com/arangodb/entity/InvertedIndexField.java new file mode 100644 index 000000000..29f59c7c5 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/InvertedIndexField.java @@ -0,0 +1,149 @@ +package com.arangodb.entity; + +import com.arangodb.entity.arangosearch.AnalyzerFeature; + +import java.util.*; + +/** + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public final class InvertedIndexField { + private String name; + private String analyzer; + private Boolean includeAllFields; + private Boolean searchField; + private Boolean trackListPositions; + private final Set features = new HashSet<>(); + private Collection nested; + + public String getName() { + return name; + } + + /** + * @param name An attribute path. The . character denotes sub-attributes. + * @return this + */ + public InvertedIndexField name(String name) { + this.name = name; + return this; + } + + public String getAnalyzer() { + return analyzer; + } + + /** + * @param analyzer The name of an Analyzer to use for this field. Default: the value defined by the top-level + * analyzer option, or if not set, the default identity Analyzer. + * @return this + */ + public InvertedIndexField analyzer(String analyzer) { + this.analyzer = analyzer; + return this; + } + + public Boolean getIncludeAllFields() { + return includeAllFields; + } + + /** + * @param includeAllFields This option only applies if you use the inverted index in a search-alias Views. If set to + * true, then all sub-attributes of this field are indexed, excluding any sub-attributes + * that are configured separately by other elements in the fields array (and their + * sub-attributes). The analyzer and features properties apply to the sub-attributes. If set + * to false, then sub-attributes are ignored. The default value is defined by the top-level + * includeAllFields option, or false if not set. + * @return this + */ + public InvertedIndexField includeAllFields(Boolean includeAllFields) { + this.includeAllFields = includeAllFields; + return this; + } + + public Boolean getSearchField() { + return searchField; + } + + /** + * @param searchField This option only applies if you use the inverted index in a search-alias Views. You can set + * the option to true to get the same behavior as with arangosearch Views regarding the indexing + * of array values for this field. If enabled, both, array and primitive values (strings, + * numbers, etc.) are accepted. Every element of an array is indexed according to the + * trackListPositions option. If set to false, it depends on the attribute path. If it explicitly + * expand an array ([*]), then the elements are indexed separately. Otherwise, the array is + * indexed as a whole, but only geopoint and aql Analyzers accept array inputs. You cannot use an + * array expansion if searchField is enabled. Default: the value defined by the top-level + * searchField option, or false if not set. + * @return this + */ + public InvertedIndexField searchField(Boolean searchField) { + this.searchField = searchField; + return this; + } + + public Boolean getTrackListPositions() { + return trackListPositions; + } + + /** + * @param trackListPositions This option only applies if you use the inverted index in a search-alias Views. If set + * to true, then track the value position in arrays for array values. For example, when + * querying a document like { attr: [ "valueX", "valueY", "valueZ" ] }, you need to + * specify the array element, e.g. doc.attr[1] == "valueY". If set to false, all values in + * an array are treated as equal alternatives. You don’t specify an array element in + * queries, e.g. doc.attr == "valueY", and all elements are searched for a match. Default: + * the value defined by the top-level trackListPositions option, or false if not set. + * @return this + */ + public InvertedIndexField trackListPositions(Boolean trackListPositions) { + this.trackListPositions = trackListPositions; + return this; + } + + public Set getFeatures() { + return features; + } + + /** + * @param features A list of Analyzer features to use for this field. They define what features are enabled for the + * analyzer. + * @return this + */ + public InvertedIndexField features(AnalyzerFeature... features) { + Collections.addAll(this.features, features); + return this; + } + + public Collection getNested() { + return nested; + } + + /** + * @param nested Index the specified sub-objects that are stored in an array. Other than with the fields property, + * the values get indexed in a way that lets you query for co-occurring values. For example, you can + * search the sub-objects and all the conditions need to be met by a single sub-object instead of + * across all of them. This property is available in the Enterprise Edition only. + * @return this + */ + public InvertedIndexField nested(InvertedIndexField... nested) { + if (this.nested == null) this.nested = new ArrayList<>(); + Collections.addAll(this.nested, nested); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + InvertedIndexField that = (InvertedIndexField) o; + return Objects.equals(name, that.name) && Objects.equals(analyzer, that.analyzer) && Objects.equals(includeAllFields, that.includeAllFields) && Objects.equals(searchField, that.searchField) && Objects.equals(trackListPositions, that.trackListPositions) && Objects.equals(features, that.features) && Objects.equals(nested, that.nested); + } + + @Override + public int hashCode() { + return Objects.hash(name, analyzer, includeAllFields, searchField, trackListPositions, features, nested); + } +} diff --git a/core/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java b/core/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java new file mode 100644 index 000000000..c4a3677d8 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/InvertedIndexPrimarySort.java @@ -0,0 +1,102 @@ +package com.arangodb.entity; + +import com.arangodb.entity.arangosearch.ArangoSearchCompression; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public final class InvertedIndexPrimarySort { + private final List fields = new ArrayList<>(); + private ArangoSearchCompression compression; + + public List getFields() { + return fields; + } + + /** + * @param fields An array of the fields to sort the index by and the direction to sort each field in. + * @return this + */ + public InvertedIndexPrimarySort fields(Field... fields) { + Collections.addAll(this.fields, fields); + return this; + } + + public ArangoSearchCompression getCompression() { + return compression; + } + + /** + * @param compression Defines how to compress the primary sort data. + * @return this + */ + public InvertedIndexPrimarySort compression(ArangoSearchCompression compression) { + this.compression = compression; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + InvertedIndexPrimarySort that = (InvertedIndexPrimarySort) o; + return Objects.equals(fields, that.fields) && compression == that.compression; + } + + @Override + public int hashCode() { + return Objects.hash(fields, compression); + } + + public static class Field { + private final String field; + private final Direction direction; + + /** + * @param field An attribute path. The . character denotes sub-attributes. + * @param direction The sorting direction. + */ + @JsonCreator + public Field(@JsonProperty("field") String field, @JsonProperty("direction") Direction direction) { + this.field = field; + this.direction = direction; + } + + public String getField() { + return field; + } + + public Direction getDirection() { + return direction; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Field field1 = (Field) o; + return Objects.equals(field, field1.field) && direction == field1.direction; + } + + @Override + public int hashCode() { + return Objects.hash(field, direction); + } + + public enum Direction { + asc, + desc + } + + } + +} diff --git a/src/main/java/com/arangodb/entity/KeyOptions.java b/core/src/main/java/com/arangodb/entity/KeyOptions.java similarity index 94% rename from src/main/java/com/arangodb/entity/KeyOptions.java rename to core/src/main/java/com/arangodb/entity/KeyOptions.java index 261450638..7206c9dbb 100644 --- a/src/main/java/com/arangodb/entity/KeyOptions.java +++ b/core/src/main/java/com/arangodb/entity/KeyOptions.java @@ -1,77 +1,77 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public class KeyOptions { - - private Boolean allowUserKeys; - private KeyType type; - private Integer increment; - private Integer offset; - - public KeyOptions() { - super(); - } - - public KeyOptions(final Boolean allowUserKeys, final KeyType type, final Integer increment, final Integer offset) { - super(); - this.allowUserKeys = allowUserKeys; - this.type = type; - this.increment = increment; - this.offset = offset; - } - - public Boolean getAllowUserKeys() { - return allowUserKeys; - } - - public void setAllowUserKeys(final Boolean allowUserKeys) { - this.allowUserKeys = allowUserKeys; - } - - public KeyType getType() { - return type; - } - - public void setType(final KeyType type) { - this.type = type; - } - - public Integer getIncrement() { - return increment; - } - - public void setIncrement(final Integer increment) { - this.increment = increment; - } - - public Integer getOffset() { - return offset; - } - - public void setOffset(final Integer offset) { - this.offset = offset; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public final class KeyOptions { + + private Boolean allowUserKeys; + private KeyType type; + private Integer increment; + private Integer offset; + + public KeyOptions() { + super(); + } + + public KeyOptions(final Boolean allowUserKeys, final KeyType type, final Integer increment, final Integer offset) { + super(); + this.allowUserKeys = allowUserKeys; + this.type = type; + this.increment = increment; + this.offset = offset; + } + + public Boolean getAllowUserKeys() { + return allowUserKeys; + } + + public void setAllowUserKeys(final Boolean allowUserKeys) { + this.allowUserKeys = allowUserKeys; + } + + public KeyType getType() { + return type; + } + + public void setType(final KeyType type) { + this.type = type; + } + + public Integer getIncrement() { + return increment; + } + + public void setIncrement(final Integer increment) { + this.increment = increment; + } + + public Integer getOffset() { + return offset; + } + + public void setOffset(final Integer offset) { + this.offset = offset; + } + +} diff --git a/src/main/java/com/arangodb/entity/KeyType.java b/core/src/main/java/com/arangodb/entity/KeyType.java similarity index 96% rename from src/main/java/com/arangodb/entity/KeyType.java rename to core/src/main/java/com/arangodb/entity/KeyType.java index 215ec6d0f..4ac2da4f3 100644 --- a/src/main/java/com/arangodb/entity/KeyType.java +++ b/core/src/main/java/com/arangodb/entity/KeyType.java @@ -1,28 +1,28 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public enum KeyType { - traditional, autoincrement, uuid, padded -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public enum KeyType { + traditional, autoincrement, uuid, padded +} diff --git a/src/main/java/com/arangodb/entity/License.java b/core/src/main/java/com/arangodb/entity/License.java similarity index 83% rename from src/main/java/com/arangodb/entity/License.java rename to core/src/main/java/com/arangodb/entity/License.java index 053b2ca64..92803eed4 100644 --- a/src/main/java/com/arangodb/entity/License.java +++ b/core/src/main/java/com/arangodb/entity/License.java @@ -20,11 +20,17 @@ package com.arangodb.entity; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * @author Axel Becker */ public enum License { - ENTERPRISE, COMMUNITY + @JsonProperty("enterprise") + ENTERPRISE, + + @JsonProperty("community") + COMMUNITY } diff --git a/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java b/core/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java similarity index 96% rename from src/main/java/com/arangodb/entity/LoadBalancingStrategy.java rename to core/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java index 9508dff48..525744fb3 100644 --- a/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java +++ b/core/src/main/java/com/arangodb/entity/LoadBalancingStrategy.java @@ -1,28 +1,28 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public enum LoadBalancingStrategy { - NONE, ROUND_ROBIN, ONE_RANDOM -} +/* + * DISCLAIMER + * + * Copyright 2017 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public enum LoadBalancingStrategy { + NONE, ROUND_ROBIN, ONE_RANDOM +} diff --git a/src/main/java/com/arangodb/entity/LogEntriesEntity.java b/core/src/main/java/com/arangodb/entity/LogEntriesEntity.java similarity index 87% rename from src/main/java/com/arangodb/entity/LogEntriesEntity.java rename to core/src/main/java/com/arangodb/entity/LogEntriesEntity.java index 43d0954b5..f7bf4ee51 100644 --- a/src/main/java/com/arangodb/entity/LogEntriesEntity.java +++ b/core/src/main/java/com/arangodb/entity/LogEntriesEntity.java @@ -24,11 +24,12 @@ /** * @author Michele Rastelli - * @see API + * @see + * API * Documentation * @since ArangoDB 3.8 */ -public class LogEntriesEntity implements Entity { +public final class LogEntriesEntity { private Long total; private List messages; @@ -41,7 +42,7 @@ public List getMessages() { return messages; } - public static class Message { + public static final class Message { Long id; String topic; String level; diff --git a/src/main/java/com/arangodb/entity/LogLevel.java b/core/src/main/java/com/arangodb/entity/LogLevel.java similarity index 100% rename from src/main/java/com/arangodb/entity/LogLevel.java rename to core/src/main/java/com/arangodb/entity/LogLevel.java index 4e220339f..8895bfa7a 100644 --- a/src/main/java/com/arangodb/entity/LogLevel.java +++ b/core/src/main/java/com/arangodb/entity/LogLevel.java @@ -33,10 +33,6 @@ public enum LogLevel { this.level = level; } - public int getLevel() { - return level; - } - public static LogLevel fromLevel(final int level) { for (final LogLevel logLevel : LogLevel.values()) { if (logLevel.level == level) { @@ -46,4 +42,8 @@ public static LogLevel fromLevel(final int level) { return null; } + public int getLevel() { + return level; + } + } diff --git a/src/main/java/com/arangodb/entity/LogLevelEntity.java b/core/src/main/java/com/arangodb/entity/LogLevelEntity.java similarity index 97% rename from src/main/java/com/arangodb/entity/LogLevelEntity.java rename to core/src/main/java/com/arangodb/entity/LogLevelEntity.java index adcc1b393..890998a68 100644 --- a/src/main/java/com/arangodb/entity/LogLevelEntity.java +++ b/core/src/main/java/com/arangodb/entity/LogLevelEntity.java @@ -23,11 +23,7 @@ /** * @author Mark Vollmary */ -public class LogLevelEntity implements Entity { - - public enum LogLevel { - FATAL, ERROR, WARNING, INFO, DEBUG, TRACE, DEFAULT - } +public final class LogLevelEntity { private LogLevel all; private LogLevel agency; @@ -53,6 +49,10 @@ public LogLevelEntity() { super(); } + public LogLevel getAll() { + return all; + } + public void setAll(final LogLevel all) { this.all = all; } @@ -201,4 +201,8 @@ public void setV8(final LogLevel v8) { this.v8 = v8; } + public enum LogLevel { + FATAL, ERROR, WARNING, INFO, DEBUG, TRACE, DEFAULT + } + } diff --git a/src/main/java/com/arangodb/entity/MetaAware.java b/core/src/main/java/com/arangodb/entity/MetaAware.java similarity index 100% rename from src/main/java/com/arangodb/entity/MetaAware.java rename to core/src/main/java/com/arangodb/entity/MetaAware.java diff --git a/src/main/java/com/arangodb/entity/MultiDocumentEntity.java b/core/src/main/java/com/arangodb/entity/MultiDocumentEntity.java similarity index 80% rename from src/main/java/com/arangodb/entity/MultiDocumentEntity.java rename to core/src/main/java/com/arangodb/entity/MultiDocumentEntity.java index bd619c4f9..6a4c5f3e0 100644 --- a/src/main/java/com/arangodb/entity/MultiDocumentEntity.java +++ b/core/src/main/java/com/arangodb/entity/MultiDocumentEntity.java @@ -25,11 +25,12 @@ /** * @author Mark Vollmary */ -public class MultiDocumentEntity implements Entity { +public final class MultiDocumentEntity { private Collection documents; private Collection errors; private Collection documentsAndErrors; + private boolean isPotentialDirtyRead = false; public MultiDocumentEntity() { super(); @@ -68,4 +69,15 @@ public void setDocumentsAndErrors(final Collection documentsAndErrors) { this.documentsAndErrors = documentsAndErrors; } + /** + * @return true if the result is a potential dirty read + * @since ArangoDB 3.10 + */ + public Boolean isPotentialDirtyRead() { + return isPotentialDirtyRead; + } + + public void setPotentialDirtyRead(final Boolean isPotentialDirtyRead) { + this.isPotentialDirtyRead = isPotentialDirtyRead; + } } diff --git a/src/main/java/com/arangodb/entity/Permissions.java b/core/src/main/java/com/arangodb/entity/Permissions.java similarity index 87% rename from src/main/java/com/arangodb/entity/Permissions.java rename to core/src/main/java/com/arangodb/entity/Permissions.java index 774f36c42..73f8b8105 100644 --- a/src/main/java/com/arangodb/entity/Permissions.java +++ b/core/src/main/java/com/arangodb/entity/Permissions.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * @author Mark Vollmary */ @@ -28,11 +30,16 @@ public enum Permissions { /** * read and write access */ + @JsonProperty("rw") RW, + /** * read-only access */ + @JsonProperty("ro") RO, + + @JsonProperty("none") NONE } diff --git a/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java b/core/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java similarity index 96% rename from src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java rename to core/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java index d820aa0c9..d0e8b73c8 100644 --- a/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java +++ b/core/src/main/java/com/arangodb/entity/QueryCachePropertiesEntity.java @@ -26,11 +26,7 @@ * "https://www.arangodb.com/docs/stable/http/aql-query-cache.html">API * Documentation */ -public class QueryCachePropertiesEntity implements Entity { - - public enum CacheMode { - off, on, demand - } +public final class QueryCachePropertiesEntity { private CacheMode mode; private Long maxResults; @@ -67,4 +63,8 @@ public void setMaxResults(final Long maxResults) { this.maxResults = maxResults; } + public enum CacheMode { + off, on, demand + } + } diff --git a/src/main/java/com/arangodb/entity/QueryEntity.java b/core/src/main/java/com/arangodb/entity/QueryEntity.java similarity index 97% rename from src/main/java/com/arangodb/entity/QueryEntity.java rename to core/src/main/java/com/arangodb/entity/QueryEntity.java index 2e78b1ed4..04cff2fe0 100644 --- a/src/main/java/com/arangodb/entity/QueryEntity.java +++ b/core/src/main/java/com/arangodb/entity/QueryEntity.java @@ -26,7 +26,7 @@ /** * @author Mark Vollmary */ -public class QueryEntity implements Entity { +public final class QueryEntity { public static final String PROPERTY_STARTED = "started"; diff --git a/src/main/java/com/arangodb/entity/QueryExecutionState.java b/core/src/main/java/com/arangodb/entity/QueryExecutionState.java similarity index 69% rename from src/main/java/com/arangodb/entity/QueryExecutionState.java rename to core/src/main/java/com/arangodb/entity/QueryExecutionState.java index 75e75df87..aa56f92e9 100644 --- a/src/main/java/com/arangodb/entity/QueryExecutionState.java +++ b/core/src/main/java/com/arangodb/entity/QueryExecutionState.java @@ -1,38 +1,61 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public enum QueryExecutionState { - INITIALIZING, - PARSING, - OPTIMIZING_AST, - LOADING_COLLECTIONS, - INSTANTIATING_PLAN, - OPTIMIZING_PLAN, - EXECUTING, - FINALIZING, - FINISHED, - KILLED, - INVALID -} +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author Mark Vollmary + */ +public enum QueryExecutionState { + @JsonProperty("initializing") + INITIALIZING, + + @JsonProperty("parsing") + PARSING, + + @JsonProperty("optimizing ast") + OPTIMIZING_AST, + + @JsonProperty("loading collections") + LOADING_COLLECTIONS, + + @JsonProperty("instantiating plan") + INSTANTIATING_PLAN, + + @JsonProperty("optimizing plan") + OPTIMIZING_PLAN, + + @JsonProperty("executing") + EXECUTING, + + @JsonProperty("finalizing") + FINALIZING, + + @JsonProperty("finished") + FINISHED, + + @JsonProperty("killed") + KILLED, + + @JsonProperty("invalid") + INVALID +} diff --git a/core/src/main/java/com/arangodb/entity/QueryOptimizerRule.java b/core/src/main/java/com/arangodb/entity/QueryOptimizerRule.java new file mode 100644 index 000000000..e6b543a6d --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/QueryOptimizerRule.java @@ -0,0 +1,50 @@ +package com.arangodb.entity; + +/** + * @since ArangoDB 3.10 + */ +public final class QueryOptimizerRule { + private String name; + private Flags flags; + + public String getName() { + return name; + } + + public Flags getFlags() { + return flags; + } + + public static class Flags { + private Boolean hidden; + private Boolean clusterOnly; + private Boolean canBeDisabled; + private Boolean canCreateAdditionalPlans; + private Boolean disabledByDefault; + private Boolean enterpriseOnly; + + public Boolean getHidden() { + return hidden; + } + + public Boolean getClusterOnly() { + return clusterOnly; + } + + public Boolean getCanBeDisabled() { + return canBeDisabled; + } + + public Boolean getCanCreateAdditionalPlans() { + return canCreateAdditionalPlans; + } + + public Boolean getDisabledByDefault() { + return disabledByDefault; + } + + public Boolean getEnterpriseOnly() { + return enterpriseOnly; + } + } +} diff --git a/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java b/core/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java similarity index 83% rename from src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java rename to core/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java index dc82e447d..80fb242de 100644 --- a/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java +++ b/core/src/main/java/com/arangodb/entity/QueryTrackingPropertiesEntity.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class QueryTrackingPropertiesEntity implements Entity { +public final class QueryTrackingPropertiesEntity { private Boolean enabled; private Boolean trackSlowQueries; @@ -44,7 +44,8 @@ public Boolean getEnabled() { } /** - * @param enabled If set to true, then queries will be tracked. If set to false, neither queries nor slow queries will + * @param enabled If set to true, then queries will be tracked. If set to false, neither queries nor slow queries + * will * be tracked */ public void setEnabled(final Boolean enabled) { @@ -61,8 +62,10 @@ public Boolean getTrackSlowQueries() { } /** - * @param trackSlowQueries If set to true, then slow queries will be tracked in the list of slow queries if their runtime exceeds - * the value set in slowQueryThreshold. In order for slow queries to be tracked, the enabled property + * @param trackSlowQueries If set to true, then slow queries will be tracked in the list of slow queries if their + * runtime exceeds + * the value set in slowQueryThreshold. In order for slow queries to be tracked, the + * enabled property * must also be set to true. */ public void setTrackSlowQueries(final Boolean trackSlowQueries) { @@ -78,7 +81,8 @@ public Long getMaxSlowQueries() { } /** - * @param maxSlowQueries The maximum number of slow queries to keep in the list of slow queries. If the list of slow queries is + * @param maxSlowQueries The maximum number of slow queries to keep in the list of slow queries. If the list of + * slow queries is * full, the oldest entry in it will be discarded when additional slow queries occur. */ public void setMaxSlowQueries(final Long maxSlowQueries) { @@ -95,8 +99,10 @@ public Long getSlowQueryThreshold() { } /** - * @param slowQueryThreshold The threshold value for treating a query as slow. A query with a runtime greater or equal to this - * threshold value will be put into the list of slow queries when slow query tracking is enabled. The + * @param slowQueryThreshold The threshold value for treating a query as slow. A query with a runtime greater or + * equal to this + * threshold value will be put into the list of slow queries when slow query tracking + * is enabled. The * value for slowQueryThreshold is specified in seconds. */ public void setSlowQueryThreshold(final Long slowQueryThreshold) { @@ -113,8 +119,10 @@ public Long getMaxQueryStringLength() { } /** - * @param maxQueryStringLength The maximum query string length to keep in the list of queries. Query strings can have arbitrary - * lengths, and this property can be used to save memory in case very long query strings are used. The + * @param maxQueryStringLength The maximum query string length to keep in the list of queries. Query strings can + * have arbitrary + * lengths, and this property can be used to save memory in case very long query + * strings are used. The * value is specified in bytes. */ public void setMaxQueryStringLength(final Long maxQueryStringLength) { diff --git a/core/src/main/java/com/arangodb/entity/ReplicationFactor.java b/core/src/main/java/com/arangodb/entity/ReplicationFactor.java new file mode 100644 index 000000000..f96ceb0dd --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/ReplicationFactor.java @@ -0,0 +1,60 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.fasterxml.jackson.annotation.JsonValue; + +public interface ReplicationFactor { + + static NumericReplicationFactor of(int value) { + return new NumericReplicationFactor(value); + } + + static SatelliteReplicationFactor ofSatellite() { + return SatelliteReplicationFactor.INSTANCE; + } + + @JsonValue + Object getValue(); + + enum SatelliteReplicationFactor implements ReplicationFactor { + INSTANCE; + + @Override + public String getValue() { + return "satellite"; + } + } + + final class NumericReplicationFactor implements ReplicationFactor { + + private final Integer value; + + public NumericReplicationFactor(Integer value) { + this.value = value; + } + + @Override + public Integer getValue() { + return value; + } + } +} diff --git a/src/main/java/com/arangodb/entity/ServerMode.java b/core/src/main/java/com/arangodb/entity/ServerMode.java similarity index 96% rename from src/main/java/com/arangodb/entity/ServerMode.java rename to core/src/main/java/com/arangodb/entity/ServerMode.java index b7f95040c..4cb13610d 100644 --- a/src/main/java/com/arangodb/entity/ServerMode.java +++ b/core/src/main/java/com/arangodb/entity/ServerMode.java @@ -1,28 +1,28 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public enum ServerMode { - DEFAULT, RESILIENT -} +/* + * DISCLAIMER + * + * Copyright 2017 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public enum ServerMode { + DEFAULT, RESILIENT +} diff --git a/src/main/java/com/arangodb/entity/ServerRole.java b/core/src/main/java/com/arangodb/entity/ServerRole.java similarity index 96% rename from src/main/java/com/arangodb/entity/ServerRole.java rename to core/src/main/java/com/arangodb/entity/ServerRole.java index 71e1b7473..a897651ff 100644 --- a/src/main/java/com/arangodb/entity/ServerRole.java +++ b/core/src/main/java/com/arangodb/entity/ServerRole.java @@ -1,28 +1,28 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public enum ServerRole { - SINGLE, AGENT, COORDINATOR, PRIMARY, SECONDARY, UNDEFINED +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public enum ServerRole { + SINGLE, AGENT, COORDINATOR, PRIMARY, SECONDARY, UNDEFINED } \ No newline at end of file diff --git a/src/main/java/com/arangodb/entity/ShardEntity.java b/core/src/main/java/com/arangodb/entity/ShardEntity.java similarity index 95% rename from src/main/java/com/arangodb/entity/ShardEntity.java rename to core/src/main/java/com/arangodb/entity/ShardEntity.java index deeb49db3..8b853a623 100644 --- a/src/main/java/com/arangodb/entity/ShardEntity.java +++ b/core/src/main/java/com/arangodb/entity/ShardEntity.java @@ -23,7 +23,7 @@ /** * @author Michele Rastelli */ -public class ShardEntity implements Entity { +public final class ShardEntity { private String shardId; diff --git a/src/main/java/com/arangodb/entity/ShardingStrategy.java b/core/src/main/java/com/arangodb/entity/ShardingStrategy.java similarity index 83% rename from src/main/java/com/arangodb/entity/ShardingStrategy.java rename to core/src/main/java/com/arangodb/entity/ShardingStrategy.java index a75e3b74d..847c16440 100644 --- a/src/main/java/com/arangodb/entity/ShardingStrategy.java +++ b/core/src/main/java/com/arangodb/entity/ShardingStrategy.java @@ -22,7 +22,7 @@ /** * @author Axel Becker - * https://www.arangodb.com/docs/stable/http/collection-creating.html + * API documentation */ public enum ShardingStrategy { @@ -30,7 +30,8 @@ public enum ShardingStrategy { ENTERPRISE_COMPAT("enterprise-compat"), ENTERPRISE_SMART_EDGE_COMPAT("enterprise-smart-edge-compat"), HASH("hash"), - ENTERPRISE_HASH_SMART_EDGE("enterprise-hash-smart-edge"); + ENTERPRISE_HASH_SMART_EDGE("enterprise-hash-smart-edge"), + ENTERPRISE_HEX_SMART_VERTEX("enterprise-hex-smart-vertex"); private final String internalName; diff --git a/src/main/java/com/arangodb/entity/StreamTransactionEntity.java b/core/src/main/java/com/arangodb/entity/StreamTransactionEntity.java similarity index 95% rename from src/main/java/com/arangodb/entity/StreamTransactionEntity.java rename to core/src/main/java/com/arangodb/entity/StreamTransactionEntity.java index b7fee3817..4dbafa475 100644 --- a/src/main/java/com/arangodb/entity/StreamTransactionEntity.java +++ b/core/src/main/java/com/arangodb/entity/StreamTransactionEntity.java @@ -26,7 +26,7 @@ * "https://www.arangodb.com/docs/stable/http/transaction-stream-transaction.html">API Documentation * @since ArangoDB 3.5.0 */ -public class StreamTransactionEntity implements Entity { +public final class StreamTransactionEntity { private String id; private StreamTransactionStatus status; diff --git a/src/main/java/com/arangodb/entity/StreamTransactionStatus.java b/core/src/main/java/com/arangodb/entity/StreamTransactionStatus.java similarity index 100% rename from src/main/java/com/arangodb/entity/StreamTransactionStatus.java rename to core/src/main/java/com/arangodb/entity/StreamTransactionStatus.java diff --git a/src/main/java/com/arangodb/entity/TransactionEntity.java b/core/src/main/java/com/arangodb/entity/TransactionEntity.java similarity index 86% rename from src/main/java/com/arangodb/entity/TransactionEntity.java rename to core/src/main/java/com/arangodb/entity/TransactionEntity.java index a700541f2..786a803b4 100644 --- a/src/main/java/com/arangodb/entity/TransactionEntity.java +++ b/core/src/main/java/com/arangodb/entity/TransactionEntity.java @@ -23,10 +23,11 @@ /** * @author Michele Rastelli * @see + * "https://www.arangodb.com/docs/stable/http/transaction-stream-transaction + * .html#list-currently-ongoing-transactions * @since ArangoDB 3.5.0 */ -public class TransactionEntity implements Entity { +public final class TransactionEntity { private String id; private StreamTransactionStatus state; @@ -35,7 +36,7 @@ public String getId() { return id; } - public StreamTransactionStatus getStatus() { + public StreamTransactionStatus getState() { return state; } diff --git a/src/main/java/com/arangodb/entity/UserEntity.java b/core/src/main/java/com/arangodb/entity/UserEntity.java similarity index 97% rename from src/main/java/com/arangodb/entity/UserEntity.java rename to core/src/main/java/com/arangodb/entity/UserEntity.java index fa082c5c7..244da2d55 100644 --- a/src/main/java/com/arangodb/entity/UserEntity.java +++ b/core/src/main/java/com/arangodb/entity/UserEntity.java @@ -26,7 +26,7 @@ * @author Mark Vollmary * @see API Documentation */ -public class UserEntity implements Entity { +public final class UserEntity { private String user; private Boolean active; diff --git a/src/main/java/com/arangodb/entity/VertexEntity.java b/core/src/main/java/com/arangodb/entity/VertexEntity.java similarity index 90% rename from src/main/java/com/arangodb/entity/VertexEntity.java rename to core/src/main/java/com/arangodb/entity/VertexEntity.java index 161ed9fd4..4dfb6a55a 100644 --- a/src/main/java/com/arangodb/entity/VertexEntity.java +++ b/core/src/main/java/com/arangodb/entity/VertexEntity.java @@ -1,32 +1,32 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public class VertexEntity extends DocumentEntity { - - public VertexEntity() { - super(); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +/** + * @author Mark Vollmary + */ +public final class VertexEntity extends DocumentEntity { + + public VertexEntity() { + super(); + } + +} diff --git a/src/main/java/com/arangodb/entity/VertexUpdateEntity.java b/core/src/main/java/com/arangodb/entity/VertexUpdateEntity.java similarity index 82% rename from src/main/java/com/arangodb/entity/VertexUpdateEntity.java rename to core/src/main/java/com/arangodb/entity/VertexUpdateEntity.java index 22d2d1078..ef19a4386 100644 --- a/src/main/java/com/arangodb/entity/VertexUpdateEntity.java +++ b/core/src/main/java/com/arangodb/entity/VertexUpdateEntity.java @@ -1,41 +1,41 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.arangodb.velocypack.annotations.SerializedName; - -/** - * @author Mark Vollmary - */ -public class VertexUpdateEntity extends DocumentEntity { - - @SerializedName("_oldRev") - private String oldRev; - - public VertexUpdateEntity() { - super(); - } - - public String getOldRev() { - return oldRev; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author Mark Vollmary + */ +public final class VertexUpdateEntity extends DocumentEntity { + + @JsonProperty("_oldRev") + private String oldRev; + + public VertexUpdateEntity() { + super(); + } + + public String getOldRev() { + return oldRev; + } + +} diff --git a/src/main/java/com/arangodb/entity/ViewEntity.java b/core/src/main/java/com/arangodb/entity/ViewEntity.java similarity index 96% rename from src/main/java/com/arangodb/entity/ViewEntity.java rename to core/src/main/java/com/arangodb/entity/ViewEntity.java index 07da45f88..e5eb28299 100644 --- a/src/main/java/com/arangodb/entity/ViewEntity.java +++ b/core/src/main/java/com/arangodb/entity/ViewEntity.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class ViewEntity implements Entity { +public class ViewEntity { private String id; private String name; diff --git a/src/main/java/com/arangodb/entity/ViewType.java b/core/src/main/java/com/arangodb/entity/ViewType.java similarity index 83% rename from src/main/java/com/arangodb/entity/ViewType.java rename to core/src/main/java/com/arangodb/entity/ViewType.java index 21c039906..063553cd5 100644 --- a/src/main/java/com/arangodb/entity/ViewType.java +++ b/core/src/main/java/com/arangodb/entity/ViewType.java @@ -20,11 +20,16 @@ package com.arangodb.entity; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * @author Mark Vollmary */ public enum ViewType { - ARANGO_SEARCH + @JsonProperty("arangosearch") + ARANGO_SEARCH, + @JsonProperty("search-alias") + SEARCH_ALIAS } diff --git a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java b/core/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java similarity index 71% rename from src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java rename to core/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java index 8fdf06509..c06d8945f 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/AnalyzerFeature.java @@ -22,7 +22,8 @@ /** * @author Michele Rastelli - * @see API Documentation + * @see + * API Documentation */ public enum AnalyzerFeature { @@ -37,8 +38,15 @@ public enum AnalyzerFeature { norm, /** - * sequentially increasing term position, required for PHRASE(). If present then the frequency feature is also required + * sequentially increasing term position, required for PHRASE(). If present then the frequency feature is also + * required. */ - position + position, + + /** + * enable search highlighting capabilities (Enterprise Edition only). If present, then the `position` and `frequency` features are also required. + * @since ArangoDB 3.10 + */ + offset } diff --git a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java b/core/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java similarity index 78% rename from src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java rename to core/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java index 7a5ea5918..acf38797d 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/AnalyzerType.java @@ -24,5 +24,20 @@ * @author Michele Rastelli */ public enum AnalyzerType { - identity, delimiter, stem, norm, ngram, text, pipeline, stopwords, aql, geojson, geopoint, segmentation, collation + identity, + delimiter, + stem, + norm, + ngram, + text, + pipeline, + stopwords, + aql, + geojson, + geopoint, + segmentation, + collation, + classification, + nearest_neighbors, + minhash } diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java b/core/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java rename to core/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchCompression.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java b/core/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java similarity index 82% rename from src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java rename to core/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java index 55c6d9afe..d2f8015e3 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java @@ -21,7 +21,8 @@ package com.arangodb.entity.arangosearch; import com.arangodb.entity.ViewEntity; -import com.arangodb.entity.ViewType; +import com.arangodb.internal.serde.InternalDeserializers; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.Collection; @@ -30,26 +31,16 @@ * @author Michele Rastelli * @see API Documentation */ -public class ArangoSearchPropertiesEntity extends ViewEntity { +public final class ArangoSearchPropertiesEntity extends ViewEntity { - private final ArangoSearchProperties properties; - - public ArangoSearchPropertiesEntity(final String id, final String name, final ViewType type, - final ArangoSearchProperties properties) { - super(id, name, type); - this.properties = properties; - } - - /** - * @return Wait at least this many milliseconds between committing index data changes and making them visible to - * queries (default: 60000, to disable use: 0). For the case where there are a lot of inserts/updates, a - * lower value, until commit, will cause the index not to account for them and memory usage would continue - * to grow. For the case where there are a few inserts/updates, a higher value will impact performance and - * waste disk space for each commit call without any added benefits. - */ - public Long getConsolidationIntervalMsec() { - return properties.getConsolidationIntervalMsec(); - } + private Long consolidationIntervalMsec; + private Long commitIntervalMsec; + private Long cleanupIntervalStep; + private ConsolidationPolicy consolidationPolicy; + private Collection primarySort; + private Collection links; + private ArangoSearchCompression primarySortCompression; + private Collection storedValues; /** * @return Wait at least this many milliseconds between committing view data store changes and making documents @@ -65,7 +56,18 @@ public Long getConsolidationIntervalMsec() { * continue to return a repeatable-read state. */ public Long getCommitIntervalMsec() { - return properties.getCommitIntervalMsec(); + return commitIntervalMsec; + } + + /** + * @return Wait at least this many milliseconds between committing index data changes and making them visible to + * queries (default: 60000, to disable use: 0). For the case where there are a lot of inserts/updates, a + * lower value, until commit, will cause the index not to account for them and memory usage would continue + * to grow. For the case where there are a few inserts/updates, a higher value will impact performance and + * waste disk space for each commit call without any added benefits. + */ + public Long getConsolidationIntervalMsec() { + return consolidationIntervalMsec; } /** @@ -76,25 +78,26 @@ public Long getCommitIntervalMsec() { * performance without any added benefits. */ public Long getCleanupIntervalStep() { - return properties.getCleanupIntervalStep(); + return cleanupIntervalStep; } public ConsolidationPolicy getConsolidationPolicy() { - return properties.getConsolidationPolicy(); + return consolidationPolicy; } /** * @return A list of linked collections */ + @JsonDeserialize(using = InternalDeserializers.CollectionLinksDeserializer.class) public Collection getLinks() { - return properties.getLinks(); + return links; } /** * @return A list of primary sort objects */ public Collection getPrimarySort() { - return properties.getPrimarySort(); + return primarySort; } /** @@ -103,7 +106,7 @@ public Collection getPrimarySort() { * @since ArangoDB 3.7 */ public ArangoSearchCompression getPrimarySortCompression() { - return properties.getPrimarySortCompression(); + return primarySortCompression; } /** @@ -113,7 +116,7 @@ public ArangoSearchCompression getPrimarySortCompression() { * @since ArangoDB 3.7 */ public Collection getStoredValues() { - return properties.getStoredValues(); + return storedValues; } } diff --git a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java b/core/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java similarity index 50% rename from src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java rename to core/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java index adf57d9da..c5901abcc 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/CollectionLink.java @@ -20,27 +20,35 @@ package com.arangodb.entity.arangosearch; -import java.util.ArrayList; +import com.arangodb.internal.serde.InternalDeserializers; +import com.arangodb.internal.serde.InternalSerializers; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + import java.util.Arrays; import java.util.Collection; /** * @author Mark Vollmary */ -public class CollectionLink { +public final class CollectionLink { private final String name; - private final Collection analyzers; + private Collection analyzers; private Boolean includeAllFields; private Boolean trackListPositions; private StoreValuesType storeValues; - private final Collection fields; + private Collection fields; + private Collection nested; + private Boolean inBackground; + private Boolean cache; private CollectionLink(final String name) { super(); this.name = name; - fields = new ArrayList<>(); - analyzers = new ArrayList<>(); } /** @@ -49,7 +57,8 @@ private CollectionLink(final String name) { * @param name Name of a collection * @return new instance of {@code CollectionLink} */ - public static CollectionLink on(final String name) { + @JsonCreator + public static CollectionLink on(@JsonProperty("name") final String name) { return new CollectionLink(name); } @@ -58,12 +67,13 @@ public static CollectionLink on(final String name) { * @return link */ public CollectionLink analyzers(final String... analyzers) { - this.analyzers.addAll(Arrays.asList(analyzers)); + this.analyzers = Arrays.asList(analyzers); return this; } /** - * @param includeAllFields The flag determines whether or not to index all fields on a particular level of depth (default: + * @param includeAllFields The flag determines whether or not to index all fields on a particular level of depth + * (default: * false). * @return link */ @@ -73,7 +83,8 @@ public CollectionLink includeAllFields(final Boolean includeAllFields) { } /** - * @param trackListPositions The flag determines whether or not values in a lists should be treated separate (default: false). + * @param trackListPositions The flag determines whether or not values in a lists should be treated separate + * (default: false). * @return link */ public CollectionLink trackListPositions(final Boolean trackListPositions) { @@ -82,7 +93,8 @@ public CollectionLink trackListPositions(final Boolean trackListPositions) { } /** - * @param storeValues How should the view track the attribute values, this setting allows for additional value retrieval + * @param storeValues How should the view track the attribute values, this setting allows for additional value + * retrieval * optimizations (default "none"). * @return link */ @@ -95,11 +107,49 @@ public CollectionLink storeValues(final StoreValuesType storeValues) { * @param fields A list of linked fields * @return link */ + @JsonDeserialize(using = InternalDeserializers.FieldLinksDeserializer.class) public CollectionLink fields(final FieldLink... fields) { - this.fields.addAll(Arrays.asList(fields)); + this.fields = Arrays.asList(fields); + return this; + } + + /** + * @param nested A list of nested fields + * @return link + * @since ArangoDB 3.10 + */ + @JsonDeserialize(using = InternalDeserializers.FieldLinksDeserializer.class) + public CollectionLink nested(final FieldLink... nested) { + this.nested = Arrays.asList(nested); + return this; + } + + /** + * @param inBackground If set to true, then no exclusive lock is used on the source collection during View index + * creation, so that it remains basically available. inBackground is an option that can be set + * when adding links. It does not get persisted as it is not a View property, but only a + * one-off option. (default: false) + * @return link + */ + public CollectionLink inBackground(final Boolean inBackground) { + this.inBackground = inBackground; return this; } + /** + * @param cache If you enable this option, then field normalization values are always cached in memory. This can + * improve the performance of scoring and ranking queries. Otherwise, these values are memory-mapped + * and it is up to the operating system to load them from disk into memory and to evict them from + * memory. + * @return link + * @since ArangoDB 3.9.5, Enterprise Edition only + */ + public CollectionLink cache(final Boolean cache) { + this.cache = cache; + return this; + } + + @JsonIgnore public String getName() { return name; } @@ -120,8 +170,22 @@ public StoreValuesType getStoreValues() { return storeValues; } + @JsonSerialize(using = InternalSerializers.FieldLinksSerializer.class) public Collection getFields() { return fields; } + @JsonSerialize(using = InternalSerializers.FieldLinksSerializer.class) + public Collection getNested() { + return nested; + } + + public Boolean getInBackground() { + return inBackground; + } + + public Boolean getCache() { + return cache; + } + } \ No newline at end of file diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java b/core/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java new file mode 100644 index 000000000..cfba95e74 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java @@ -0,0 +1,144 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch; + +import java.util.Objects; + +/** + * @author Mark Vollmary + */ +public final class ConsolidationPolicy { + + private ConsolidationType type; + private Double threshold; + private Long segmentsMin; + private Long segmentsMax; + private Long segmentsBytesMax; + private Long segmentsBytesFloor; + private Long minScore; + + public static ConsolidationPolicy of(final ConsolidationType type) { + return new ConsolidationPolicy().type(type); + } + + public ConsolidationPolicy type(final ConsolidationType type) { + this.type = type; + return this; + } + + /** + * @param threshold value in the range [0.0, 1.0] + * @return this + */ + public ConsolidationPolicy threshold(final Double threshold) { + this.threshold = threshold; + return this; + } + + public ConsolidationType getType() { + return type; + } + + public Double getThreshold() { + return threshold; + } + + public Long getSegmentsMin() { + return segmentsMin; + } + + /** + * @param segmentsMin The minimum number of segments that will be evaluated as candidates for consolidation. + * (default: 1) + * @return this + */ + public ConsolidationPolicy segmentsMin(final Long segmentsMin) { + this.segmentsMin = segmentsMin; + return this; + } + + public Long getSegmentsMax() { + return segmentsMax; + } + + /** + * @param segmentsMax The maximum number of segments that will be evaluated as candidates for consolidation. + * (default: 10) + * @return this + */ + public ConsolidationPolicy segmentsMax(final Long segmentsMax) { + this.segmentsMax = segmentsMax; + return this; + } + + public Long getSegmentsBytesMax() { + return segmentsBytesMax; + } + + /** + * @param segmentsBytesMax Maximum allowed size of all consolidated segments in bytes. (default: 5368709120) + * @return this + */ + public ConsolidationPolicy segmentsBytesMax(final Long segmentsBytesMax) { + this.segmentsBytesMax = segmentsBytesMax; + return this; + } + + public Long getSegmentsBytesFloor() { + return segmentsBytesFloor; + } + + /** + * @param segmentsBytesFloor Defines the value (in bytes) to treat all smaller segments as equal for consolidation + * selection. (default: 2097152) + * @return this + */ + public ConsolidationPolicy segmentsBytesFloor(final Long segmentsBytesFloor) { + this.segmentsBytesFloor = segmentsBytesFloor; + return this; + } + + public Long getMinScore() { + return minScore; + } + + /** + * @param minScore Filter out consolidation candidates with a score less than this. (default: 0) + * @return this + */ + public ConsolidationPolicy minScore(final Long minScore) { + this.minScore = minScore; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ConsolidationPolicy that = (ConsolidationPolicy) o; + return type == that.type && Objects.equals(threshold, that.threshold) && Objects.equals(segmentsMin, that.segmentsMin) && Objects.equals(segmentsMax, that.segmentsMax) && Objects.equals(segmentsBytesMax, that.segmentsBytesMax) && Objects.equals(segmentsBytesFloor, that.segmentsBytesFloor) && Objects.equals(minScore, that.minScore); + } + + @Override + public int hashCode() { + return Objects.hash(type, threshold, segmentsMin, segmentsMax, segmentsBytesMax, segmentsBytesFloor, minScore); + } +} diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java b/core/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java new file mode 100644 index 000000000..1eb3b1ebc --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java @@ -0,0 +1,18 @@ +package com.arangodb.entity.arangosearch; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public enum ConsolidationType { + + /** + * @deprecated The “bytes_accum” policy type is deprecated and remains in ArangoSearch for backwards compatibility + * with the older versions. Please make sure to always use the “tier” policy instead. + */ + @Deprecated + @JsonProperty("bytes_accum") + BYTES_ACCUM, + + @JsonProperty("tier") + TIER + +} \ No newline at end of file diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java b/core/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java new file mode 100644 index 000000000..ab71321b3 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java @@ -0,0 +1,149 @@ +package com.arangodb.entity.arangosearch; + +import com.arangodb.internal.serde.InternalDeserializers; +import com.arangodb.internal.serde.InternalSerializers; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.util.Arrays; +import java.util.Collection; + +public final class FieldLink { + + private final String name; + private Collection analyzers; + private Boolean includeAllFields; + private Boolean trackListPositions; + private StoreValuesType storeValues; + private Collection fields; + private Collection nested; + private Boolean inBackground; + + private FieldLink(final String name) { + super(); + this.name = name; + } + + /** + * Creates an instance of {@code FieldLink} on the given field name + * + * @param name Name of a field + * @return new instance of {@code FieldLink} + */ + @JsonCreator + public static FieldLink on(@JsonProperty("name") final String name) { + return new FieldLink(name); + } + + /** + * @param analyzers The list of analyzers to be used for indexing of string values (default: ["identity"]). + * @return link + */ + public FieldLink analyzers(final String... analyzers) { + this.analyzers = Arrays.asList(analyzers); + return this; + } + + /** + * @param includeAllFields The flag determines whether or not to index all fields on a particular level of depth + * (default: + * false). + * @return link + */ + public FieldLink includeAllFields(final Boolean includeAllFields) { + this.includeAllFields = includeAllFields; + return this; + } + + /** + * @param trackListPositions The flag determines whether or not values in a lists should be treated separate + * (default: false). + * @return link + */ + public FieldLink trackListPositions(final Boolean trackListPositions) { + this.trackListPositions = trackListPositions; + return this; + } + + /** + * @param storeValues How should the view track the attribute values, this setting allows for additional value + * retrieval + * optimizations (default "none"). + * @return link + */ + public FieldLink storeValues(final StoreValuesType storeValues) { + this.storeValues = storeValues; + return this; + } + + /** + * @param fields A list of linked fields + * @return link + */ + @JsonDeserialize(using = InternalDeserializers.FieldLinksDeserializer.class) + public FieldLink fields(final FieldLink... fields) { + this.fields = Arrays.asList(fields); + return this; + } + + /** + * @param nested A list of nested fields + * @return link + * @since ArangoDB 3.10 + */ + @JsonDeserialize(using = InternalDeserializers.FieldLinksDeserializer.class) + public FieldLink nested(final FieldLink... nested) { + this.nested = Arrays.asList(nested); + return this; + } + + /** + * @param inBackground If set to true, then no exclusive lock is used on the source collection during View index + * creation, so that it remains basically available. inBackground is an option that can be set + * when adding links. It does not get persisted as it is not a View property, but only a + * one-off option. (default: false) + * @return link + */ + public FieldLink inBackground(final Boolean inBackground) { + this.inBackground = inBackground; + return this; + } + + @JsonIgnore + public String getName() { + return name; + } + + public Collection getAnalyzers() { + return analyzers; + } + + public Boolean getIncludeAllFields() { + return includeAllFields; + } + + public Boolean getTrackListPositions() { + return trackListPositions; + } + + public StoreValuesType getStoreValues() { + return storeValues; + } + + @JsonSerialize(using = InternalSerializers.FieldLinksSerializer.class) + public Collection getFields() { + return fields; + } + + @JsonSerialize(using = InternalSerializers.FieldLinksSerializer.class) + public Collection getNested() { + return nested; + } + + public Boolean getInBackground() { + return inBackground; + } +} \ No newline at end of file diff --git a/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java b/core/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java similarity index 97% rename from src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java rename to core/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java index 32c3a34a3..ab0d7c872 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/PrimarySort.java @@ -23,7 +23,7 @@ /** * @author Heiko Kernbach */ -public class PrimarySort { +public final class PrimarySort { private final String fieldName; private Boolean ascending; diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java b/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java new file mode 100644 index 000000000..1d18076f0 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasIndex.java @@ -0,0 +1,53 @@ +package com.arangodb.entity.arangosearch; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author Michele Rastelli + * @since ArabgoDB 3.10 + */ +public final class SearchAliasIndex { + private final String collection; + private final String index; + private final OperationType operation; + + /** + * @param collection The name of a collection. + * @param index The name of an inverted index of the collection. + */ + public SearchAliasIndex(String collection, String index) { + this(collection, index, null); + } + + /** + * @param collection The name of a collection. + * @param index The name of an inverted index of the collection. + * @param operation Whether to add or remove the index to the stored indexes property of the View. (default "add") + */ + @JsonCreator + public SearchAliasIndex( + @JsonProperty("collection") String collection, + @JsonProperty("index") String index, + @JsonProperty("operation") OperationType operation) { + this.collection = collection; + this.index = index; + this.operation = operation; + } + + public String getCollection() { + return collection; + } + + public String getIndex() { + return index; + } + + public OperationType getOperation() { + return operation; + } + + public enum OperationType { + add, del + } +} diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java b/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java new file mode 100644 index 000000000..37d2a1587 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/arangosearch/SearchAliasPropertiesEntity.java @@ -0,0 +1,43 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch; + +import com.arangodb.entity.ViewEntity; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * @author Michele Rastelli + * @see API Documentation + */ +public final class SearchAliasPropertiesEntity extends ViewEntity { + + private final Collection indexes = new ArrayList<>(); + + /** + * @return A list of inverted indexes to add to the View. + */ + public Collection getIndexes() { + return indexes; + } + +} diff --git a/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java b/core/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java similarity index 90% rename from src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java rename to core/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java index 3630e903a..23577a4f8 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/StoreValuesType.java @@ -20,6 +20,8 @@ package com.arangodb.entity.arangosearch; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * @author Mark Vollmary */ @@ -28,11 +30,13 @@ public enum StoreValuesType { /** * Do not track values by the view */ + @JsonProperty("none") NONE, /** * Track only value presence, to allow use of the EXISTS() function. */ + @JsonProperty("id") ID } diff --git a/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java b/core/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java similarity index 52% rename from src/main/java/com/arangodb/entity/arangosearch/StoredValue.java rename to core/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java index 5d3c2bd36..66c261f77 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/StoredValue.java @@ -21,41 +21,67 @@ package com.arangodb.entity.arangosearch; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import java.util.List; +import java.util.Objects; /** * @author Michele Rastelli * @see API Documentation * @since ArangoDB 3.7 */ -public class StoredValue { +public final class StoredValue { private final List fields; private final ArangoSearchCompression compression; + private final Boolean cache; - public StoredValue(List fields, ArangoSearchCompression compression) { + /** + * @param fields A list of attribute paths. The . character denotes sub-attributes. + * @param compression Defines how to compress the attribute values. + * @param cache Whether to cache stored values in memory. (Since ArangoDB 3.9.5, Enterprise Edition only) + */ + @JsonCreator + public StoredValue(@JsonProperty("fields") List fields, + @JsonProperty("compression") ArangoSearchCompression compression, + @JsonProperty("cache") Boolean cache) { this.fields = fields; this.compression = compression; + this.cache = cache; + } + + public StoredValue(List fields, ArangoSearchCompression compression) { + this(fields, compression, null); } public StoredValue(List fields) { this(fields, null); } - /** - * @return an array of strings with one or more document attribute paths. The specified attributes are placed into a - * single column of the index. A column with all fields that are involved in common search queries is ideal for - * performance. The column should not include too many unneeded fields however. - */ public List getFields() { return fields; } - /** - * @return defines the compression type used for the internal column-store - */ public ArangoSearchCompression getCompression() { return compression; } + public Boolean getCache() { + return cache; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + StoredValue that = (StoredValue) o; + return Objects.equals(fields, that.fields) && compression == that.compression && Objects.equals(cache, that.cache); + } + + @Override + public int hashCode() { + return Objects.hash(fields, compression, cache); + } } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java similarity index 97% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java index 2677d0de4..428308712 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzer.java @@ -32,13 +32,13 @@ * @see API Documentation * @since ArangoDB 3.8 */ -public class AQLAnalyzer extends SearchAnalyzer { +public final class AQLAnalyzer extends SearchAnalyzer { + private AQLAnalyzerProperties properties; + public AQLAnalyzer() { setType(AnalyzerType.aql); } - private AQLAnalyzerProperties properties; - public AQLAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java similarity index 89% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java index 6118d2c3b..acb3c2a29 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/AQLAnalyzerProperties.java @@ -27,7 +27,7 @@ /** * @author Michele Rastelli */ -public class AQLAnalyzerProperties { +public final class AQLAnalyzerProperties { private String queryString; private Boolean collapsePositions; @@ -37,10 +37,6 @@ public class AQLAnalyzerProperties { private ReturnType returnType; - public enum ReturnType { - string, number, bool - } - /** * @return AQL query to be executed */ @@ -76,7 +72,8 @@ public void setCollapsePositions(Boolean collapsePositions) { * true (default): treat null like an empty string * *
  • - * false: discard nulls from View index. Can be used for index filtering (i.e. make your query return null for unwanted data). Note that empty results are always discarded. + * false: discard nulls from View index. Can be used for index filtering (i.e. make your query return null for + * unwanted data). Note that empty results are always discarded. *
  • * */ @@ -129,7 +126,9 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AQLAnalyzerProperties that = (AQLAnalyzerProperties) o; - return Objects.equals(queryString, that.queryString) && Objects.equals(collapsePositions, that.collapsePositions) && Objects.equals(keepNull, that.keepNull) && Objects.equals(batchSize, that.batchSize) && Objects.equals(memoryLimit, that.memoryLimit) && returnType == that.returnType; + return Objects.equals(queryString, that.queryString) && Objects.equals(collapsePositions, + that.collapsePositions) && Objects.equals(keepNull, that.keepNull) && Objects.equals(batchSize, + that.batchSize) && Objects.equals(memoryLimit, that.memoryLimit) && returnType == that.returnType; } @Override @@ -137,4 +136,8 @@ public int hashCode() { return Objects.hash(queryString, collapsePositions, keepNull, batchSize, memoryLimit, returnType); } + public enum ReturnType { + string, number, bool + } + } diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java new file mode 100644 index 000000000..62290126b --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzer.java @@ -0,0 +1,64 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch.analyzer; + + +import com.arangodb.entity.arangosearch.AnalyzerType; + +import java.util.Objects; + +/** + * An Analyzer capable of classifying tokens in the input text. It applies a user-provided supervised fastText word + * embedding model to classify the input text. It is able to classify individual tokens as well as entire inputs. + * + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public final class ClassificationAnalyzer extends SearchAnalyzer { + public ClassificationAnalyzer() { + setType(AnalyzerType.classification); + } + + private ClassificationAnalyzerProperties properties; + + public ClassificationAnalyzerProperties getProperties() { + return properties; + } + + public void setProperties(ClassificationAnalyzerProperties properties) { + this.properties = properties; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + ClassificationAnalyzer that = (ClassificationAnalyzer) o; + return Objects.equals(properties, that.properties); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), properties); + } +} diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java new file mode 100644 index 000000000..00ee39c88 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/ClassificationAnalyzerProperties.java @@ -0,0 +1,78 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch.analyzer; + + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +/** + * @author Michele Rastelli + * @since ArangoDB 3.10 + */ +public final class ClassificationAnalyzerProperties { + + @JsonProperty("model_location") + private String modelLocation; + + @JsonProperty("top_k") + private Integer topK; + + private Double threshold; + + public String getModelLocation() { + return modelLocation; + } + + public void setModelLocation(String modelLocation) { + this.modelLocation = modelLocation; + } + + public Integer getTopK() { + return topK; + } + + public void setTopK(Integer topK) { + this.topK = topK; + } + + public Double getThreshold() { + return threshold; + } + + public void setThreshold(Double threshold) { + this.threshold = threshold; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ClassificationAnalyzerProperties that = (ClassificationAnalyzerProperties) o; + return Objects.equals(modelLocation, that.modelLocation) && Objects.equals(topK, that.topK) && Objects.equals(threshold, that.threshold); + } + + @Override + public int hashCode() { + return Objects.hash(modelLocation, topK, threshold); + } +} diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java similarity index 96% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java index e07d820a3..559c22def 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzer.java @@ -33,13 +33,13 @@ * @see API Documentation * @since ArangoDB 3.9 */ -public class CollationAnalyzer extends SearchAnalyzer { +public final class CollationAnalyzer extends SearchAnalyzer { + private CollationAnalyzerProperties properties; + public CollationAnalyzer() { setType(AnalyzerType.collation); } - private CollationAnalyzerProperties properties; - public CollationAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java similarity index 90% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java index d056dbaa2..0e21c4029 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/CollationAnalyzerProperties.java @@ -27,7 +27,7 @@ * @author Michele Rastelli * @since ArangoDB 3.9 */ -public class CollationAnalyzerProperties { +public final class CollationAnalyzerProperties { private String locale; @@ -35,7 +35,8 @@ public class CollationAnalyzerProperties { * @return a locale in the format `language[_COUNTRY][.encoding][@variant]` (square brackets denote optional parts), * e.g. `de.utf-8` or `en_US.utf-8`. Only UTF-8 encoding is meaningful in ArangoDB. * The locale is forwarded to ICU without checks. An invalid locale does not prevent the creation of the Analyzer. - * @see Supported Languages + * @see + * Supported Languages */ public String getLocale() { return locale; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java similarity index 93% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java index 764096619..ccfcee9de 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzer.java @@ -26,18 +26,19 @@ import java.util.Objects; /** - * An Analyzer capable of breaking up delimited text into tokens as per RFC 4180 (without starting new records on newlines). + * An Analyzer capable of breaking up delimited text into tokens as per RFC 4180 (without starting new records on + * newlines). * * @author Michele Rastelli * @see API Documentation */ -public class DelimiterAnalyzer extends SearchAnalyzer { +public final class DelimiterAnalyzer extends SearchAnalyzer { + private DelimiterAnalyzerProperties properties; + public DelimiterAnalyzer() { setType(AnalyzerType.delimiter); } - private DelimiterAnalyzerProperties properties; - public DelimiterAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java similarity index 96% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java index c67f05428..21c8ef741 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/DelimiterAnalyzerProperties.java @@ -26,7 +26,7 @@ /** * @author Michele Rastelli */ -public class DelimiterAnalyzerProperties { +public final class DelimiterAnalyzerProperties { private String delimiter; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java similarity index 98% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java index 018fc2eac..35c4536da 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/EdgeNgram.java @@ -26,7 +26,7 @@ /** * @author Michele Rastelli */ -public class EdgeNgram { +public final class EdgeNgram { private long min; private long max; private boolean preserveOriginal; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java similarity index 98% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java index 5b48d1c69..a6a2f6762 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoAnalyzerOptions.java @@ -27,7 +27,7 @@ /** * @author Michele Rastelli */ -public class GeoAnalyzerOptions { +public final class GeoAnalyzerOptions { private Integer maxCells; private Integer minLevel; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java similarity index 96% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java index a5005b676..d6e48662e 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzer.java @@ -33,13 +33,13 @@ * @see API Documentation * @since ArangoDB 3.8 */ -public class GeoJSONAnalyzer extends SearchAnalyzer { +public final class GeoJSONAnalyzer extends SearchAnalyzer { + private GeoJSONAnalyzerProperties properties; + public GeoJSONAnalyzer() { setType(AnalyzerType.geojson); } - private GeoJSONAnalyzerProperties properties; - public GeoJSONAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java similarity index 97% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java index 7c2289666..9e43c6d3c 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoJSONAnalyzerProperties.java @@ -26,25 +26,7 @@ /** * @author Michele Rastelli */ -public class GeoJSONAnalyzerProperties { - - public enum GeoJSONAnalyzerType { - - /** - * (default): index all GeoJSON geometry types (Point, Polygon etc.) - */ - shape, - - /** - * compute and only index the centroid of the input geometry - */ - centroid, - - /** - * only index GeoJSON objects of type Point, ignore all other geometry types - */ - point - } +public final class GeoJSONAnalyzerProperties { private GeoJSONAnalyzerType type; private GeoAnalyzerOptions options; @@ -81,4 +63,22 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(type, options); } + + public enum GeoJSONAnalyzerType { + + /** + * (default): index all GeoJSON geometry types (Point, Polygon etc.) + */ + shape, + + /** + * compute and only index the centroid of the input geometry + */ + centroid, + + /** + * only index GeoJSON objects of type Point, ignore all other geometry types + */ + point + } } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java similarity index 96% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java index e4ead1855..b88694c70 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzer.java @@ -33,13 +33,13 @@ * @see API Documentation * @since ArangoDB 3.8 */ -public class GeoPointAnalyzer extends SearchAnalyzer { +public final class GeoPointAnalyzer extends SearchAnalyzer { + private GeoPointAnalyzerProperties properties; + public GeoPointAnalyzer() { setType(AnalyzerType.geopoint); } - private GeoPointAnalyzerProperties properties; - public GeoPointAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java similarity index 98% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java index f90953421..a0c148216 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/GeoPointAnalyzerProperties.java @@ -27,7 +27,7 @@ /** * @author Michele Rastelli */ -public class GeoPointAnalyzerProperties { +public final class GeoPointAnalyzerProperties { private String[] latitude; private String[] longitude; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java similarity index 83% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java index ad096e669..7cf1b12e7 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/IdentityAnalyzer.java @@ -29,18 +29,8 @@ * @author Michele Rastelli * @see API Documentation */ -public class IdentityAnalyzer extends SearchAnalyzer { +public final class IdentityAnalyzer extends SearchAnalyzer { public IdentityAnalyzer() { setType(AnalyzerType.identity); } - - @Override - public boolean equals(Object o) { - return super.equals(o); - } - - @Override - public int hashCode() { - return super.hashCode(); - } } diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java new file mode 100644 index 000000000..8afbde752 --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzer.java @@ -0,0 +1,64 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch.analyzer; + + +import com.arangodb.entity.arangosearch.AnalyzerType; + +import java.util.Objects; + +/** + * An Analyzer that computes so called MinHash signatures using a locality-sensitive hash function. It applies an + * Analyzer of your choice before the hashing, for example, to break up text into words. + * + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public final class MinHashAnalyzer extends SearchAnalyzer { + public MinHashAnalyzer() { + setType(AnalyzerType.minhash); + } + + private MinHashAnalyzerProperties properties; + + public MinHashAnalyzerProperties getProperties() { + return properties; + } + + public void setProperties(MinHashAnalyzerProperties properties) { + this.properties = properties; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + MinHashAnalyzer that = (MinHashAnalyzer) o; + return Objects.equals(properties, that.properties); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), properties); + } +} diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java new file mode 100644 index 000000000..1c37c1c0f --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/MinHashAnalyzerProperties.java @@ -0,0 +1,63 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch.analyzer; + + +import java.util.Objects; + +/** + * @author Michele Rastelli + * @since ArangoDB 3.10 + */ +public final class MinHashAnalyzerProperties { + + private SearchAnalyzer analyzer; + private Integer numHashes; + + public SearchAnalyzer getAnalyzer() { + return analyzer; + } + + public void setAnalyzer(SearchAnalyzer analyzer) { + this.analyzer = analyzer; + } + + public Integer getNumHashes() { + return numHashes; + } + + public void setNumHashes(Integer numHashes) { + this.numHashes = numHashes; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MinHashAnalyzerProperties that = (MinHashAnalyzerProperties) o; + return Objects.equals(analyzer, that.analyzer) && Objects.equals(numHashes, that.numHashes); + } + + @Override + public int hashCode() { + return Objects.hash(analyzer, numHashes); + } +} diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java similarity index 97% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java index 7e76429fd..43cb3e23d 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzer.java @@ -36,13 +36,13 @@ * @author Michele Rastelli * @see API Documentation */ -public class NGramAnalyzer extends SearchAnalyzer { +public final class NGramAnalyzer extends SearchAnalyzer { + private NGramAnalyzerProperties properties; + public NGramAnalyzer() { setType(AnalyzerType.ngram); } - private NGramAnalyzerProperties properties; - public NGramAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java similarity index 97% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java index 534c38916..53d51672d 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NGramAnalyzerProperties.java @@ -34,7 +34,7 @@ * @author Michele Rastelli * @see API Documentation */ -public class NGramAnalyzerProperties { +public final class NGramAnalyzerProperties { private long min; private long max; @@ -73,7 +73,7 @@ public void setMax(long max) { /** * @return true to include the original value as well - * false to produce the n-grams based on min and max only + * false to produce the n-grams based on min and max only */ public boolean isPreserveOriginal() { return preserveOriginal; diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java new file mode 100644 index 000000000..5bf97df0f --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzer.java @@ -0,0 +1,66 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch.analyzer; + + +import com.arangodb.entity.arangosearch.AnalyzerType; + +import java.util.Objects; + +/** + * An Analyzer capable of finding nearest neighbors of tokens in the input. It applies a user-provided supervised + * fastText word embedding model to retrieve nearest neighbor tokens in the text. It is able to find neighbors of + * individual tokens as well as entire input strings. For entire input strings, the Analyzer will return nearest + * neighbors for each token within the input string. + * + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public final class NearestNeighborsAnalyzer extends SearchAnalyzer { + public NearestNeighborsAnalyzer() { + setType(AnalyzerType.nearest_neighbors); + } + + private NearestNeighborsAnalyzerProperties properties; + + public NearestNeighborsAnalyzerProperties getProperties() { + return properties; + } + + public void setProperties(NearestNeighborsAnalyzerProperties properties) { + this.properties = properties; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + NearestNeighborsAnalyzer that = (NearestNeighborsAnalyzer) o; + return Objects.equals(properties, that.properties); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), properties); + } +} diff --git a/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java new file mode 100644 index 000000000..25f31ce7a --- /dev/null +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NearestNeighborsAnalyzerProperties.java @@ -0,0 +1,69 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.entity.arangosearch.analyzer; + + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +/** + * @author Michele Rastelli + * @since ArangoDB 3.10 + */ +public final class NearestNeighborsAnalyzerProperties { + + @JsonProperty("model_location") + private String modelLocation; + + @JsonProperty("top_k") + private Integer topK; + + + public String getModelLocation() { + return modelLocation; + } + + public void setModelLocation(String modelLocation) { + this.modelLocation = modelLocation; + } + + public Integer getTopK() { + return topK; + } + + public void setTopK(Integer topK) { + this.topK = topK; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + NearestNeighborsAnalyzerProperties that = (NearestNeighborsAnalyzerProperties) o; + return Objects.equals(modelLocation, that.modelLocation) && Objects.equals(topK, that.topK); + } + + @Override + public int hashCode() { + return Objects.hash(modelLocation, topK); + } +} diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java similarity index 96% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java index 4673ccb1b..1073204c2 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzer.java @@ -31,13 +31,13 @@ * @author Michele Rastelli * @see API Documentation */ -public class NormAnalyzer extends SearchAnalyzer { +public final class NormAnalyzer extends SearchAnalyzer { + private NormAnalyzerProperties properties; + public NormAnalyzer() { setType(AnalyzerType.norm); } - private NormAnalyzerProperties properties; - public NormAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java similarity index 86% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java index cb1bcfbb8..5fcfa23ca 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/NormAnalyzerProperties.java @@ -21,26 +21,27 @@ package com.arangodb.entity.arangosearch.analyzer; -import com.arangodb.velocypack.annotations.SerializedName; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; /** * @author Michele Rastelli */ -public class NormAnalyzerProperties { +public final class NormAnalyzerProperties { private String locale; private boolean accent; - @SerializedName("case") + @JsonProperty("case") private SearchAnalyzerCase analyzerCase; /** * @return a locale in the format `language[_COUNTRY][.encoding][@variant]` (square brackets denote optional parts), * e.g. `de.utf-8` or `en_US.utf-8`. Only UTF-8 encoding is meaningful in ArangoDB. - * @see Supported Languages + * @see + * Supported Languages */ public String getLocale() { return locale; @@ -52,7 +53,7 @@ public void setLocale(String locale) { /** * @return true to preserve accented characters (default) - * false to convert accented characters to their base characters + * false to convert accented characters to their base characters */ public boolean isAccent() { return accent; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java similarity index 94% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java index 6616d3845..d61b6cda8 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzer.java @@ -29,21 +29,23 @@ * An Analyzer capable of chaining effects of multiple Analyzers into one. The pipeline is a list of Analyzers, where * the output of an Analyzer is passed to the next for further processing. *

    - * LIMITATIONS: Analyzers of types {@link GeoPointAnalyzer} and {@link GeoJSONAnalyzer} cannot be used in pipelines and + * LIMITATIONS: Analyzers of types {@link GeoPointAnalyzer} and {@link GeoJSONAnalyzer} cannot be used in + * pipelines and * will make the creation fail. *

    + * * @author Michele Rastelli * @see API Documentation * @since ArangoDB 3.8 */ -public class PipelineAnalyzer extends SearchAnalyzer { +public final class PipelineAnalyzer extends SearchAnalyzer { + + private PipelineAnalyzerProperties properties; public PipelineAnalyzer() { setType(AnalyzerType.pipeline); } - private PipelineAnalyzerProperties properties; - public PipelineAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java similarity index 97% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java index 5cc686d9f..bdcf4a91d 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/PipelineAnalyzerProperties.java @@ -28,7 +28,7 @@ /** * @author Michele Rastelli */ -public class PipelineAnalyzerProperties { +public final class PipelineAnalyzerProperties { private List pipeline = new LinkedList<>(); /** diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java similarity index 58% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java index 2155a39a8..6d10f8c69 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzer.java @@ -21,9 +21,11 @@ package com.arangodb.entity.arangosearch.analyzer; -import com.arangodb.entity.Entity; import com.arangodb.entity.arangosearch.AnalyzerFeature; import com.arangodb.entity.arangosearch.AnalyzerType; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import java.util.Collection; import java.util.HashSet; @@ -33,7 +35,26 @@ /** * @author Michele Rastelli */ -public abstract class SearchAnalyzer implements Entity { +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type") +@JsonSubTypes({ + @JsonSubTypes.Type(name = "identity", value = IdentityAnalyzer.class), + @JsonSubTypes.Type(name = "delimiter", value = DelimiterAnalyzer.class), + @JsonSubTypes.Type(name = "stem", value = StemAnalyzer.class), + @JsonSubTypes.Type(name = "norm", value = NormAnalyzer.class), + @JsonSubTypes.Type(name = "ngram", value = NGramAnalyzer.class), + @JsonSubTypes.Type(name = "text", value = TextAnalyzer.class), + @JsonSubTypes.Type(name = "pipeline", value = PipelineAnalyzer.class), + @JsonSubTypes.Type(name = "stopwords", value = StopwordsAnalyzer.class), + @JsonSubTypes.Type(name = "aql", value = AQLAnalyzer.class), + @JsonSubTypes.Type(name = "geojson", value = GeoJSONAnalyzer.class), + @JsonSubTypes.Type(name = "geopoint", value = GeoPointAnalyzer.class), + @JsonSubTypes.Type(name = "segmentation", value = SegmentationAnalyzer.class), + @JsonSubTypes.Type(name = "collation", value = CollationAnalyzer.class), + @JsonSubTypes.Type(name = "classification", value = ClassificationAnalyzer.class), + @JsonSubTypes.Type(name = "nearest_neighbors", value = NearestNeighborsAnalyzer.class), + @JsonSubTypes.Type(name = "minhash", value = MinHashAnalyzer.class) +}) +public abstract class SearchAnalyzer { private String name; private AnalyzerType type; private Collection features; @@ -52,6 +73,7 @@ public void setName(String name) { /** * @return The Analyzer type. */ + @JsonIgnore public AnalyzerType getType() { return type; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SearchAnalyzerCase.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java similarity index 96% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java index 70ce2f4cf..9a218a4af 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzer.java @@ -35,13 +35,13 @@ * @see API Documentation * @since ArangoDB 3.9 */ -public class SegmentationAnalyzer extends SearchAnalyzer { +public final class SegmentationAnalyzer extends SearchAnalyzer { + private SegmentationAnalyzerProperties properties; + public SegmentationAnalyzer() { setType(AnalyzerType.segmentation); } - private SegmentationAnalyzerProperties properties; - public SegmentationAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java similarity index 92% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java index 221cda81e..f674d6e34 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/SegmentationAnalyzerProperties.java @@ -21,7 +21,7 @@ package com.arangodb.entity.arangosearch.analyzer; -import com.arangodb.velocypack.annotations.SerializedName; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -29,12 +29,12 @@ * @author Michele Rastelli * @since ArangoDB 3.9 */ -public class SegmentationAnalyzerProperties { +public final class SegmentationAnalyzerProperties { - @SerializedName("break") + @JsonProperty("break") private BreakMode breakMode; - @SerializedName("case") + @JsonProperty("case") private SearchAnalyzerCase analyzerCase; public BreakMode getBreakMode() { @@ -59,10 +59,6 @@ public void setAnalyzerCase(SearchAnalyzerCase analyzerCase) { this.analyzerCase = analyzerCase; } - public enum BreakMode { - all, alpha, graphic - } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -75,4 +71,8 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(breakMode, analyzerCase); } + + public enum BreakMode { + all, alpha, graphic + } } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java similarity index 96% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java index 6e3166c64..bc48869c2 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzer.java @@ -31,13 +31,13 @@ * @author Michele Rastelli * @see API Documentation */ -public class StemAnalyzer extends SearchAnalyzer { +public final class StemAnalyzer extends SearchAnalyzer { + private StemAnalyzerProperties properties; + public StemAnalyzer() { setType(AnalyzerType.stem); } - private StemAnalyzerProperties properties; - public StemAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java similarity index 89% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java index b58634f6a..9057c3c21 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StemAnalyzerProperties.java @@ -26,14 +26,15 @@ /** * @author Michele Rastelli */ -public class StemAnalyzerProperties { +public final class StemAnalyzerProperties { private String locale; /** * @return a locale in the format `language[_COUNTRY][.encoding][@variant]` (square brackets denote optional parts), * e.g. `de.utf-8` or `en_US.utf-8`. Only UTF-8 encoding is meaningful in ArangoDB. - * @see Supported Languages + * @see + * Supported Languages */ public String getLocale() { return locale; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java similarity index 96% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java index 264b48d54..34c31617c 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzer.java @@ -32,13 +32,13 @@ * @see API Documentation * @since ArangoDB 3.8 */ -public class StopwordsAnalyzer extends SearchAnalyzer { +public final class StopwordsAnalyzer extends SearchAnalyzer { + private StopwordsAnalyzerProperties properties; + public StopwordsAnalyzer() { setType(AnalyzerType.stopwords); } - private StopwordsAnalyzerProperties properties; - public StopwordsAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java similarity index 93% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java index a82374b31..daa3d4e04 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StopwordsAnalyzerProperties.java @@ -21,6 +21,8 @@ package com.arangodb.entity.arangosearch.analyzer; +import com.fasterxml.jackson.annotation.JsonIgnore; + import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -29,7 +31,15 @@ /** * @author Michele Rastelli */ -public class StopwordsAnalyzerProperties { +public final class StopwordsAnalyzerProperties { + + private final List stopwords; + private final boolean hex; + + public StopwordsAnalyzerProperties() { + stopwords = new ArrayList<>(); + hex = true; + } private static String stringToHex(String str) { final StringBuilder hex = new StringBuilder(); @@ -49,26 +59,14 @@ private static String hexToString(String hex) { return result.toString(); } - public StopwordsAnalyzerProperties() { - stopwords = new ArrayList<>(); - hex = true; - } - - private final List stopwords; - private final boolean hex; - - /** - * @return list of hex-encoded strings that describe the tokens to be discarded. - * @deprecated use {@link #getStopwordsAsHexList()} instead - */ - @Deprecated public List getStopwords() { - return getStopwordsAsHexList(); + return stopwords; } /** * @return list of verbatim strings that describe the tokens to be discarded. */ + @JsonIgnore public List getStopwordsAsStringList() { if (hex) { return stopwords.stream() @@ -82,6 +80,7 @@ public List getStopwordsAsStringList() { /** * @return list of hex-encoded strings that describe the tokens to be discarded. */ + @JsonIgnore public List getStopwordsAsHexList() { if (hex) { return stopwords; diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java similarity index 100% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/StreamType.java diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java similarity index 97% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java index edc70b858..13f1d2112 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzer.java @@ -32,13 +32,13 @@ * @author Michele Rastelli * @see API Documentation */ -public class TextAnalyzer extends SearchAnalyzer { +public final class TextAnalyzer extends SearchAnalyzer { + private TextAnalyzerProperties properties; + public TextAnalyzer() { setType(AnalyzerType.text); } - private TextAnalyzerProperties properties; - public TextAnalyzerProperties getProperties() { return properties; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java similarity index 93% rename from src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java rename to core/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java index b22f7bc34..acba41525 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java +++ b/core/src/main/java/com/arangodb/entity/arangosearch/analyzer/TextAnalyzerProperties.java @@ -21,7 +21,7 @@ package com.arangodb.entity.arangosearch.analyzer; -import com.arangodb.velocypack.annotations.SerializedName; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Collections; import java.util.List; @@ -30,31 +30,26 @@ /** * @author Michele Rastelli */ -public class TextAnalyzerProperties { - - public TextAnalyzerProperties() { - stopwords = Collections.emptyList(); - } +public final class TextAnalyzerProperties { private String locale; - private boolean accent; - - @SerializedName("case") + @JsonProperty("case") private SearchAnalyzerCase analyzerCase; - private boolean stemming; - private EdgeNgram edgeNgram; - private List stopwords; - private String stopwordsPath; + public TextAnalyzerProperties() { + stopwords = Collections.emptyList(); + } + /** * @return a locale in the format `language[_COUNTRY][.encoding][@variant]` (square brackets denote optional parts), * e.g. `de.utf-8` or `en_US.utf-8`. Only UTF-8 encoding is meaningful in ArangoDB. - * @see Supported Languages + * @see + * Supported Languages */ public String getLocale() { return locale; @@ -130,13 +125,15 @@ public void setStopwords(List stopwords) { } /** - * @return path with a language sub-directory (e.g. en for a locale en_US.utf-8) containing files with words to omit. + * @return path with a language sub-directory (e.g. en for a locale en_US.utf-8) containing files with words to + * omit. * Each word has to be on a separate line. Everything after the first whitespace character on a line will be ignored * and can be used for comments. The files can be named arbitrarily and have any file extension (or none). *

    * Default: if no path is provided then the value of the environment variable IRESEARCH_TEXT_STOPWORD_PATH is used * to determine the path, or if it is undefined then the current working directory is assumed. If the stopwords - * attribute is provided then no stop-words are loaded from files, unless an explicit stopwordsPath is also provided. + * attribute is provided then no stop-words are loaded from files, unless an explicit stopwordsPath is also + * provided. *

    * Note that if the stopwordsPath can not be accessed, is missing language sub-directories or has no files for a * language required by an Analyzer, then the creation of a new Analyzer is refused. If such an issue is discovered diff --git a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/core/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java similarity index 50% rename from src/main/java/com/arangodb/internal/ArangoCollectionImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index ef362803b..0f8f8834f 100644 --- a/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/core/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -25,12 +25,14 @@ import com.arangodb.entity.*; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.model.*; -import com.arangodb.velocypack.VPackSlice; +import com.arangodb.util.RawData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collection; +import static com.arangodb.internal.serde.SerdeUtils.constructParametricType; + /** * @author Mark Vollmary * @author Michele Rastelli @@ -38,71 +40,99 @@ public class ArangoCollectionImpl extends InternalArangoCollection implements ArangoCollection { - private static final Logger LOGGER = LoggerFactory.getLogger(ArangoCollection.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ArangoCollectionImpl.class); protected ArangoCollectionImpl(final ArangoDatabaseImpl db, final String name) { super(db, name); } @Override - public DocumentCreateEntity insertDocument(final T value) throws ArangoDBException { - return insertDocument(value, new DocumentCreateOptions()); + public DocumentCreateEntity insertDocument(final Object value) { + return executor.execute(insertDocumentRequest(value, new DocumentCreateOptions()), + constructParametricType(DocumentCreateEntity.class, Void.class)); } @Override - public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options) - throws ArangoDBException { + @SuppressWarnings("unchecked") + public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options) { + return insertDocument(value, options, (Class) value.getClass()); + } + + @Override + public DocumentCreateEntity insertDocument(final T value, final DocumentCreateOptions options, + final Class type) { + return executor.execute(insertDocumentRequest(value, options), + constructParametricType(DocumentCreateEntity.class, type)); + } + + @Override + public MultiDocumentEntity> insertDocuments(RawData values) { return executor - .execute(insertDocumentRequest(value, options), insertDocumentResponseDeserializer(value, options)); + .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), + insertDocumentsResponseDeserializer(Void.class)); } @Override - public MultiDocumentEntity> insertDocuments(final Collection values) - throws ArangoDBException { - return insertDocuments(values, new DocumentCreateOptions()); + @SuppressWarnings("unchecked") + public MultiDocumentEntity> insertDocuments(RawData values, + DocumentCreateOptions options) { + return executor + .execute(insertDocumentsRequest(values, options), + insertDocumentsResponseDeserializer((Class) values.getClass())); } @Override + public MultiDocumentEntity> insertDocuments(final Collection values) { + return executor + .execute(insertDocumentsRequest(values, new DocumentCreateOptions()), + insertDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") public MultiDocumentEntity> insertDocuments( - final Collection values, final DocumentCreateOptions options) throws ArangoDBException { - final DocumentCreateOptions params = (options != null ? options : new DocumentCreateOptions()); + final Collection values, final DocumentCreateOptions options) { + return insertDocuments(values, options, (Class) getCollectionContentClass(values)); + } + + @Override + public MultiDocumentEntity> insertDocuments(Collection values, + DocumentCreateOptions options, + Class type) { return executor - .execute(insertDocumentsRequest(values, params), insertDocumentsResponseDeserializer(values, params)); + .execute(insertDocumentsRequest(values, options), insertDocumentsResponseDeserializer(type)); } @Override - public DocumentImportEntity importDocuments(final Collection values) throws ArangoDBException { + public DocumentImportEntity importDocuments(final Collection values) { return importDocuments(values, new DocumentImportOptions()); } @Override - public DocumentImportEntity importDocuments(final Collection values, final DocumentImportOptions options) - throws ArangoDBException { + public DocumentImportEntity importDocuments(final Collection values, final DocumentImportOptions options) { return executor.execute(importDocumentsRequest(values, options), DocumentImportEntity.class); } @Override - public DocumentImportEntity importDocuments(final String values) throws ArangoDBException { + public DocumentImportEntity importDocuments(RawData values) { return importDocuments(values, new DocumentImportOptions()); } @Override - public DocumentImportEntity importDocuments(final String values, final DocumentImportOptions options) - throws ArangoDBException { + public DocumentImportEntity importDocuments(RawData values, DocumentImportOptions options) { return executor.execute(importDocumentsRequest(values, options), DocumentImportEntity.class); } @Override - public T getDocument(final String key, final Class type) throws ArangoDBException { + public T getDocument(final String key, final Class type) { return getDocument(key, type, new DocumentReadOptions()); } @Override - public T getDocument(final String key, final Class type, final DocumentReadOptions options) - throws ArangoDBException { + public T getDocument(final String key, final Class type, final DocumentReadOptions options) { DocumentUtil.validateDocumentKey(key); try { - return executor.execute(getDocumentRequest(key, options), type); + return executor.execute(getDocumentRequest(key, options), getDocumentResponseDeserializer(type)); } catch (final ArangoDBException e) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(e.getMessage(), e); @@ -114,7 +144,7 @@ public T getDocument(final String key, final Class type, final DocumentRe } if ((e.getResponseCode() != null && (e.getResponseCode() == 404 || e.getResponseCode() == 304 - || e.getResponseCode() == 412)) && (options == null || options.isCatchException())) { + || e.getResponseCode() == 412))) { return null; } throw e; @@ -122,105 +152,170 @@ public T getDocument(final String key, final Class type, final DocumentRe } @Override - public MultiDocumentEntity getDocuments(final Collection keys, final Class type) - throws ArangoDBException { + public MultiDocumentEntity getDocuments(final Collection keys, final Class type) { return getDocuments(keys, type, new DocumentReadOptions()); } @Override public MultiDocumentEntity getDocuments( - final Collection keys, final Class type, final DocumentReadOptions options) - throws ArangoDBException { - return executor.execute(getDocumentsRequest(keys, options), getDocumentsResponseDeserializer(type, options)); + final Collection keys, final Class type, final DocumentReadOptions options) { + return executor.execute(getDocumentsRequest(keys, options), getDocumentsResponseDeserializer(type)); } @Override - public DocumentUpdateEntity replaceDocument(final String key, final T value) throws ArangoDBException { - return replaceDocument(key, value, new DocumentReplaceOptions()); + public DocumentUpdateEntity replaceDocument(final String key, final Object value) { + return executor.execute(replaceDocumentRequest(key, value, new DocumentReplaceOptions()), + constructParametricType(DocumentUpdateEntity.class, Void.class)); } @Override + @SuppressWarnings("unchecked") public DocumentUpdateEntity replaceDocument( - final String key, final T value, final DocumentReplaceOptions options) throws ArangoDBException { + final String key, final T value, final DocumentReplaceOptions options) { + return replaceDocument(key, value, options, (Class) value.getClass()); + } + + @Override + public DocumentUpdateEntity replaceDocument(String key, T value, DocumentReplaceOptions options, + Class type) { return executor.execute(replaceDocumentRequest(key, value, options), - replaceDocumentResponseDeserializer(value, options)); + constructParametricType(DocumentUpdateEntity.class, type)); } @Override - public MultiDocumentEntity> replaceDocuments(final Collection values) - throws ArangoDBException { - return replaceDocuments(values, new DocumentReplaceOptions()); + public MultiDocumentEntity> replaceDocuments(RawData values) { + return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), + replaceDocumentsResponseDeserializer(Void.class)); } @Override + @SuppressWarnings("unchecked") + public MultiDocumentEntity> replaceDocuments(RawData values, + DocumentReplaceOptions options) { + return executor.execute(replaceDocumentsRequest(values, options), + replaceDocumentsResponseDeserializer((Class) values.getClass())); + } + + @Override + public MultiDocumentEntity> replaceDocuments(final Collection values) { + return executor.execute(replaceDocumentsRequest(values, new DocumentReplaceOptions()), + replaceDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") public MultiDocumentEntity> replaceDocuments( - final Collection values, final DocumentReplaceOptions options) throws ArangoDBException { - final DocumentReplaceOptions params = (options != null ? options : new DocumentReplaceOptions()); - return executor - .execute(replaceDocumentsRequest(values, params), replaceDocumentsResponseDeserializer(values, params)); + final Collection values, final DocumentReplaceOptions options) { + return replaceDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override - public DocumentUpdateEntity updateDocument(final String key, final T value) throws ArangoDBException { - return updateDocument(key, value, new DocumentUpdateOptions()); + public MultiDocumentEntity> replaceDocuments(Collection values, + DocumentReplaceOptions options, + Class type) { + return executor.execute(replaceDocumentsRequest(values, options), replaceDocumentsResponseDeserializer(type)); } @Override + public DocumentUpdateEntity updateDocument(final String key, final Object value) { + return updateDocument(key, value, new DocumentUpdateOptions(), Void.class); + } + + @Override + @SuppressWarnings("unchecked") public DocumentUpdateEntity updateDocument( - final String key, final T value, final DocumentUpdateOptions options) throws ArangoDBException { + final String key, final T value, final DocumentUpdateOptions options) { return updateDocument(key, value, options, (Class) value.getClass()); } @Override - public DocumentUpdateEntity updateDocument( - final String key, final T value, final DocumentUpdateOptions options, final Class returnType) throws ArangoDBException { + public DocumentUpdateEntity updateDocument( + final String key, final Object value, final DocumentUpdateOptions options, final Class returnType) { return executor.execute(updateDocumentRequest(key, value, options), - updateDocumentResponseDeserializer(value, options, returnType)); + constructParametricType(DocumentUpdateEntity.class, returnType)); + } + + @Override + public MultiDocumentEntity> updateDocuments(RawData values) { + return executor + .execute(updateDocumentsRequest(values, new DocumentUpdateOptions()), + updateDocumentsResponseDeserializer(Void.class)); + } + + @Override + @SuppressWarnings("unchecked") + public MultiDocumentEntity> updateDocuments(RawData values, + DocumentUpdateOptions options) { + return executor + .execute(updateDocumentsRequest(values, options), + updateDocumentsResponseDeserializer((Class) values.getClass())); } @Override - public MultiDocumentEntity> updateDocuments(final Collection values) - throws ArangoDBException { - return updateDocuments(values, new DocumentUpdateOptions()); + public MultiDocumentEntity> updateDocuments(final Collection values) { + return updateDocuments(values, new DocumentUpdateOptions(), Void.class); } @Override + @SuppressWarnings("unchecked") public MultiDocumentEntity> updateDocuments( - final Collection values, final DocumentUpdateOptions options) throws ArangoDBException { - return updateDocuments(values, options, values.isEmpty() ? null : (Class) values.iterator().next().getClass()); + final Collection values, final DocumentUpdateOptions options) { + return updateDocuments(values, options, (Class) getCollectionContentClass(values)); } @Override - public MultiDocumentEntity> updateDocuments( - final Collection values, final DocumentUpdateOptions options, final Class returnType) throws ArangoDBException { - final DocumentUpdateOptions params = (options != null ? options : new DocumentUpdateOptions()); + public MultiDocumentEntity> updateDocuments( + final Collection values, final DocumentUpdateOptions options, final Class returnType) { return executor - .execute(updateDocumentsRequest(values, params), updateDocumentsResponseDeserializer(returnType)); + .execute(updateDocumentsRequest(values, options), updateDocumentsResponseDeserializer(returnType)); } @Override - public DocumentDeleteEntity deleteDocument(final String key) throws ArangoDBException { - return executor.execute(deleteDocumentRequest(key, new DocumentDeleteOptions()), - deleteDocumentResponseDeserializer(Void.class)); + public DocumentDeleteEntity deleteDocument(final String key) { + return deleteDocument(key, new DocumentDeleteOptions()); + } + + @Override + public DocumentDeleteEntity deleteDocument(String key, DocumentDeleteOptions options) { + return deleteDocument(key, options, Void.class); } @Override public DocumentDeleteEntity deleteDocument( - final String key, final Class type, final DocumentDeleteOptions options) throws ArangoDBException { - return executor.execute(deleteDocumentRequest(key, options), deleteDocumentResponseDeserializer(type)); + final String key, final DocumentDeleteOptions options, final Class type) { + return executor.execute(deleteDocumentRequest(key, options), + constructParametricType(DocumentDeleteEntity.class, type)); } @Override - public MultiDocumentEntity> deleteDocuments(final Collection values) - throws ArangoDBException { + public MultiDocumentEntity> deleteDocuments(RawData values) { return executor.execute(deleteDocumentsRequest(values, new DocumentDeleteOptions()), deleteDocumentsResponseDeserializer(Void.class)); } + @Override + @SuppressWarnings("unchecked") + public MultiDocumentEntity> deleteDocuments(RawData values, + DocumentDeleteOptions options) { + return executor.execute(deleteDocumentsRequest(values, options), + deleteDocumentsResponseDeserializer((Class) values.getClass())); + } + + @Override + public MultiDocumentEntity> deleteDocuments(final Collection values) { + return deleteDocuments(values, new DocumentDeleteOptions(), Void.class); + } + + @Override + @SuppressWarnings("unchecked") + public MultiDocumentEntity> deleteDocuments( + final Collection values, final DocumentDeleteOptions options) { + return deleteDocuments(values, options, (Class) getCollectionContentClass(values)); + } + @Override public MultiDocumentEntity> deleteDocuments( - final Collection values, final Class type, final DocumentDeleteOptions options) - throws ArangoDBException { + final Collection values, final DocumentDeleteOptions options, final Class type) { return executor.execute(deleteDocumentsRequest(values, options), deleteDocumentsResponseDeserializer(type)); } @@ -230,9 +325,9 @@ public Boolean documentExists(final String key) { } @Override - public Boolean documentExists(final String key, final DocumentExistsOptions options) throws ArangoDBException { + public Boolean documentExists(final String key, final DocumentExistsOptions options) { try { - executor.execute(documentExistsRequest(key, options), VPackSlice.class); + executor.execute(documentExistsRequest(key, options), Void.class); return true; } catch (final ArangoDBException e) { @@ -241,8 +336,8 @@ public Boolean documentExists(final String key, final DocumentExistsOptions opti throw e; } - if ((e.getResponseCode() != null && (e.getResponseCode() == 404 || e.getResponseCode() == 304 - || e.getResponseCode() == 412)) && (options == null || options.isCatchException())) { + if ((e.getResponseCode() != null && + (e.getResponseCode() == 404 || e.getResponseCode() == 304 || e.getResponseCode() == 412))) { return false; } throw e; @@ -250,66 +345,75 @@ public Boolean documentExists(final String key, final DocumentExistsOptions opti } @Override - public IndexEntity getIndex(final String id) throws ArangoDBException { + public IndexEntity getIndex(final String id) { return executor.execute(getIndexRequest(id), IndexEntity.class); } @Override - public String deleteIndex(final String id) throws ArangoDBException { + public InvertedIndexEntity getInvertedIndex(String id) { + return executor.execute(getIndexRequest(id), InvertedIndexEntity.class); + } + + @Override + public String deleteIndex(final String id) { return executor.execute(deleteIndexRequest(id), deleteIndexResponseDeserializer()); } @Deprecated @Override - public IndexEntity ensureHashIndex(final Iterable fields, final HashIndexOptions options) - throws ArangoDBException { + public IndexEntity ensureHashIndex(final Iterable fields, final HashIndexOptions options) { return executor.execute(createHashIndexRequest(fields, options), IndexEntity.class); } @Deprecated @Override - public IndexEntity ensureSkiplistIndex(final Iterable fields, final SkiplistIndexOptions options) - throws ArangoDBException { + public IndexEntity ensureSkiplistIndex(final Iterable fields, final SkiplistIndexOptions options) { return executor.execute(createSkiplistIndexRequest(fields, options), IndexEntity.class); } @Override - public IndexEntity ensurePersistentIndex(final Iterable fields, final PersistentIndexOptions options) - throws ArangoDBException { + public IndexEntity ensurePersistentIndex(final Iterable fields, final PersistentIndexOptions options) { return executor.execute(createPersistentIndexRequest(fields, options), IndexEntity.class); } @Override - public IndexEntity ensureGeoIndex(final Iterable fields, final GeoIndexOptions options) - throws ArangoDBException { + public InvertedIndexEntity ensureInvertedIndex(final InvertedIndexOptions options) { + return executor.execute(createInvertedIndexRequest(options), InvertedIndexEntity.class); + } + + @Override + public IndexEntity ensureGeoIndex(final Iterable fields, final GeoIndexOptions options) { return executor.execute(createGeoIndexRequest(fields, options), IndexEntity.class); } + @Deprecated @Override - public IndexEntity ensureFulltextIndex(final Iterable fields, final FulltextIndexOptions options) - throws ArangoDBException { + public IndexEntity ensureFulltextIndex(final Iterable fields, final FulltextIndexOptions options) { return executor.execute(createFulltextIndexRequest(fields, options), IndexEntity.class); } @Override - public IndexEntity ensureTtlIndex(final Iterable fields, final TtlIndexOptions options) - throws ArangoDBException { + public IndexEntity ensureTtlIndex(final Iterable fields, final TtlIndexOptions options) { return executor.execute(createTtlIndexRequest(fields, options), IndexEntity.class); } @Override - public IndexEntity ensureZKDIndex(final Iterable fields, final ZKDIndexOptions options) - throws ArangoDBException { + public IndexEntity ensureZKDIndex(final Iterable fields, final ZKDIndexOptions options) { return executor.execute(createZKDIndexRequest(fields, options), IndexEntity.class); } @Override - public Collection getIndexes() throws ArangoDBException { + public Collection getIndexes() { return executor.execute(getIndexesRequest(), getIndexesResponseDeserializer()); } @Override - public boolean exists() throws ArangoDBException { + public Collection getInvertedIndexes() { + return executor.execute(getIndexesRequest(), getInvertedIndexesResponseDeserializer()); + } + + @Override + public boolean exists() { try { getInfo(); return true; @@ -322,105 +426,94 @@ public boolean exists() throws ArangoDBException { } @Override - public CollectionEntity truncate() throws ArangoDBException { + public CollectionEntity truncate() { return truncate(null); } @Override - public CollectionEntity truncate(CollectionTruncateOptions options) throws ArangoDBException { + public CollectionEntity truncate(CollectionTruncateOptions options) { return executor.execute(truncateRequest(options), CollectionEntity.class); } @Override - public CollectionPropertiesEntity count() throws ArangoDBException { + public CollectionPropertiesEntity count() { return count(null); } @Override - public CollectionPropertiesEntity count(CollectionCountOptions options) throws ArangoDBException { + public CollectionPropertiesEntity count(CollectionCountOptions options) { return executor.execute(countRequest(options), CollectionPropertiesEntity.class); } @Override - public CollectionEntity create() throws ArangoDBException { + public CollectionEntity create() { return db().createCollection(name()); } @Override - public CollectionEntity create(final CollectionCreateOptions options) throws ArangoDBException { + public CollectionEntity create(final CollectionCreateOptions options) { return db().createCollection(name(), options); } @Override - public void drop() throws ArangoDBException { + public void drop() { executor.execute(dropRequest(null), Void.class); } @Override - public void drop(final boolean isSystem) throws ArangoDBException { + public void drop(final boolean isSystem) { executor.execute(dropRequest(isSystem), Void.class); } @Override - public CollectionEntity load() throws ArangoDBException { - return executor.execute(loadRequest(), CollectionEntity.class); - } - - @Override - public CollectionEntity unload() throws ArangoDBException { - return executor.execute(unloadRequest(), CollectionEntity.class); - } - - @Override - public CollectionEntity getInfo() throws ArangoDBException { + public CollectionEntity getInfo() { return executor.execute(getInfoRequest(), CollectionEntity.class); } @Override - public CollectionPropertiesEntity getProperties() throws ArangoDBException { + public CollectionPropertiesEntity getProperties() { return executor.execute(getPropertiesRequest(), CollectionPropertiesEntity.class); } @Override - public CollectionPropertiesEntity changeProperties(final CollectionPropertiesOptions options) - throws ArangoDBException { + public CollectionPropertiesEntity changeProperties(final CollectionPropertiesOptions options) { return executor.execute(changePropertiesRequest(options), CollectionPropertiesEntity.class); } @Override - public synchronized CollectionEntity rename(final String newName) throws ArangoDBException { + public synchronized CollectionEntity rename(final String newName) { final CollectionEntity result = executor.execute(renameRequest(newName), CollectionEntity.class); name = result.getName(); return result; } @Override - public ShardEntity getResponsibleShard(final Object value) throws ArangoDBException { + public ShardEntity getResponsibleShard(final Object value) { return executor.execute(responsibleShardRequest(value), ShardEntity.class); } @Override - public CollectionRevisionEntity getRevision() throws ArangoDBException { + public CollectionRevisionEntity getRevision() { return executor.execute(getRevisionRequest(), CollectionRevisionEntity.class); } @Override - public void grantAccess(final String user, final Permissions permissions) throws ArangoDBException { + public void grantAccess(final String user, final Permissions permissions) { executor.execute(grantAccessRequest(user, permissions), Void.class); } @Override - public void revokeAccess(final String user) throws ArangoDBException { + public void revokeAccess(final String user) { executor.execute(grantAccessRequest(user, Permissions.NONE), Void.class); } @Override - public void resetAccess(final String user) throws ArangoDBException { + public void resetAccess(final String user) { executor.execute(resetAccessRequest(user), Void.class); } @Override - public Permissions getPermissions(final String user) throws ArangoDBException { + public Permissions getPermissions(final String user) { return executor.execute(getPermissionsRequest(user), getPermissionsResponseDeserialzer()); } diff --git a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java b/core/src/main/java/com/arangodb/internal/ArangoCursorExecute.java similarity index 74% rename from src/main/java/com/arangodb/internal/ArangoCursorExecute.java rename to core/src/main/java/com/arangodb/internal/ArangoCursorExecute.java index 455844113..7efc5eef9 100644 --- a/src/main/java/com/arangodb/internal/ArangoCursorExecute.java +++ b/core/src/main/java/com/arangodb/internal/ArangoCursorExecute.java @@ -1,37 +1,36 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.ArangoDBException; -import com.arangodb.entity.CursorEntity; - -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public interface ArangoCursorExecute { - - CursorEntity next(String id, Map meta) throws ArangoDBException; - - void close(String id, Map meta) throws ArangoDBException; - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.internal.cursor.entity.InternalCursorEntity; + +import java.util.Map; + +/** + * @author Mark Vollmary + */ +public interface ArangoCursorExecute { + + InternalCursorEntity next(String id, Map meta); + + void close(String id, Map meta); + +} diff --git a/src/main/java/com/arangodb/internal/ArangoDBImpl.java b/core/src/main/java/com/arangodb/internal/ArangoDBImpl.java similarity index 50% rename from src/main/java/com/arangodb/internal/ArangoDBImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoDBImpl.java index be0ffd48c..52801b51e 100644 --- a/src/main/java/com/arangodb/internal/ArangoDBImpl.java +++ b/core/src/main/java/com/arangodb/internal/ArangoDBImpl.java @@ -22,28 +22,18 @@ import com.arangodb.*; import com.arangodb.entity.*; -import com.arangodb.internal.http.HttpCommunication; -import com.arangodb.internal.http.HttpProtocol; -import com.arangodb.internal.net.CommunicationProtocol; -import com.arangodb.internal.net.HostHandle; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; -import com.arangodb.internal.velocystream.VstCommunicationSync; -import com.arangodb.internal.velocystream.VstProtocol; +import com.arangodb.internal.net.ProtocolProvider; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.DBCreateOptions; import com.arangodb.model.LogOptions; import com.arangodb.model.UserCreateOptions; import com.arangodb.model.UserUpdateOptions; -import com.arangodb.util.ArangoCursorInitializer; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; import java.util.Collection; /** @@ -54,55 +44,15 @@ public class ArangoDBImpl extends InternalArangoDB implements ArangoDB { private static final Logger LOGGER = LoggerFactory.getLogger(ArangoDBImpl.class); - - private ArangoCursorInitializer cursorInitializer; - private final CommunicationProtocol cp; private final HostHandler hostHandler; - public ArangoDBImpl(final VstCommunicationSync.Builder vstBuilder, final HttpCommunication.Builder httpBuilder, - final ArangoSerializationFactory util, final Protocol protocol, final HostResolver hostResolver, - final HostHandler hostHandler, final ArangoContext context, int responseQueueTimeSamples, final int timeoutMs) { - - super(new ArangoExecutorSync( - createProtocol(vstBuilder, httpBuilder, util.get(Serializer.INTERNAL), protocol), - util, - new DocumentCache(), new QueueTimeMetricsImpl(responseQueueTimeSamples), timeoutMs), - util, - context); - - cp = createProtocol( - new VstCommunicationSync.Builder(vstBuilder).maxConnections(1), - new HttpCommunication.Builder(httpBuilder), - util.get(Serializer.INTERNAL), - protocol); + public ArangoDBImpl(final ArangoConfig config, + final HostResolver hostResolver, final ProtocolProvider protocolProvider, + final HostHandler hostHandler) { + super(new ArangoExecutorSync(protocolProvider.createProtocol(config, hostHandler), config), config.getInternalSerde()); this.hostHandler = hostHandler; - - hostResolver.init(this.executor(), util()); - + hostResolver.init(this.executor(), getSerde()); LOGGER.debug("ArangoDB Client is ready to use"); - - } - - private static CommunicationProtocol createProtocol( - final VstCommunicationSync.Builder vstBuilder, - final HttpCommunication.Builder httpBuilder, - final ArangoSerialization util, - final Protocol protocol) { - - return (protocol == null || Protocol.VST == protocol) ? createVST(vstBuilder, util) - : createHTTP(httpBuilder, util); - } - - private static CommunicationProtocol createVST( - final VstCommunicationSync.Builder builder, - final ArangoSerialization util) { - return new VstProtocol(builder.build(util)); - } - - private static CommunicationProtocol createHTTP( - final HttpCommunication.Builder builder, - final ArangoSerialization util) { - return new HttpProtocol(builder.build(util)); } @Override @@ -111,22 +61,13 @@ protected ArangoExecutorSync executor() { } @Override - public void shutdown() throws ArangoDBException { - try { - executor.disconnect(); - } finally { - try { - cp.close(); - } catch (final IOException e) { - LOGGER.error("Got exception during shutdown:", e); - } - } + public void shutdown() { + executor.disconnect(); } @Override public void updateJwt(String jwt) { hostHandler.setJwt(jwt); - cp.setJwt(jwt); executor.setJwt(jwt); } @@ -137,7 +78,7 @@ public ArangoDatabase db() { @Override public ArangoDatabase db(final DbName dbName) { - return new ArangoDatabaseImpl(this, dbName).setCursorInitializer(cursorInitializer); + return new ArangoDatabaseImpl(this, dbName); } @Override @@ -146,133 +87,120 @@ public ArangoMetrics metrics() { } @Override - public Boolean createDatabase(final DbName dbName) throws ArangoDBException { + public Boolean createDatabase(final DbName dbName) { return createDatabase(new DBCreateOptions().name(dbName)); } @Override - public Boolean createDatabase(DBCreateOptions options) throws ArangoDBException { + public Boolean createDatabase(DBCreateOptions options) { return executor.execute(createDatabaseRequest(options), createDatabaseResponseDeserializer()); } @Override - public Collection getDatabases() throws ArangoDBException { + public Collection getDatabases() { return executor.execute(getDatabasesRequest(db().dbName()), getDatabaseResponseDeserializer()); } @Override - public Collection getAccessibleDatabases() throws ArangoDBException { + public Collection getAccessibleDatabases() { return db().getAccessibleDatabases(); } @Override - public Collection getAccessibleDatabasesFor(final String user) throws ArangoDBException { + public Collection getAccessibleDatabasesFor(final String user) { return executor.execute(getAccessibleDatabasesForRequest(db().dbName(), user), getAccessibleDatabasesForResponseDeserializer()); } @Override - public ArangoDBVersion getVersion() throws ArangoDBException { + public ArangoDBVersion getVersion() { return db().getVersion(); } @Override - public ArangoDBEngine getEngine() throws ArangoDBException { + public ArangoDBEngine getEngine() { return db().getEngine(); } @Override - public ServerRole getRole() throws ArangoDBException { + public ServerRole getRole() { return executor.execute(getRoleRequest(), getRoleResponseDeserializer()); } @Override - public String getServerId() throws ArangoDBException { + public String getServerId() { return executor.execute(getServerIdRequest(), getServerIdResponseDeserializer()); } @Override - public UserEntity createUser(final String user, final String passwd) throws ArangoDBException { + public UserEntity createUser(final String user, final String passwd) { return executor.execute(createUserRequest(db().dbName(), user, passwd, new UserCreateOptions()), UserEntity.class); } @Override - public UserEntity createUser(final String user, final String passwd, final UserCreateOptions options) - throws ArangoDBException { + public UserEntity createUser(final String user, final String passwd, final UserCreateOptions options) { return executor.execute(createUserRequest(db().dbName(), user, passwd, options), UserEntity.class); } @Override - public void deleteUser(final String user) throws ArangoDBException { + public void deleteUser(final String user) { executor.execute(deleteUserRequest(db().dbName(), user), Void.class); } @Override - public UserEntity getUser(final String user) throws ArangoDBException { + public UserEntity getUser(final String user) { return executor.execute(getUserRequest(db().dbName(), user), UserEntity.class); } @Override - public Collection getUsers() throws ArangoDBException { + public Collection getUsers() { return executor.execute(getUsersRequest(db().dbName()), getUsersResponseDeserializer()); } @Override - public UserEntity updateUser(final String user, final UserUpdateOptions options) throws ArangoDBException { + public UserEntity updateUser(final String user, final UserUpdateOptions options) { return executor.execute(updateUserRequest(db().dbName(), user, options), UserEntity.class); } @Override - public UserEntity replaceUser(final String user, final UserUpdateOptions options) throws ArangoDBException { + public UserEntity replaceUser(final String user, final UserUpdateOptions options) { return executor.execute(replaceUserRequest(db().dbName(), user, options), UserEntity.class); } @Override - public void grantDefaultDatabaseAccess(final String user, final Permissions permissions) throws ArangoDBException { + public void grantDefaultDatabaseAccess(final String user, final Permissions permissions) { executor.execute(updateUserDefaultDatabaseAccessRequest(user, permissions), Void.class); } @Override - public void grantDefaultCollectionAccess(final String user, final Permissions permissions) - throws ArangoDBException { + public void grantDefaultCollectionAccess(final String user, final Permissions permissions) { executor.execute(updateUserDefaultCollectionAccessRequest(user, permissions), Void.class); } @Override - public Response execute(final Request request) throws ArangoDBException { - return executor.execute(request, response -> response); - } - - @Override - public Response execute(final Request request, final HostHandle hostHandle) throws ArangoDBException { - return executor.execute(request, response -> response, hostHandle); - } - - @Override - public LogEntity getLogs(final LogOptions options) throws ArangoDBException { - return executor.execute(getLogsRequest(options), LogEntity.class); + public Response execute(Request request, Class type) { + return executor.execute(executeRequest(request), responseDeserializer(type)); } @Override - public LogEntriesEntity getLogEntries(final LogOptions options) throws ArangoDBException { + public LogEntriesEntity getLogEntries(final LogOptions options) { return executor.execute(getLogEntriesRequest(options), LogEntriesEntity.class); } @Override - public LogLevelEntity getLogLevel() throws ArangoDBException { + public LogLevelEntity getLogLevel() { return executor.execute(getLogLevelRequest(), LogLevelEntity.class); } @Override - public LogLevelEntity setLogLevel(final LogLevelEntity entity) throws ArangoDBException { + public LogLevelEntity setLogLevel(final LogLevelEntity entity) { return executor.execute(setLogLevelRequest(entity), LogLevelEntity.class); } @Override - public ArangoDBImpl _setCursorInitializer(final ArangoCursorInitializer cursorInitializer) { - this.cursorInitializer = cursorInitializer; - return this; + public Collection getQueryOptimizerRules() { + return executor.execute(getQueryOptimizerRulesRequest(), SerdeUtils.constructListType(QueryOptimizerRule.class)); } } diff --git a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java b/core/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java similarity index 65% rename from src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java index 6b38136ac..e2c1eca2d 100644 --- a/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java +++ b/core/src/main/java/com/arangodb/internal/ArangoDatabaseImpl.java @@ -22,22 +22,21 @@ import com.arangodb.*; import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.AnalyzerEntity; import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; import com.arangodb.internal.cursor.ArangoCursorImpl; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.model.*; import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import com.arangodb.util.ArangoCursorInitializer; -import com.arangodb.velocypack.Type; -import com.arangodb.velocystream.Request; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; import java.util.Collection; -import java.util.Collections; import java.util.Map; +import static com.arangodb.internal.serde.SerdeUtils.constructListType; + /** * @author Mark Vollmary * @author Michele Rastelli @@ -45,24 +44,22 @@ public class ArangoDatabaseImpl extends InternalArangoDatabase implements ArangoDatabase { - private ArangoCursorInitializer cursorInitializer; - protected ArangoDatabaseImpl(final ArangoDBImpl arangoDB, final DbName name) { super(arangoDB, name); } @Override - public ArangoDBVersion getVersion() throws ArangoDBException { + public ArangoDBVersion getVersion() { return executor.execute(getVersionRequest(), ArangoDBVersion.class); } @Override - public ArangoDBEngine getEngine() throws ArangoDBException { + public ArangoDBEngine getEngine() { return executor.execute(getEngineRequest(), ArangoDBEngine.class); } @Override - public boolean exists() throws ArangoDBException { + public boolean exists() { try { getInfo(); return true; @@ -75,7 +72,7 @@ public boolean exists() throws ArangoDBException { } @Override - public Collection getAccessibleDatabases() throws ArangoDBException { + public Collection getAccessibleDatabases() { return executor.execute(getAccessibleDatabasesRequest(), getDatabaseResponseDeserializer()); } @@ -85,90 +82,88 @@ public ArangoCollection collection(final String name) { } @Override - public CollectionEntity createCollection(final String name) throws ArangoDBException { + public CollectionEntity createCollection(final String name) { return executor.execute(createCollectionRequest(name, new CollectionCreateOptions()), CollectionEntity.class); } @Override - public CollectionEntity createCollection(final String name, final CollectionCreateOptions options) - throws ArangoDBException { + public CollectionEntity createCollection(final String name, final CollectionCreateOptions options) { return executor.execute(createCollectionRequest(name, options), CollectionEntity.class); } @Override - public Collection getCollections() throws ArangoDBException { + public Collection getCollections() { return executor .execute(getCollectionsRequest(new CollectionsReadOptions()), getCollectionsResponseDeserializer()); } @Override - public Collection getCollections(final CollectionsReadOptions options) throws ArangoDBException { + public Collection getCollections(final CollectionsReadOptions options) { return executor.execute(getCollectionsRequest(options), getCollectionsResponseDeserializer()); } @Override - public IndexEntity getIndex(final String id) throws ArangoDBException { + public IndexEntity getIndex(final String id) { DocumentUtil.validateIndexId(id); final String[] split = id.split("/"); return collection(split[0]).getIndex(split[1]); } @Override - public String deleteIndex(final String id) throws ArangoDBException { + public String deleteIndex(final String id) { DocumentUtil.validateIndexId(id); final String[] split = id.split("/"); return collection(split[0]).deleteIndex(split[1]); } @Override - public Boolean create() throws ArangoDBException { + public Boolean create() { return arango().createDatabase(dbName()); } @Override - public Boolean drop() throws ArangoDBException { + public Boolean drop() { return executor.execute(dropRequest(), createDropResponseDeserializer()); } @Override - public void grantAccess(final String user, final Permissions permissions) throws ArangoDBException { + public void grantAccess(final String user, final Permissions permissions) { executor.execute(grantAccessRequest(user, permissions), Void.class); } @Override - public void grantAccess(final String user) throws ArangoDBException { + public void grantAccess(final String user) { executor.execute(grantAccessRequest(user, Permissions.RW), Void.class); } @Override - public void revokeAccess(final String user) throws ArangoDBException { + public void revokeAccess(final String user) { executor.execute(grantAccessRequest(user, Permissions.NONE), Void.class); } @Override - public void resetAccess(final String user) throws ArangoDBException { + public void resetAccess(final String user) { executor.execute(resetAccessRequest(user), Void.class); } @Override - public void grantDefaultCollectionAccess(final String user, final Permissions permissions) - throws ArangoDBException { + public void grantDefaultCollectionAccess(final String user, final Permissions permissions) { executor.execute(updateUserDefaultCollectionAccessRequest(user, permissions), Void.class); } @Override - public Permissions getPermissions(final String user) throws ArangoDBException { + public Permissions getPermissions(final String user) { return executor.execute(getPermissionsRequest(user), getPermissionsResponseDeserialzer()); } @Override public ArangoCursor query( - final String query, final Map bindVars, final AqlQueryOptions options, final Class type) - throws ArangoDBException { + final String query, final Map bindVars, final AqlQueryOptions options, + final Class type) { - final Request request = queryRequest(query, bindVars, options); + final InternalRequest request = queryRequest(query, bindVars, options); final HostHandle hostHandle = new HostHandle(); - final CursorEntity result = executor.execute(request, CursorEntity.class, hostHandle); + final InternalCursorEntity result = executor.execute(request, InternalCursorEntity.class, hostHandle); return createCursor(result, type, options, hostHandle); @@ -176,39 +171,38 @@ public ArangoCursor query( @Override public ArangoCursor query( - final String query, final Map bindVars, final Class type) throws ArangoDBException { + final String query, final Map bindVars, final Class type) { return query(query, bindVars, null, type); } @Override - public ArangoCursor query(final String query, final AqlQueryOptions options, final Class type) - throws ArangoDBException { + public ArangoCursor query(final String query, final AqlQueryOptions options, final Class type) { return query(query, null, options, type); } @Override - public ArangoCursor query(final String query, final Class type) throws ArangoDBException { + public ArangoCursor query(final String query, final Class type) { return query(query, null, null, type); } @Override - public ArangoCursor cursor(final String cursorId, final Class type) throws ArangoDBException { + public ArangoCursor cursor(final String cursorId, final Class type) { final HostHandle hostHandle = new HostHandle(); - final CursorEntity result = executor - .execute(queryNextRequest(cursorId, null, null), CursorEntity.class, hostHandle); + final InternalCursorEntity result = executor + .execute(queryNextRequest(cursorId, null, null), InternalCursorEntity.class, hostHandle); return createCursor(result, type, null, hostHandle); } private ArangoCursor createCursor( - final CursorEntity result, + final InternalCursorEntity result, final Class type, final AqlQueryOptions options, final HostHandle hostHandle) { final ArangoCursorExecute execute = new ArangoCursorExecute() { @Override - public CursorEntity next(final String id, Map meta) { - return executor.execute(queryNextRequest(id, options, meta), CursorEntity.class, hostHandle); + public InternalCursorEntity next(final String id, Map meta) { + return executor.execute(queryNextRequest(id, options, meta), InternalCursorEntity.class, hostHandle); } @Override @@ -217,86 +211,80 @@ public void close(final String id, Map meta) { } }; - return cursorInitializer != null ? - cursorInitializer.createInstance(this, execute, type, result) : - new ArangoCursorImpl<>(this, execute, type, result); + return new ArangoCursorImpl<>(this, execute, type, result); } @Override public AqlExecutionExplainEntity explainQuery( - final String query, final Map bindVars, final AqlQueryExplainOptions options) - throws ArangoDBException { + final String query, final Map bindVars, final AqlQueryExplainOptions options) { return executor.execute(explainQueryRequest(query, bindVars, options), AqlExecutionExplainEntity.class); } @Override - public AqlParseEntity parseQuery(final String query) throws ArangoDBException { + public AqlParseEntity parseQuery(final String query) { return executor.execute(parseQueryRequest(query), AqlParseEntity.class); } @Override - public void clearQueryCache() throws ArangoDBException { + public void clearQueryCache() { executor.execute(clearQueryCacheRequest(), Void.class); } @Override - public QueryCachePropertiesEntity getQueryCacheProperties() throws ArangoDBException { + public QueryCachePropertiesEntity getQueryCacheProperties() { return executor.execute(getQueryCachePropertiesRequest(), QueryCachePropertiesEntity.class); } @Override - public QueryCachePropertiesEntity setQueryCacheProperties(final QueryCachePropertiesEntity properties) - throws ArangoDBException { + public QueryCachePropertiesEntity setQueryCacheProperties(final QueryCachePropertiesEntity properties) { return executor.execute(setQueryCachePropertiesRequest(properties), QueryCachePropertiesEntity.class); } @Override - public QueryTrackingPropertiesEntity getQueryTrackingProperties() throws ArangoDBException { + public QueryTrackingPropertiesEntity getQueryTrackingProperties() { return executor.execute(getQueryTrackingPropertiesRequest(), QueryTrackingPropertiesEntity.class); } @Override - public QueryTrackingPropertiesEntity setQueryTrackingProperties(final QueryTrackingPropertiesEntity properties) - throws ArangoDBException { + public QueryTrackingPropertiesEntity setQueryTrackingProperties(final QueryTrackingPropertiesEntity properties) { return executor.execute(setQueryTrackingPropertiesRequest(properties), QueryTrackingPropertiesEntity.class); } @Override - public Collection getCurrentlyRunningQueries() throws ArangoDBException { - return executor.execute(getCurrentlyRunningQueriesRequest(), new Type>() { - }.getType()); + public Collection getCurrentlyRunningQueries() { + return executor.execute(getCurrentlyRunningQueriesRequest(), + constructListType(QueryEntity.class)); } @Override - public Collection getSlowQueries() throws ArangoDBException { - return executor.execute(getSlowQueriesRequest(), new Type>() { - }.getType()); + public Collection getSlowQueries() { + return executor.execute(getSlowQueriesRequest(), + constructListType(QueryEntity.class)); } @Override - public void clearSlowQueries() throws ArangoDBException { + public void clearSlowQueries() { executor.execute(clearSlowQueriesRequest(), Void.class); } @Override - public void killQuery(final String id) throws ArangoDBException { + public void killQuery(final String id) { executor.execute(killQueryRequest(id), Void.class); } @Override public void createAqlFunction( - final String name, final String code, final AqlFunctionCreateOptions options) throws ArangoDBException { + final String name, final String code, final AqlFunctionCreateOptions options) { executor.execute(createAqlFunctionRequest(name, code, options), Void.class); } @Override - public Integer deleteAqlFunction(final String name, final AqlFunctionDeleteOptions options) - throws ArangoDBException { + public Integer deleteAqlFunction(final String name, final AqlFunctionDeleteOptions options) { return executor.execute(deleteAqlFunctionRequest(name, options), deleteAqlFunctionResponseDeserializer()); } @Override - public Collection getAqlFunctions(final AqlFunctionGetOptions options) throws ArangoDBException { + public Collection getAqlFunctions(final AqlFunctionGetOptions options) { return executor.execute(getAqlFunctionsRequest(options), getAqlFunctionsResponseDeserializer()); } @@ -306,100 +294,78 @@ public ArangoGraph graph(final String name) { } @Override - public GraphEntity createGraph(final String name, final Collection edgeDefinitions) - throws ArangoDBException { + public GraphEntity createGraph(final String name, final Collection edgeDefinitions) { return executor.execute(createGraphRequest(name, edgeDefinitions, new GraphCreateOptions()), createGraphResponseDeserializer()); } @Override public GraphEntity createGraph( - final String name, final Collection edgeDefinitions, final GraphCreateOptions options) - throws ArangoDBException { + final String name, final Collection edgeDefinitions, final GraphCreateOptions options) { return executor.execute(createGraphRequest(name, edgeDefinitions, options), createGraphResponseDeserializer()); } @Override - public Collection getGraphs() throws ArangoDBException { + public Collection getGraphs() { return executor.execute(getGraphsRequest(), getGraphsResponseDeserializer()); } @Override - public T transaction(final String action, final Class type, final TransactionOptions options) - throws ArangoDBException { + public T transaction(final String action, final Class type, final TransactionOptions options) { return executor.execute(transactionRequest(action, options), transactionResponseDeserializer(type)); } @Override - public StreamTransactionEntity beginStreamTransaction(StreamTransactionOptions options) throws ArangoDBException { + public StreamTransactionEntity beginStreamTransaction(StreamTransactionOptions options) { return executor.execute(beginStreamTransactionRequest(options), streamTransactionResponseDeserializer()); } @Override - public StreamTransactionEntity abortStreamTransaction(String id) throws ArangoDBException { + public StreamTransactionEntity abortStreamTransaction(String id) { return executor.execute(abortStreamTransactionRequest(id), streamTransactionResponseDeserializer()); } @Override - public StreamTransactionEntity getStreamTransaction(String id) throws ArangoDBException { + public StreamTransactionEntity getStreamTransaction(String id) { return executor.execute(getStreamTransactionRequest(id), streamTransactionResponseDeserializer()); } @Override - public Collection getStreamTransactions() throws ArangoDBException { + public Collection getStreamTransactions() { return executor.execute(getStreamTransactionsRequest(), transactionsResponseDeserializer()); } @Override - public StreamTransactionEntity commitStreamTransaction(String id) throws ArangoDBException { + public StreamTransactionEntity commitStreamTransaction(String id) { return executor.execute(commitStreamTransactionRequest(id), streamTransactionResponseDeserializer()); } @Override - public DatabaseEntity getInfo() throws ArangoDBException { + public DatabaseEntity getInfo() { return executor.execute(getInfoRequest(), getInfoResponseDeserializer()); } @Override - public TraversalEntity executeTraversal( - final Class vertexClass, final Class edgeClass, final TraversalOptions options) - throws ArangoDBException { - final Request request = executeTraversalRequest(options); - return executor.execute(request, executeTraversalResponseDeserializer(vertexClass, edgeClass)); - } - - @Override - public T getDocument(final String id, final Class type) throws ArangoDBException { + public T getDocument(final String id, final Class type) { DocumentUtil.validateDocumentId(id); final String[] split = id.split("/"); return collection(split[0]).getDocument(split[1], type); } @Override - public T getDocument(final String id, final Class type, final DocumentReadOptions options) - throws ArangoDBException { + public T getDocument(final String id, final Class type, final DocumentReadOptions options) { DocumentUtil.validateDocumentId(id); final String[] split = id.split("/"); return collection(split[0]).getDocument(split[1], type, options); } @Override - public void reloadRouting() throws ArangoDBException { + public void reloadRouting() { executor.execute(reloadRoutingRequest(), Void.class); } - protected ArangoDatabaseImpl setCursorInitializer(final ArangoCursorInitializer cursorInitializer) { - this.cursorInitializer = cursorInitializer; - return this; - } - @Override - public ArangoRoute route(final String... path) { - return new ArangoRouteImpl(this, String.join("/", path), Collections.emptyMap()); - } - - @Override - public Collection getViews() throws ArangoDBException { + public Collection getViews() { return executor.execute(getViewsRequest(), getViewsResponseDeserializer()); } @@ -414,64 +380,48 @@ public ArangoSearch arangoSearch(final String name) { } @Override - public ViewEntity createView(final String name, final ViewType type) throws ArangoDBException { - return executor.execute(createViewRequest(name, type), ViewEntity.class); + public SearchAlias searchAlias(String name) { + return new SearchAliasImpl(this, name); } @Override - public ViewEntity createArangoSearch(final String name, final ArangoSearchCreateOptions options) - throws ArangoDBException { - return executor.execute(createArangoSearchRequest(name, options), ViewEntity.class); + public ViewEntity createView(final String name, final ViewType type) { + return executor.execute(createViewRequest(name, type), ViewEntity.class); } @Override - public AnalyzerEntity createAnalyzer(AnalyzerEntity options) throws ArangoDBException { - return executor.execute(createAnalyzerRequest(options), AnalyzerEntity.class); + public ViewEntity createArangoSearch(final String name, final ArangoSearchCreateOptions options) { + return executor.execute(createArangoSearchRequest(name, options), ViewEntity.class); } @Override - public SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer) throws ArangoDBException { - return executor.execute(createAnalyzerRequest(analyzer), SearchAnalyzer.class); + public ViewEntity createSearchAlias(String name, SearchAliasCreateOptions options) { + return executor.execute(createSearchAliasRequest(name, options), ViewEntity.class); } @Override - public AnalyzerEntity getAnalyzer(String name) throws ArangoDBException { - return executor.execute(getAnalyzerRequest(name), AnalyzerEntity.class); + public SearchAnalyzer createSearchAnalyzer(SearchAnalyzer analyzer) { + return executor.execute(createAnalyzerRequest(analyzer), SearchAnalyzer.class); } @Override - public SearchAnalyzer getSearchAnalyzer(String name) throws ArangoDBException { + public SearchAnalyzer getSearchAnalyzer(String name) { return executor.execute(getAnalyzerRequest(name), SearchAnalyzer.class); } @Override - public Collection getAnalyzers() throws ArangoDBException { - return executor.execute(getAnalyzersRequest(), getAnalyzersResponseDeserializer()); - } - - @Override - public Collection getSearchAnalyzers() throws ArangoDBException { + public Collection getSearchAnalyzers() { return executor.execute(getAnalyzersRequest(), getSearchAnalyzersResponseDeserializer()); } @Override - public void deleteAnalyzer(String name) throws ArangoDBException { - executor.execute(deleteAnalyzerRequest(name, null), Void.class); + public void deleteSearchAnalyzer(String name) { + deleteSearchAnalyzer(name, null); } @Override - public void deleteAnalyzer(String name, AnalyzerDeleteOptions options) throws ArangoDBException { + public void deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options) { executor.execute(deleteAnalyzerRequest(name, options), Void.class); } - @Override - public void deleteSearchAnalyzer(String name) throws ArangoDBException { - deleteAnalyzer(name); - } - - @Override - public void deleteSearchAnalyzer(String name, AnalyzerDeleteOptions options) throws ArangoDBException { - deleteAnalyzer(name, options); - } - } diff --git a/src/main/java/com/arangodb/internal/ArangoDefaults.java b/core/src/main/java/com/arangodb/internal/ArangoDefaults.java similarity index 70% rename from src/main/java/com/arangodb/internal/ArangoDefaults.java rename to core/src/main/java/com/arangodb/internal/ArangoDefaults.java index ad8f1ed36..aab635dd3 100644 --- a/src/main/java/com/arangodb/internal/ArangoDefaults.java +++ b/core/src/main/java/com/arangodb/internal/ArangoDefaults.java @@ -21,35 +21,40 @@ package com.arangodb.internal; import com.arangodb.Protocol; +import com.arangodb.config.HostDescription; import com.arangodb.entity.LoadBalancingStrategy; +import java.util.Collections; +import java.util.List; + /** * @author Mark Vollmary */ public final class ArangoDefaults { - private ArangoDefaults() { - super(); - } - public static final int INTEGER_BYTES = Integer.SIZE / Byte.SIZE; public static final int LONG_BYTES = Long.SIZE / Byte.SIZE; - - public static final String DEFAULT_HOST = "127.0.0.1"; - public static final Integer DEFAULT_PORT = 8529; - public static final Integer DEFAULT_TIMEOUT = 0; - public static final String DEFAULT_USER = "root"; - public static final Boolean DEFAULT_USE_SSL = false; public static final int CHUNK_MIN_HEADER_SIZE = INTEGER_BYTES + INTEGER_BYTES + LONG_BYTES; public static final int CHUNK_MAX_HEADER_SIZE = CHUNK_MIN_HEADER_SIZE + LONG_BYTES; - public static final int CHUNK_DEFAULT_CONTENT_SIZE = 30000; public static final int MAX_CONNECTIONS_VST_DEFAULT = 1; - public static final Integer CONNECTION_TTL_VST_DEFAULT = null; public static final int MAX_CONNECTIONS_HTTP_DEFAULT = 20; - public static final Protocol DEFAULT_NETWORK_PROTOCOL = Protocol.VST; - public static final boolean DEFAULT_ACQUIRE_HOST_LIST = false; - public static final int DEFAULT_ACQUIRE_HOST_LIST_INTERVAL = 60 * 60 * 1000; // hour + public static final int MAX_CONNECTIONS_HTTP2_DEFAULT = 1; + + // default config properties + public static final List DEFAULT_HOSTS = Collections.emptyList(); + public static final Protocol DEFAULT_PROTOCOL = Protocol.HTTP2_JSON; + public static final String DEFAULT_USER = "root"; + public static final Integer DEFAULT_TIMEOUT = 0; + public static final Boolean DEFAULT_USE_SSL = false; + public static final Boolean DEFAULT_VERIFY_HOST = true; + public static final Integer DEFAULT_CHUNK_SIZE = 30_000; + public static final Boolean DEFAULT_ACQUIRE_HOST_LIST = false; + public static final Integer DEFAULT_ACQUIRE_HOST_LIST_INTERVAL = 60 * 60 * 1000; // hour public static final LoadBalancingStrategy DEFAULT_LOAD_BALANCING_STRATEGY = LoadBalancingStrategy.NONE; - public static final int DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES = 10; + public static final Integer DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES = 10; + + private ArangoDefaults() { + super(); + } } diff --git a/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java b/core/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java similarity index 70% rename from src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java index 5c84bb556..1b593beac 100644 --- a/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java +++ b/core/src/main/java/com/arangodb/internal/ArangoEdgeCollectionImpl.java @@ -42,20 +42,21 @@ protected ArangoEdgeCollectionImpl(final ArangoGraphImpl graph, final String nam } @Override - public EdgeEntity insertEdge(final T value) throws ArangoDBException { + public EdgeEntity insertEdge(final Object value) { return executor.execute(insertEdgeRequest(value, new EdgeCreateOptions()), - insertEdgeResponseDeserializer(value)); + insertEdgeResponseDeserializer()); } @Override - public EdgeEntity insertEdge(final T value, final EdgeCreateOptions options) throws ArangoDBException { - return executor.execute(insertEdgeRequest(value, options), insertEdgeResponseDeserializer(value)); + public EdgeEntity insertEdge(final Object value, final EdgeCreateOptions options) { + return executor.execute(insertEdgeRequest(value, options), insertEdgeResponseDeserializer()); } @Override - public T getEdge(final String key, final Class type) throws ArangoDBException { + public T getEdge(final String key, final Class type) { try { - return executor.execute(getEdgeRequest(key, new GraphDocumentReadOptions()), getEdgeResponseDeserializer(type)); + return executor.execute(getEdgeRequest(key, new GraphDocumentReadOptions()), + getEdgeResponseDeserializer(type)); } catch (final ArangoDBException e) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(e.getMessage(), e); @@ -65,8 +66,7 @@ public T getEdge(final String key, final Class type) throws ArangoDBExcep } @Override - public T getEdge(final String key, final Class type, final GraphDocumentReadOptions options) - throws ArangoDBException { + public T getEdge(final String key, final Class type, final GraphDocumentReadOptions options) { try { return executor.execute(getEdgeRequest(key, options), getEdgeResponseDeserializer(type)); } catch (final ArangoDBException e) { @@ -78,36 +78,34 @@ public T getEdge(final String key, final Class type, final GraphDocumentR } @Override - public EdgeUpdateEntity replaceEdge(final String key, final T value) throws ArangoDBException { + public EdgeUpdateEntity replaceEdge(final String key, final Object value) { return executor.execute(replaceEdgeRequest(key, value, new EdgeReplaceOptions()), - replaceEdgeResponseDeserializer(value)); + replaceEdgeResponseDeserializer()); } @Override - public EdgeUpdateEntity replaceEdge(final String key, final T value, final EdgeReplaceOptions options) - throws ArangoDBException { - return executor.execute(replaceEdgeRequest(key, value, options), replaceEdgeResponseDeserializer(value)); + public EdgeUpdateEntity replaceEdge(final String key, final Object value, final EdgeReplaceOptions options) { + return executor.execute(replaceEdgeRequest(key, value, options), replaceEdgeResponseDeserializer()); } @Override - public EdgeUpdateEntity updateEdge(final String key, final T value) throws ArangoDBException { + public EdgeUpdateEntity updateEdge(final String key, final Object value) { return executor.execute(updateEdgeRequest(key, value, new EdgeUpdateOptions()), - updateEdgeResponseDeserializer(value)); + updateEdgeResponseDeserializer()); } @Override - public EdgeUpdateEntity updateEdge(final String key, final T value, final EdgeUpdateOptions options) - throws ArangoDBException { - return executor.execute(updateEdgeRequest(key, value, options), updateEdgeResponseDeserializer(value)); + public EdgeUpdateEntity updateEdge(final String key, final Object value, final EdgeUpdateOptions options) { + return executor.execute(updateEdgeRequest(key, value, options), updateEdgeResponseDeserializer()); } @Override - public void deleteEdge(final String key) throws ArangoDBException { + public void deleteEdge(final String key) { executor.execute(deleteEdgeRequest(key, new EdgeDeleteOptions()), Void.class); } @Override - public void deleteEdge(final String key, final EdgeDeleteOptions options) throws ArangoDBException { + public void deleteEdge(final String key, final EdgeDeleteOptions options) { executor.execute(deleteEdgeRequest(key, options), Void.class); } diff --git a/src/main/java/com/arangodb/internal/ArangoErrors.java b/core/src/main/java/com/arangodb/internal/ArangoErrors.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoErrors.java rename to core/src/main/java/com/arangodb/internal/ArangoErrors.java index ba2bc5f57..70a07f1bf 100644 --- a/src/main/java/com/arangodb/internal/ArangoErrors.java +++ b/core/src/main/java/com/arangodb/internal/ArangoErrors.java @@ -25,13 +25,13 @@ */ public final class ArangoErrors { - private ArangoErrors() { - super(); - } - public static final Integer ERROR_ARANGO_DATA_SOURCE_NOT_FOUND = 1203; public static final Integer ERROR_ARANGO_DATABASE_NOT_FOUND = 1228; public static final Integer ERROR_GRAPH_NOT_FOUND = 1924; public static final Integer QUEUE_TIME_VIOLATED = 21004; + private ArangoErrors() { + super(); + } + } diff --git a/src/main/java/com/arangodb/internal/ArangoExecuteable.java b/core/src/main/java/com/arangodb/internal/ArangoExecuteable.java similarity index 59% rename from src/main/java/com/arangodb/internal/ArangoExecuteable.java rename to core/src/main/java/com/arangodb/internal/ArangoExecuteable.java index dc58fe914..10fc7c87a 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecuteable.java +++ b/core/src/main/java/com/arangodb/internal/ArangoExecuteable.java @@ -20,52 +20,25 @@ package com.arangodb.internal; +import com.arangodb.ArangoSerdeAccessor; import com.arangodb.DbName; -import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.EncodeUtils; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; - -import java.util.Map.Entry; /** * @author Mark Vollmary */ -public abstract class ArangoExecuteable { +public abstract class ArangoExecuteable implements ArangoSerdeAccessor { private static final String SLASH = "/"; protected final E executor; - protected final ArangoSerializationFactory util; - protected final ArangoContext context; + protected final InternalSerde serde; - protected ArangoExecuteable(final E executor, final ArangoSerializationFactory util, final ArangoContext context) { + protected ArangoExecuteable(final E executor, final InternalSerde serde) { super(); this.executor = executor; - this.util = util; - this.context = context; - } - - protected E executor() { - return executor; - } - - public ArangoSerialization util() { - return util.get(Serializer.INTERNAL); - } - - public ArangoSerialization util(final Serializer serializer) { - return util.get(serializer); - } - - protected Request request(final DbName dbName, final RequestType requestType, final String... path) { - final Request request = new Request(dbName, requestType, createPath(path)); - for (final Entry header : context.getHeaderParam().entrySet()) { - request.putHeaderParam(header.getKey(), header.getValue()); - } - return request; + this.serde = serde; } protected static String createPath(final String... params) { @@ -85,4 +58,17 @@ protected static String createPath(final String... params) { return sb.toString(); } + protected E executor() { + return executor; + } + + @Override + public InternalSerde getSerde() { + return serde; + } + + protected InternalRequest request(final DbName dbName, final RequestType requestType, final String... path) { + return new InternalRequest(dbName, requestType, createPath(path)); + } + } diff --git a/core/src/main/java/com/arangodb/internal/ArangoExecutor.java b/core/src/main/java/com/arangodb/internal/ArangoExecutor.java new file mode 100644 index 000000000..a37f4b11c --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/ArangoExecutor.java @@ -0,0 +1,68 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.QueueTimeMetrics; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.serde.InternalSerde; + +import java.lang.reflect.Type; + +/** + * @author Mark Vollmary + */ +public abstract class ArangoExecutor { + + private final QueueTimeMetricsImpl qtMetrics; + private final InternalSerde serde; + private final String timeoutS; + + protected ArangoExecutor(final ArangoConfig config) { + super(); + qtMetrics = new QueueTimeMetricsImpl(config.getResponseQueueTimeSamples()); + serde = config.getInternalSerde(); + timeoutS = config.getTimeout() >= 1000 ? Integer.toString(config.getTimeout() / 1000) : null; + } + + protected T createResult(final Type type, final InternalResponse response) { + return serde.deserialize(response.getBody(), type); + } + + protected final void interceptResponse(InternalResponse response) { + String queueTime = response.getMeta("X-Arango-Queue-Time-Seconds"); + if (queueTime != null) { + qtMetrics.add(Double.parseDouble(queueTime)); + } + } + + protected final InternalRequest interceptRequest(InternalRequest request) { + request.putHeaderParam("x-arango-queue-time-seconds", timeoutS); + return request; + } + + public QueueTimeMetrics getQueueTimeMetrics() { + return qtMetrics; + } + + public interface ResponseDeserializer { + T deserialize(InternalResponse response); + } +} diff --git a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java b/core/src/main/java/com/arangodb/internal/ArangoExecutorSync.java similarity index 57% rename from src/main/java/com/arangodb/internal/ArangoExecutorSync.java rename to core/src/main/java/com/arangodb/internal/ArangoExecutorSync.java index 2f60d2b56..00a6ae6f7 100644 --- a/src/main/java/com/arangodb/internal/ArangoExecutorSync.java +++ b/core/src/main/java/com/arangodb/internal/ArangoExecutorSync.java @@ -22,12 +22,9 @@ import com.arangodb.ArangoDBException; import com.arangodb.entity.MetaAware; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; -import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.velocypack.exception.VPackException; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,45 +40,38 @@ public class ArangoExecutorSync extends ArangoExecutor { private final CommunicationProtocol protocol; - public ArangoExecutorSync(final CommunicationProtocol protocol, final ArangoSerializationFactory util, - final DocumentCache documentCache, final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { - super(util, documentCache, qtMetrics, timeoutMs); + public ArangoExecutorSync(final CommunicationProtocol protocol, final ArangoConfig config) { + super(config); this.protocol = protocol; } - public T execute(final Request request, final Type type) throws ArangoDBException { + public T execute(final InternalRequest request, final Type type) { return execute(request, type, null); } - public T execute(final Request request, final Type type, final HostHandle hostHandle) throws ArangoDBException { + public T execute(final InternalRequest request, final Type type, final HostHandle hostHandle) { return execute(request, response -> createResult(type, response), hostHandle); } - public T execute(final Request request, final ResponseDeserializer responseDeserializer) throws ArangoDBException { + public T execute(final InternalRequest request, final ResponseDeserializer responseDeserializer) { return execute(request, responseDeserializer, null); } public T execute( - final Request request, + final InternalRequest request, final ResponseDeserializer responseDeserializer, - final HostHandle hostHandle) throws ArangoDBException { + final HostHandle hostHandle) { - try { - - final Response response = protocol.execute(interceptRequest(request), hostHandle); - interceptResponse(response); - T deserialize = responseDeserializer.deserialize(response); - - if (deserialize instanceof MetaAware) { - LOG.debug("Response is MetaAware " + deserialize.getClass().getName()); - ((MetaAware) deserialize).setMeta(response.getMeta()); - } + final InternalResponse response = protocol.execute(interceptRequest(request), hostHandle); + interceptResponse(response); + T deserialize = responseDeserializer.deserialize(response); - return deserialize; - - } catch (final VPackException e) { - throw new ArangoDBException(e); + if (deserialize instanceof MetaAware) { + LOG.debug("Response is MetaAware {}", deserialize.getClass().getName()); + ((MetaAware) deserialize).setMeta(response.getMeta()); } + + return deserialize; } public void disconnect() { diff --git a/src/main/java/com/arangodb/internal/ArangoGraphImpl.java b/core/src/main/java/com/arangodb/internal/ArangoGraphImpl.java similarity index 82% rename from src/main/java/com/arangodb/internal/ArangoGraphImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoGraphImpl.java index c72c86fc8..adc737f36 100644 --- a/src/main/java/com/arangodb/internal/ArangoGraphImpl.java +++ b/core/src/main/java/com/arangodb/internal/ArangoGraphImpl.java @@ -42,7 +42,7 @@ protected ArangoGraphImpl(final ArangoDatabaseImpl db, final String name) { } @Override - public boolean exists() throws ArangoDBException { + public boolean exists() { try { getInfo(); return true; @@ -55,43 +55,42 @@ public boolean exists() throws ArangoDBException { } @Override - public GraphEntity create(final Collection edgeDefinitions) throws ArangoDBException { + public GraphEntity create(final Collection edgeDefinitions) { return db().createGraph(name(), edgeDefinitions); } @Override - public GraphEntity create(final Collection edgeDefinitions, final GraphCreateOptions options) - throws ArangoDBException { + public GraphEntity create(final Collection edgeDefinitions, final GraphCreateOptions options) { return db().createGraph(name(), edgeDefinitions, options); } @Override - public void drop() throws ArangoDBException { + public void drop() { executor.execute(dropRequest(), Void.class); } @Override - public void drop(final boolean dropCollections) throws ArangoDBException { + public void drop(final boolean dropCollections) { executor.execute(dropRequest(dropCollections), Void.class); } @Override - public GraphEntity getInfo() throws ArangoDBException { + public GraphEntity getInfo() { return executor.execute(getInfoRequest(), getInfoResponseDeserializer()); } @Override - public Collection getVertexCollections() throws ArangoDBException { + public Collection getVertexCollections() { return executor.execute(getVertexCollectionsRequest(), getVertexCollectionsResponseDeserializer()); } @Override - public GraphEntity addVertexCollection(final String name) throws ArangoDBException { + public GraphEntity addVertexCollection(final String name) { return addVertexCollection(name, new VertexCollectionCreateOptions()); } @Override - public GraphEntity addVertexCollection(final String name, final VertexCollectionCreateOptions options) throws ArangoDBException { + public GraphEntity addVertexCollection(final String name, final VertexCollectionCreateOptions options) { return executor.execute(addVertexCollectionRequest(name, options), addVertexCollectionResponseDeserializer()); } @@ -106,22 +105,22 @@ public ArangoEdgeCollection edgeCollection(final String name) { } @Override - public Collection getEdgeDefinitions() throws ArangoDBException { + public Collection getEdgeDefinitions() { return executor.execute(getEdgeDefinitionsRequest(), getEdgeDefinitionsDeserializer()); } @Override - public GraphEntity addEdgeDefinition(final EdgeDefinition definition) throws ArangoDBException { + public GraphEntity addEdgeDefinition(final EdgeDefinition definition) { return executor.execute(addEdgeDefinitionRequest(definition), addEdgeDefinitionResponseDeserializer()); } @Override - public GraphEntity replaceEdgeDefinition(final EdgeDefinition definition) throws ArangoDBException { + public GraphEntity replaceEdgeDefinition(final EdgeDefinition definition) { return executor.execute(replaceEdgeDefinitionRequest(definition), replaceEdgeDefinitionResponseDeserializer()); } @Override - public GraphEntity removeEdgeDefinition(final String definitionName) throws ArangoDBException { + public GraphEntity removeEdgeDefinition(final String definitionName) { return executor.execute(removeEdgeDefinitionRequest(definitionName), removeEdgeDefinitionResponseDeserializer()); } diff --git a/src/main/java/com/arangodb/internal/ArangoMetricsImpl.java b/core/src/main/java/com/arangodb/internal/ArangoMetricsImpl.java similarity index 100% rename from src/main/java/com/arangodb/internal/ArangoMetricsImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoMetricsImpl.java diff --git a/src/main/java/com/arangodb/internal/ArangoRequestParam.java b/core/src/main/java/com/arangodb/internal/ArangoRequestParam.java similarity index 90% rename from src/main/java/com/arangodb/internal/ArangoRequestParam.java rename to core/src/main/java/com/arangodb/internal/ArangoRequestParam.java index 62c9be370..16c497994 100644 --- a/src/main/java/com/arangodb/internal/ArangoRequestParam.java +++ b/core/src/main/java/com/arangodb/internal/ArangoRequestParam.java @@ -25,15 +25,15 @@ */ public final class ArangoRequestParam { - private ArangoRequestParam() { - super(); - } - public static final String SYSTEM = "_system"; public static final String DATABASE = "database"; public static final String WAIT_FOR_SYNC = "waitForSync"; - public static final String IF_NONE_MATCH = "If-None-Match"; - public static final String IF_MATCH = "If-Match"; + public static final String IF_NONE_MATCH = "if-none-match"; + public static final String IF_MATCH = "if-match"; public static final String KEEP_NULL = "keepNull"; + private ArangoRequestParam() { + super(); + } + } diff --git a/src/main/java/com/arangodb/internal/ArangoResponseField.java b/core/src/main/java/com/arangodb/internal/ArangoResponseField.java similarity index 87% rename from src/main/java/com/arangodb/internal/ArangoResponseField.java rename to core/src/main/java/com/arangodb/internal/ArangoResponseField.java index 846774a3e..0388977dc 100644 --- a/src/main/java/com/arangodb/internal/ArangoResponseField.java +++ b/core/src/main/java/com/arangodb/internal/ArangoResponseField.java @@ -25,11 +25,11 @@ */ public final class ArangoResponseField { + public static final String ERROR_FIELD_NAME = "error"; + public static final String RESULT_JSON_POINTER = "/result"; + private ArangoResponseField() { super(); } - public static final String ERROR = "error"; - public static final String RESULT = "result"; - } diff --git a/src/main/java/com/arangodb/internal/ArangoSearchImpl.java b/core/src/main/java/com/arangodb/internal/ArangoSearchImpl.java similarity index 84% rename from src/main/java/com/arangodb/internal/ArangoSearchImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoSearchImpl.java index 286a34787..87522d6ac 100644 --- a/src/main/java/com/arangodb/internal/ArangoSearchImpl.java +++ b/core/src/main/java/com/arangodb/internal/ArangoSearchImpl.java @@ -38,7 +38,7 @@ protected ArangoSearchImpl(final ArangoDatabaseImpl db, final String name) { } @Override - public boolean exists() throws ArangoDBException { + public boolean exists() { try { getInfo(); return true; @@ -51,46 +51,44 @@ public boolean exists() throws ArangoDBException { } @Override - public void drop() throws ArangoDBException { + public void drop() { executor.execute(dropRequest(), Void.class); } @Override - public synchronized ViewEntity rename(final String newName) throws ArangoDBException { + public synchronized ViewEntity rename(final String newName) { final ViewEntity result = executor.execute(renameRequest(newName), ViewEntity.class); name = result.getName(); return result; } @Override - public ViewEntity getInfo() throws ArangoDBException { + public ViewEntity getInfo() { return executor.execute(getInfoRequest(), ViewEntity.class); } @Override - public ViewEntity create() throws ArangoDBException { + public ViewEntity create() { return create(new ArangoSearchCreateOptions()); } @Override - public ViewEntity create(final ArangoSearchCreateOptions options) throws ArangoDBException { + public ViewEntity create(final ArangoSearchCreateOptions options) { return db().createArangoSearch(name(), options); } @Override - public ArangoSearchPropertiesEntity getProperties() throws ArangoDBException { + public ArangoSearchPropertiesEntity getProperties() { return executor.execute(getPropertiesRequest(), ArangoSearchPropertiesEntity.class); } @Override - public ArangoSearchPropertiesEntity updateProperties(final ArangoSearchPropertiesOptions options) - throws ArangoDBException { + public ArangoSearchPropertiesEntity updateProperties(final ArangoSearchPropertiesOptions options) { return executor.execute(updatePropertiesRequest(options), ArangoSearchPropertiesEntity.class); } @Override - public ArangoSearchPropertiesEntity replaceProperties(final ArangoSearchPropertiesOptions options) - throws ArangoDBException { + public ArangoSearchPropertiesEntity replaceProperties(final ArangoSearchPropertiesOptions options) { return executor.execute(replacePropertiesRequest(options), ArangoSearchPropertiesEntity.class); } diff --git a/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java b/core/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java similarity index 70% rename from src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java index 399ec2321..7fb752905 100644 --- a/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java +++ b/core/src/main/java/com/arangodb/internal/ArangoVertexCollectionImpl.java @@ -42,23 +42,23 @@ protected ArangoVertexCollectionImpl(final ArangoGraphImpl graph, final String n } @Override - public void drop() throws ArangoDBException { + public void drop() { executor.execute(dropRequest(), Void.class); } @Override - public VertexEntity insertVertex(final T value) throws ArangoDBException { + public VertexEntity insertVertex(final Object value) { return executor.execute(insertVertexRequest(value, new VertexCreateOptions()), - insertVertexResponseDeserializer(value)); + insertVertexResponseDeserializer()); } @Override - public VertexEntity insertVertex(final T value, final VertexCreateOptions options) throws ArangoDBException { - return executor.execute(insertVertexRequest(value, options), insertVertexResponseDeserializer(value)); + public VertexEntity insertVertex(final Object value, final VertexCreateOptions options) { + return executor.execute(insertVertexRequest(value, options), insertVertexResponseDeserializer()); } @Override - public T getVertex(final String key, final Class type) throws ArangoDBException { + public T getVertex(final String key, final Class type) { try { return executor.execute(getVertexRequest(key, new GraphDocumentReadOptions()), getVertexResponseDeserializer(type)); @@ -71,8 +71,7 @@ public T getVertex(final String key, final Class type) throws ArangoDBExc } @Override - public T getVertex(final String key, final Class type, final GraphDocumentReadOptions options) - throws ArangoDBException { + public T getVertex(final String key, final Class type, final GraphDocumentReadOptions options) { try { return executor.execute(getVertexRequest(key, options), getVertexResponseDeserializer(type)); } catch (final ArangoDBException e) { @@ -84,36 +83,34 @@ public T getVertex(final String key, final Class type, final GraphDocumen } @Override - public VertexUpdateEntity replaceVertex(final String key, final T value) throws ArangoDBException { + public VertexUpdateEntity replaceVertex(final String key, final Object value) { return executor.execute(replaceVertexRequest(key, value, new VertexReplaceOptions()), - replaceVertexResponseDeserializer(value)); + replaceVertexResponseDeserializer()); } @Override - public VertexUpdateEntity replaceVertex(final String key, final T value, final VertexReplaceOptions options) - throws ArangoDBException { - return executor.execute(replaceVertexRequest(key, value, options), replaceVertexResponseDeserializer(value)); + public VertexUpdateEntity replaceVertex(final String key, final Object value, final VertexReplaceOptions options) { + return executor.execute(replaceVertexRequest(key, value, options), replaceVertexResponseDeserializer()); } @Override - public VertexUpdateEntity updateVertex(final String key, final T value) throws ArangoDBException { + public VertexUpdateEntity updateVertex(final String key, final Object value) { return executor.execute(updateVertexRequest(key, value, new VertexUpdateOptions()), - updateVertexResponseDeserializer(value)); + updateVertexResponseDeserializer()); } @Override - public VertexUpdateEntity updateVertex(final String key, final T value, final VertexUpdateOptions options) - throws ArangoDBException { - return executor.execute(updateVertexRequest(key, value, options), updateVertexResponseDeserializer(value)); + public VertexUpdateEntity updateVertex(final String key, final Object value, final VertexUpdateOptions options) { + return executor.execute(updateVertexRequest(key, value, options), updateVertexResponseDeserializer()); } @Override - public void deleteVertex(final String key) throws ArangoDBException { + public void deleteVertex(final String key) { executor.execute(deleteVertexRequest(key, new VertexDeleteOptions()), Void.class); } @Override - public void deleteVertex(final String key, final VertexDeleteOptions options) throws ArangoDBException { + public void deleteVertex(final String key, final VertexDeleteOptions options) { executor.execute(deleteVertexRequest(key, options), Void.class); } diff --git a/src/main/java/com/arangodb/internal/ArangoViewImpl.java b/core/src/main/java/com/arangodb/internal/ArangoViewImpl.java similarity index 90% rename from src/main/java/com/arangodb/internal/ArangoViewImpl.java rename to core/src/main/java/com/arangodb/internal/ArangoViewImpl.java index 60faebd7e..a9d0d37a4 100644 --- a/src/main/java/com/arangodb/internal/ArangoViewImpl.java +++ b/core/src/main/java/com/arangodb/internal/ArangoViewImpl.java @@ -35,7 +35,7 @@ protected ArangoViewImpl(final ArangoDatabaseImpl db, final String name) { } @Override - public boolean exists() throws ArangoDBException { + public boolean exists() { try { getInfo(); return true; @@ -48,19 +48,19 @@ public boolean exists() throws ArangoDBException { } @Override - public void drop() throws ArangoDBException { + public void drop() { executor.execute(dropRequest(), Void.class); } @Override - public synchronized ViewEntity rename(final String newName) throws ArangoDBException { + public synchronized ViewEntity rename(final String newName) { final ViewEntity result = executor.execute(renameRequest(newName), ViewEntity.class); name = result.getName(); return result; } @Override - public ViewEntity getInfo() throws ArangoDBException { + public ViewEntity getInfo() { return executor.execute(getInfoRequest(), ViewEntity.class); } diff --git a/src/main/java/com/arangodb/internal/DocumentFields.java b/core/src/main/java/com/arangodb/internal/DocumentFields.java similarity index 100% rename from src/main/java/com/arangodb/internal/DocumentFields.java rename to core/src/main/java/com/arangodb/internal/DocumentFields.java index 058aa8e2f..f2b20e375 100644 --- a/src/main/java/com/arangodb/internal/DocumentFields.java +++ b/core/src/main/java/com/arangodb/internal/DocumentFields.java @@ -5,15 +5,15 @@ public final class DocumentFields { - private DocumentFields() { - } - public static final String ID = "_id"; public static final String KEY = "_key"; public static final String REV = "_rev"; public static final String FROM = "_from"; public static final String TO = "_to"; + private DocumentFields() { + } + public static List values() { return Arrays.asList(ID, KEY, REV, FROM, TO); } diff --git a/core/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/core/src/main/java/com/arangodb/internal/InternalArangoCollection.java new file mode 100644 index 000000000..90389ed3b --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -0,0 +1,608 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.ArangoDBException; +import com.arangodb.DbName; +import com.arangodb.entity.*; +import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; +import com.arangodb.internal.util.DocumentUtil; +import com.arangodb.internal.util.RequestUtils; +import com.arangodb.model.*; +import com.arangodb.util.RawData; +import com.fasterxml.jackson.databind.JsonNode; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; + +import static com.arangodb.internal.serde.SerdeUtils.constructParametricType; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +public abstract class InternalArangoCollection, D extends InternalArangoDatabase, + E extends ArangoExecutor> + extends ArangoExecuteable { + + protected static final String PATH_API_COLLECTION = "/_api/collection"; + private static final String COLLECTION = "collection"; + private static final String PATH_API_DOCUMENT = "/_api/document"; + private static final String PATH_API_INDEX = "/_api/index"; + private static final String PATH_API_IMPORT = "/_api/import"; + private static final String PATH_API_USER = "/_api/user"; + private static final String MERGE_OBJECTS = "mergeObjects"; + private static final String KEEP_NULL = "keepNull"; + private static final String IGNORE_REVS = "ignoreRevs"; + private static final String RETURN_NEW = "returnNew"; + private static final String RETURN_OLD = "returnOld"; + private static final String OVERWRITE = "overwrite"; + private static final String OVERWRITE_MODE = "overwriteMode"; + private static final String SILENT = "silent"; + + private static final String TRANSACTION_ID = "x-arango-trx-id"; + + private final D db; + protected volatile String name; + + protected InternalArangoCollection(final D db, final String name) { + super(db.executor, db.serde); + this.db = db; + this.name = name; + } + + public D db() { + return db; + } + + public String name() { + return name; + } + + protected InternalRequest insertDocumentRequest(final T value, final DocumentCreateOptions options) { + final InternalRequest request = createInsertDocumentRequest(options); + request.setBody(getSerde().serializeUserData(value)); + return request; + } + + protected InternalRequest insertDocumentsRequest(final RawData values, final DocumentCreateOptions options) { + InternalRequest request = createInsertDocumentRequest(options); + request.setBody(getSerde().serialize(values)); + return request; + } + + protected InternalRequest insertDocumentsRequest(final Collection values, final DocumentCreateOptions options) { + InternalRequest request = createInsertDocumentRequest(options); + request.setBody(getSerde().serializeCollectionUserData(values)); + return request; + } + + private InternalRequest createInsertDocumentRequest(final DocumentCreateOptions options) { + final DocumentCreateOptions params = (options != null ? options : new DocumentCreateOptions()); + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_DOCUMENT, name); + request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); + request.putQueryParam(RETURN_NEW, params.getReturnNew()); + request.putQueryParam(RETURN_OLD, params.getReturnOld()); + request.putQueryParam(SILENT, params.getSilent()); + request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? + params.getOverwriteMode().getValue() : null); + request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); + request.putQueryParam(KEEP_NULL, params.getKeepNull()); + request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); + return request; + } + + protected ResponseDeserializer>> insertDocumentsResponseDeserializer(Class userDataClass) { + return response -> { + final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); + final Collection> docs = new ArrayList<>(); + final Collection errors = new ArrayList<>(); + final Collection documentsAndErrors = new ArrayList<>(); + final JsonNode body = getSerde().parse(response.getBody()); + for (final JsonNode next : body) { + JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); + if (isError != null && isError.booleanValue()) { + final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); + errors.add(error); + documentsAndErrors.add(error); + } else { + Type type = constructParametricType(DocumentCreateEntity.class, userDataClass); + final DocumentCreateEntity doc = getSerde().deserialize(next, type); + docs.add(doc); + documentsAndErrors.add(doc); + } + } + multiDocument.setDocuments(docs); + multiDocument.setErrors(errors); + multiDocument.setDocumentsAndErrors(documentsAndErrors); + return multiDocument; + }; + } + + protected InternalRequest importDocumentsRequest(final RawData values, final DocumentImportOptions options) { + return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(getSerde().serialize(values)); + } + + protected InternalRequest importDocumentsRequest(final Collection values, final DocumentImportOptions options) { + return importDocumentsRequest(options).putQueryParam("type", ImportType.list) + .setBody(getSerde().serializeCollectionUserData(values)); + } + + protected InternalRequest importDocumentsRequest(final DocumentImportOptions options) { + final DocumentImportOptions params = options != null ? options : new DocumentImportOptions(); + return request(db.dbName(), RequestType.POST, PATH_API_IMPORT).putQueryParam(COLLECTION, name) + .putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()) + .putQueryParam("fromPrefix", params.getFromPrefix()).putQueryParam("toPrefix", params.getToPrefix()) + .putQueryParam(OVERWRITE, params.getOverwrite()).putQueryParam("onDuplicate", params.getOnDuplicate()) + .putQueryParam("complete", params.getComplete()).putQueryParam("details", params.getDetails()); + } + + protected InternalRequest getDocumentRequest(final String key, final DocumentReadOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.GET, PATH_API_DOCUMENT, + DocumentUtil.createDocumentHandle(name, key)); + final DocumentReadOptions params = (options != null ? options : new DocumentReadOptions()); + request.putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()); + request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); + request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); + if (Boolean.TRUE.equals(params.getAllowDirtyRead())) { + RequestUtils.allowDirtyRead(request); + } + return request; + } + + protected ResponseDeserializer getDocumentResponseDeserializer(final Class type) { + return response -> getSerde().deserializeUserData(response.getBody(), type); + } + + protected InternalRequest getDocumentsRequest(final Collection keys, final DocumentReadOptions options) { + final DocumentReadOptions params = (options != null ? options : new DocumentReadOptions()); + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, name) + .putQueryParam("onlyget", true) + .putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()) + .putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()).setBody(getSerde().serialize(keys)) + .putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); + if (Boolean.TRUE.equals(params.getAllowDirtyRead())) { + RequestUtils.allowDirtyRead(request); + } + return request; + } + + protected ResponseDeserializer> getDocumentsResponseDeserializer( + final Class type) { + return response -> { + final MultiDocumentEntity multiDocument = new MultiDocumentEntity<>(); + boolean potentialDirtyRead = Boolean.parseBoolean(response.getMeta("X-Arango-Potential-Dirty-Read")); + multiDocument.setPotentialDirtyRead(potentialDirtyRead); + final Collection docs = new ArrayList<>(); + final Collection errors = new ArrayList<>(); + final Collection documentsAndErrors = new ArrayList<>(); + final JsonNode body = getSerde().parse(response.getBody()); + for (final JsonNode next : body) { + JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); + if (isError != null && isError.booleanValue()) { + final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); + errors.add(error); + documentsAndErrors.add(error); + } else { + final T doc = getSerde().deserializeUserData(getSerde().serialize(next), type); + docs.add(doc); + documentsAndErrors.add(doc); + } + } + multiDocument.setDocuments(docs); + multiDocument.setErrors(errors); + multiDocument.setDocumentsAndErrors(documentsAndErrors); + return multiDocument; + }; + } + + protected InternalRequest replaceDocumentRequest( + final String key, final T value, final DocumentReplaceOptions options) { + final InternalRequest request = createReplaceDocumentRequest(options, DocumentUtil.createDocumentHandle(name, key)); + request.setBody(getSerde().serializeUserData(value)); + return request; + } + + protected InternalRequest replaceDocumentsRequest(final Collection values, final DocumentReplaceOptions options) { + final InternalRequest request = createReplaceDocumentRequest(options, name); + request.setBody(getSerde().serializeCollectionUserData(values)); + return request; + } + + protected InternalRequest replaceDocumentsRequest(final RawData values, final DocumentReplaceOptions options) { + final InternalRequest request = createReplaceDocumentRequest(options, name); + request.setBody(getSerde().serialize(values)); + return request; + } + + private InternalRequest createReplaceDocumentRequest(final DocumentReplaceOptions options, String path) { + final DocumentReplaceOptions params = (options != null ? options : new DocumentReplaceOptions()); + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, path); + request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); + request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); + request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); + request.putQueryParam(IGNORE_REVS, params.getIgnoreRevs()); + request.putQueryParam(RETURN_NEW, params.getReturnNew()); + request.putQueryParam(RETURN_OLD, params.getReturnOld()); + request.putQueryParam(SILENT, params.getSilent()); + return request; + } + + protected ResponseDeserializer>> replaceDocumentsResponseDeserializer( + final Class returnType) { + return response -> { + final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); + final Collection> docs = new ArrayList<>(); + final Collection errors = new ArrayList<>(); + final Collection documentsAndErrors = new ArrayList<>(); + final JsonNode body = getSerde().parse(response.getBody()); + for (final JsonNode next : body) { + JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); + if (isError != null && isError.booleanValue()) { + final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); + errors.add(error); + documentsAndErrors.add(error); + } else { + Type type = constructParametricType(DocumentUpdateEntity.class, returnType); + final DocumentUpdateEntity doc = getSerde().deserialize(next, type); + docs.add(doc); + documentsAndErrors.add(doc); + } + } + multiDocument.setDocuments(docs); + multiDocument.setErrors(errors); + multiDocument.setDocumentsAndErrors(documentsAndErrors); + return multiDocument; + }; + } + + protected InternalRequest updateDocumentRequest(final String key, final T value, final DocumentUpdateOptions options) { + final InternalRequest request = createUpdateDocumentRequest(options, DocumentUtil.createDocumentHandle(name, key)); + request.setBody(getSerde().serializeUserData(value)); + return request; + } + + protected InternalRequest updateDocumentsRequest(final Collection values, final DocumentUpdateOptions options) { + final InternalRequest request = createUpdateDocumentRequest(options, name); + request.setBody(getSerde().serializeCollectionUserData(values)); + return request; + } + + protected InternalRequest updateDocumentsRequest(final RawData values, final DocumentUpdateOptions options) { + final InternalRequest request = createUpdateDocumentRequest(options, name); + request.setBody(getSerde().serialize(values)); + return request; + } + + private InternalRequest createUpdateDocumentRequest(final DocumentUpdateOptions options, String path) { + final DocumentUpdateOptions params = (options != null ? options : new DocumentUpdateOptions()); + final InternalRequest request = request(db.dbName(), RequestType.PATCH, PATH_API_DOCUMENT, path); + request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); + request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); + request.putQueryParam(ArangoRequestParam.KEEP_NULL, params.getKeepNull()); + request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); + request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); + request.putQueryParam(IGNORE_REVS, params.getIgnoreRevs()); + request.putQueryParam(RETURN_NEW, params.getReturnNew()); + request.putQueryParam(RETURN_OLD, params.getReturnOld()); + request.putQueryParam(SILENT, params.getSilent()); + return request; + } + + protected ResponseDeserializer>> updateDocumentsResponseDeserializer( + final Class returnType) { + return response -> { + final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); + final Collection> docs = new ArrayList<>(); + final Collection errors = new ArrayList<>(); + final Collection documentsAndErrors = new ArrayList<>(); + final JsonNode body = getSerde().parse(response.getBody()); + for (final JsonNode next : body) { + JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); + if (isError != null && isError.booleanValue()) { + final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); + errors.add(error); + documentsAndErrors.add(error); + } else { + Type type = constructParametricType(DocumentUpdateEntity.class, returnType); + final DocumentUpdateEntity doc = getSerde().deserialize(next, type); + docs.add(doc); + documentsAndErrors.add(doc); + } + } + multiDocument.setDocuments(docs); + multiDocument.setErrors(errors); + multiDocument.setDocumentsAndErrors(documentsAndErrors); + return multiDocument; + }; + } + + protected InternalRequest deleteDocumentRequest(final String key, final DocumentDeleteOptions options) { + return createDeleteDocumentRequest(options, DocumentUtil.createDocumentHandle(name, key)); + } + + protected InternalRequest deleteDocumentsRequest(final Collection docs, final DocumentDeleteOptions options) { + final InternalRequest request = createDeleteDocumentRequest(options, name); + request.setBody(getSerde().serializeCollectionUserData(docs)); + return request; + } + + protected InternalRequest deleteDocumentsRequest(final RawData docs, final DocumentDeleteOptions options) { + final InternalRequest request = createDeleteDocumentRequest(options, name); + request.setBody(getSerde().serialize(docs)); + return request; + } + + private InternalRequest createDeleteDocumentRequest(final DocumentDeleteOptions options, String path) { + final DocumentDeleteOptions params = (options != null ? options : new DocumentDeleteOptions()); + final InternalRequest request = request(db.dbName(), RequestType.DELETE, PATH_API_DOCUMENT, path); + request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); + request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); + request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); + request.putQueryParam(RETURN_OLD, params.getReturnOld()); + request.putQueryParam(SILENT, params.getSilent()); + return request; + } + + protected ResponseDeserializer>> deleteDocumentsResponseDeserializer( + final Class userDataClass) { + return response -> { + final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); + final Collection> docs = new ArrayList<>(); + final Collection errors = new ArrayList<>(); + final Collection documentsAndErrors = new ArrayList<>(); + final JsonNode body = getSerde().parse(response.getBody()); + for (final JsonNode next : body) { + JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME); + if (isError != null && isError.booleanValue()) { + final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class); + errors.add(error); + documentsAndErrors.add(error); + } else { + Type type = constructParametricType(DocumentDeleteEntity.class, userDataClass); + final DocumentDeleteEntity doc = getSerde().deserialize(next, type); + docs.add(doc); + documentsAndErrors.add(doc); + } + } + multiDocument.setDocuments(docs); + multiDocument.setErrors(errors); + multiDocument.setDocumentsAndErrors(documentsAndErrors); + return multiDocument; + }; + } + + protected InternalRequest documentExistsRequest(final String key, final DocumentExistsOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.HEAD, PATH_API_DOCUMENT, + DocumentUtil.createDocumentHandle(name, key)); + final DocumentExistsOptions params = (options != null ? options : new DocumentExistsOptions()); + request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); + request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); + request.putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()); + return request; + } + + protected InternalRequest getIndexRequest(final String id) { + return request(db.dbName(), RequestType.GET, PATH_API_INDEX, createIndexId(id)); + } + + protected InternalRequest deleteIndexRequest(final String id) { + return request(db.dbName(), RequestType.DELETE, PATH_API_INDEX, createIndexId(id)); + } + + protected ResponseDeserializer deleteIndexResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), "/id", String.class); + } + + private String createIndexId(final String id) { + final String index; + if (id.matches(DocumentUtil.REGEX_ID)) { + index = id; + } else if (id.matches(DocumentUtil.REGEX_KEY)) { + index = name + "/" + id; + } else { + throw new ArangoDBException(String.format("index id %s is not valid.", id)); + } + return index; + } + + @Deprecated + protected InternalRequest createHashIndexRequest(final Iterable fields, final HashIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + request.putQueryParam(COLLECTION, name); + request.setBody( + getSerde().serialize(OptionsBuilder.build(options != null ? options : new HashIndexOptions(), fields))); + return request; + } + + @Deprecated + protected InternalRequest createSkiplistIndexRequest(final Iterable fields, final SkiplistIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + request.putQueryParam(COLLECTION, name); + request.setBody( + getSerde().serialize(OptionsBuilder.build(options != null ? options : new SkiplistIndexOptions(), + fields))); + return request; + } + + protected InternalRequest createPersistentIndexRequest( + final Iterable fields, final PersistentIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + request.putQueryParam(COLLECTION, name); + request.setBody(getSerde().serialize( + OptionsBuilder.build(options != null ? options : new PersistentIndexOptions(), fields))); + return request; + } + + protected InternalRequest createInvertedIndexRequest(final InvertedIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + request.putQueryParam(COLLECTION, name); + request.setBody(getSerde().serialize(options)); + return request; + } + + protected InternalRequest createGeoIndexRequest(final Iterable fields, final GeoIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + request.putQueryParam(COLLECTION, name); + request.setBody( + getSerde().serialize(OptionsBuilder.build(options != null ? options : new GeoIndexOptions(), fields))); + return request; + } + + @Deprecated + protected InternalRequest createFulltextIndexRequest(final Iterable fields, final FulltextIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + request.putQueryParam(COLLECTION, name); + request.setBody( + getSerde().serialize(OptionsBuilder.build(options != null ? options : new FulltextIndexOptions(), + fields))); + return request; + } + + protected InternalRequest createTtlIndexRequest(final Iterable fields, final TtlIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + request.putQueryParam(COLLECTION, name); + request.setBody( + getSerde().serialize(OptionsBuilder.build(options != null ? options : new TtlIndexOptions(), fields))); + return request; + } + + protected InternalRequest createZKDIndexRequest( + final Iterable fields, final ZKDIndexOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); + request.putQueryParam(COLLECTION, name); + request.setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : + new ZKDIndexOptions().fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE), fields))); + return request; + } + + protected InternalRequest getIndexesRequest() { + final InternalRequest request = request(db.dbName(), RequestType.GET, PATH_API_INDEX); + request.putQueryParam(COLLECTION, name); + return request; + } + + protected ResponseDeserializer> getIndexesResponseDeserializer() { + return response -> { + Collection indexes = new ArrayList<>(); + for (JsonNode idx : getSerde().parse(response.getBody(), "/indexes")) { + if (!"inverted".equals(idx.get("type").textValue())) { + indexes.add(getSerde().deserialize(idx, IndexEntity.class)); + } + } + return indexes; + }; + } + + protected ResponseDeserializer> getInvertedIndexesResponseDeserializer() { + return response -> { + Collection indexes = new ArrayList<>(); + for (JsonNode idx : getSerde().parse(response.getBody(), "/indexes")) { + if ("inverted".equals(idx.get("type").textValue())) { + indexes.add(getSerde().deserialize(idx, InvertedIndexEntity.class)); + } + } + return indexes; + }; + } + + protected InternalRequest truncateRequest(final CollectionTruncateOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "truncate"); + final CollectionTruncateOptions params = (options != null ? options : new CollectionTruncateOptions()); + request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); + return request; + } + + protected InternalRequest countRequest(final CollectionCountOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name, "count"); + final CollectionCountOptions params = (options != null ? options : new CollectionCountOptions()); + request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); + return request; + } + + protected InternalRequest dropRequest(final Boolean isSystem) { + return request(db.dbName(), RequestType.DELETE, PATH_API_COLLECTION, name).putQueryParam("isSystem", isSystem); + } + + protected InternalRequest getInfoRequest() { + return request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name); + } + + protected InternalRequest getPropertiesRequest() { + return request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name, "properties"); + } + + protected InternalRequest changePropertiesRequest(final CollectionPropertiesOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "properties"); + request.setBody(getSerde().serialize(options != null ? options : new CollectionPropertiesOptions())); + return request; + } + + protected InternalRequest renameRequest(final String newName) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "rename"); + request.setBody(getSerde().serialize(OptionsBuilder.build(new CollectionRenameOptions(), newName))); + return request; + } + + protected InternalRequest responsibleShardRequest(final T value) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "responsibleShard"); + request.setBody(getSerde().serializeUserData(value)); + return request; + } + + protected InternalRequest getRevisionRequest() { + return request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name, "revision"); + } + + protected InternalRequest grantAccessRequest(final String user, final Permissions permissions) { + return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, + db.dbName().get(), name).setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), + permissions))); + } + + protected InternalRequest resetAccessRequest(final String user) { + return request(DbName.SYSTEM, RequestType.DELETE, PATH_API_USER, user, ArangoRequestParam.DATABASE, + db.dbName().get(), name); + } + + protected InternalRequest getPermissionsRequest(final String user) { + return request(DbName.SYSTEM, RequestType.GET, PATH_API_USER, user, ArangoRequestParam.DATABASE, + db.dbName().get(), name); + } + + protected ResponseDeserializer getPermissionsResponseDeserialzer() { + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + Permissions.class); + } + + protected Class getCollectionContentClass(Collection c) { + if (c == null || c.isEmpty()) { + return null; + } + Object v = c.iterator().next(); + if (v == null) { + return null; + } + return v.getClass(); + } + +} diff --git a/src/main/java/com/arangodb/internal/InternalArangoDB.java b/core/src/main/java/com/arangodb/internal/InternalArangoDB.java similarity index 50% rename from src/main/java/com/arangodb/internal/InternalArangoDB.java rename to core/src/main/java/com/arangodb/internal/InternalArangoDB.java index 017ddab6b..1243fd53e 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoDB.java +++ b/core/src/main/java/com/arangodb/internal/InternalArangoDB.java @@ -21,162 +21,162 @@ package com.arangodb.internal; import com.arangodb.DbName; -import com.arangodb.entity.*; +import com.arangodb.Request; +import com.arangodb.Response; +import com.arangodb.entity.LogLevelEntity; +import com.arangodb.entity.Permissions; +import com.arangodb.entity.ServerRole; +import com.arangodb.entity.UserEntity; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; -import com.arangodb.internal.util.ArangoSerializationFactory; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.model.*; -import com.arangodb.velocypack.Type; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; -import java.util.Map.Entry; + +import static com.arangodb.internal.serde.SerdeUtils.constructListType; /** * @author Mark Vollmary * @author Heiko Kernbach */ public abstract class InternalArangoDB extends ArangoExecuteable { - - private static final String PATH_API_ADMIN_LOG = "/_admin/log"; private static final String PATH_API_ADMIN_LOG_ENTRIES = "/_admin/log/entries"; private static final String PATH_API_ADMIN_LOG_LEVEL = "/_admin/log/level"; private static final String PATH_API_ROLE = "/_admin/server/role"; private static final String PATH_API_SERVER_ID = "/_admin/server/id"; - private static final String PATH_ENDPOINTS = "/_api/cluster/endpoints"; private static final String PATH_API_USER = "/_api/user"; + private static final String PATH_API_QUERY_RULES = "/_api/query/rules"; - protected InternalArangoDB(final E executor, final ArangoSerializationFactory util, final ArangoContext context) { - super(executor, util, context); + protected InternalArangoDB(final E executor, final InternalSerde util) { + super(executor, util); } - protected Request getRoleRequest() { + protected InternalRequest getRoleRequest() { return request(DbName.SYSTEM, RequestType.GET, PATH_API_ROLE); } - protected Request getServerIdRequest() { + protected InternalRequest getServerIdRequest() { return request(DbName.SYSTEM, RequestType.GET, PATH_API_SERVER_ID); } protected ResponseDeserializer getRoleResponseDeserializer() { - return response -> util().deserialize(response.getBody().get("role"), ServerRole.class); + return response -> getSerde().deserialize(response.getBody(), "/role", ServerRole.class); } protected ResponseDeserializer getServerIdResponseDeserializer() { - return response -> util().deserialize(response.getBody().get("id"), String.class); + return response -> getSerde().deserialize(response.getBody(), "/id", String.class); } - protected Request createDatabaseRequest(final DBCreateOptions options) { - final Request request = request(DbName.SYSTEM, RequestType.POST, + protected InternalRequest createDatabaseRequest(final DBCreateOptions options) { + final InternalRequest request = request(DbName.SYSTEM, RequestType.POST, InternalArangoDatabase.PATH_API_DATABASE); - request.setBody(util().serialize(options)); + request.setBody(getSerde().serialize(options)); return request; } protected ResponseDeserializer createDatabaseResponseDeserializer() { - return response -> response.getBody().get(ArangoResponseField.RESULT).getAsBoolean(); + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + Boolean.class); } - protected Request getDatabasesRequest(final DbName dbName) { + protected InternalRequest getDatabasesRequest(final DbName dbName) { return request(dbName, RequestType.GET, InternalArangoDatabase.PATH_API_DATABASE); } protected ResponseDeserializer> getDatabaseResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { - }.getType()); - }; + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + constructListType(String.class)); } - protected Request getAccessibleDatabasesForRequest(final DbName dbName, final String user) { + protected InternalRequest getAccessibleDatabasesForRequest(final DbName dbName, final String user) { return request(dbName, RequestType.GET, PATH_API_USER, user, ArangoRequestParam.DATABASE); } protected ResponseDeserializer> getAccessibleDatabasesForResponseDeserializer() { return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); + Iterator names = + getSerde().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER).fieldNames(); final Collection dbs = new ArrayList<>(); - for (final Iterator> iterator = result.objectIterator(); iterator - .hasNext(); ) { - dbs.add(iterator.next().getKey()); + while (names.hasNext()) { + dbs.add(names.next()); } return dbs; }; } - protected Request createUserRequest( + protected InternalRequest createUserRequest( final DbName dbName, final String user, final String passwd, final UserCreateOptions options) { - final Request request; + final InternalRequest request; request = request(dbName, RequestType.POST, PATH_API_USER); request.setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new UserCreateOptions(), user, passwd))); + getSerde().serialize(OptionsBuilder.build(options != null ? options : new UserCreateOptions(), user, + passwd))); return request; } - protected Request deleteUserRequest(final DbName dbName, final String user) { + protected InternalRequest deleteUserRequest(final DbName dbName, final String user) { return request(dbName, RequestType.DELETE, PATH_API_USER, user); } - protected Request getUsersRequest(final DbName dbName) { + protected InternalRequest getUsersRequest(final DbName dbName) { return request(dbName, RequestType.GET, PATH_API_USER); } - protected Request getUserRequest(final DbName dbName, final String user) { + protected InternalRequest getUserRequest(final DbName dbName, final String user) { return request(dbName, RequestType.GET, PATH_API_USER, user); } protected ResponseDeserializer> getUsersResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { - }.getType()); - }; + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + constructListType(UserEntity.class)); } - protected Request updateUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { - final Request request; + protected InternalRequest updateUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { + final InternalRequest request; request = request(dbName, RequestType.PATCH, PATH_API_USER, user); - request.setBody(util().serialize(options != null ? options : new UserUpdateOptions())); + request.setBody(getSerde().serialize(options != null ? options : new UserUpdateOptions())); return request; } - protected Request replaceUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { - final Request request; + protected InternalRequest replaceUserRequest(final DbName dbName, final String user, final UserUpdateOptions options) { + final InternalRequest request; request = request(dbName, RequestType.PUT, PATH_API_USER, user); - request.setBody(util().serialize(options != null ? options : new UserUpdateOptions())); + request.setBody(getSerde().serialize(options != null ? options : new UserUpdateOptions())); return request; } - protected Request updateUserDefaultDatabaseAccessRequest(final String user, final Permissions permissions) { + protected InternalRequest updateUserDefaultDatabaseAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - "*").setBody(util().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + "*").setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } - protected Request updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { + protected InternalRequest updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - "*", "*").setBody(util().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + "*", "*").setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); } - protected Request getLogsRequest(final LogOptions options) { - final LogOptions params = options != null ? options : new LogOptions(); - return request(DbName.SYSTEM, RequestType.GET, PATH_API_ADMIN_LOG) - .putQueryParam(LogOptions.PROPERTY_UPTO, params.getUpto()) - .putQueryParam(LogOptions.PROPERTY_LEVEL, params.getLevel()) - .putQueryParam(LogOptions.PROPERTY_START, params.getStart()) - .putQueryParam(LogOptions.PROPERTY_SIZE, params.getSize()) - .putQueryParam(LogOptions.PROPERTY_OFFSET, params.getOffset()) - .putQueryParam(LogOptions.PROPERTY_SEARCH, params.getSearch()) - .putQueryParam(LogOptions.PROPERTY_SORT, params.getSort()); + protected InternalRequest executeRequest(final Request request) { + InternalRequest ireq = new InternalRequest(request.getDb(), RequestType.from(request.getMethod()), request.getPath()); + ireq.putHeaderParams(request.getHeaders()); + ireq.putQueryParams(request.getQueryParams()); + ireq.setBody(serde.serializeUserData(request.getBody())); + return ireq; } - protected Request getLogEntriesRequest(final LogOptions options) { + protected ResponseDeserializer> responseDeserializer(Class type) { + return response -> new Response<>( + response.getResponseCode(), + response.getMeta(), + serde.deserializeUserData(response.getBody(), type) + ); + } + + protected InternalRequest getLogEntriesRequest(final LogOptions options) { final LogOptions params = options != null ? options : new LogOptions(); return request(DbName.SYSTEM, RequestType.GET, PATH_API_ADMIN_LOG_ENTRIES) .putQueryParam(LogOptions.PROPERTY_UPTO, params.getUpto()) @@ -188,13 +188,17 @@ protected Request getLogEntriesRequest(final LogOptions options) { .putQueryParam(LogOptions.PROPERTY_SORT, params.getSort()); } - protected Request getLogLevelRequest() { + protected InternalRequest getLogLevelRequest() { return request(DbName.SYSTEM, RequestType.GET, PATH_API_ADMIN_LOG_LEVEL); } - protected Request setLogLevelRequest(final LogLevelEntity entity) { + protected InternalRequest setLogLevelRequest(final LogLevelEntity entity) { return request(DbName.SYSTEM, RequestType.PUT, PATH_API_ADMIN_LOG_LEVEL) - .setBody(util().serialize(entity)); + .setBody(getSerde().serialize(entity)); + } + + protected InternalRequest getQueryOptimizerRulesRequest() { + return request(DbName.SYSTEM, RequestType.GET, PATH_API_QUERY_RULES); } } diff --git a/core/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/core/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java new file mode 100644 index 000000000..e482e405c --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java @@ -0,0 +1,349 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.Protocol; +import com.arangodb.Request; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.HostDescription; +import com.arangodb.entity.LoadBalancingStrategy; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.*; +import com.arangodb.internal.util.HostUtils; +import com.arangodb.serde.ArangoSerde; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLContext; +import java.util.ArrayList; +import java.util.Collection; +import java.util.ServiceLoader; + + +/** + * @author Mark Vollmary + */ +public abstract class InternalArangoDBBuilder> { + private static final Logger LOG = LoggerFactory.getLogger(InternalArangoDBBuilder.class); + protected final ArangoConfig config = new ArangoConfig(); + + @SuppressWarnings("unchecked") + public T loadProperties(final ArangoConfigProperties properties) { + config.loadProperties(properties); + return (T) this; + } + + /** + * Adds a host to connect to. Multiple hosts can be added to provide fallbacks. + * + * @param host address of the host + * @param port port of the host + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T host(final String host, final int port) { + config.addHost(new HostDescription(host, port)); + return (T) this; + } + + /** + * Sets the connection and request timeout in milliseconds. + * + * @param timeout timeout in milliseconds + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T timeout(final Integer timeout) { + config.setTimeout(timeout); + return (T) this; + } + + /** + * Sets the username to use for authentication. + * + * @param user the user in the database (default: {@code root}) + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T user(final String user) { + config.setUser(user); + return (T) this; + } + + /** + * Sets the password for the user for authentication. + * + * @param password the password of the user in the database (default: {@code null}) + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T password(final String password) { + config.setPassword(password); + return (T) this; + } + + /** + * Sets the JWT for the user authentication. + * + * @param jwt token to use (default: {@code null}) + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T jwt(final String jwt) { + config.setJwt(jwt); + return (T) this; + } + + /** + * If set to {@code true} SSL will be used when connecting to an ArangoDB server. + * + * @param useSsl whether or not use SSL (default: {@code false}) + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T useSsl(final Boolean useSsl) { + config.setUseSsl(useSsl); + return (T) this; + } + + /** + * Sets the SSL context to be used when {@code true} is passed through {@link #useSsl(Boolean)}. + * + * @param sslContext SSL context to be used + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T sslContext(final SSLContext sslContext) { + config.setSslContext(sslContext); + return (T) this; + } + + /** + * Set whether hostname verification is enabled + * + * @param verifyHost {@code true} if enabled + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T verifyHost(final Boolean verifyHost) { + config.setVerifyHost(verifyHost); + return (T) this; + } + + /** + * Sets the chunk size when {@link Protocol#VST} is used. + * + * @param chunksize size of a chunk in bytes + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T chunksize(final Integer chunksize) { + config.setChunkSize(chunksize); + return (T) this; + } + + /** + * Sets the maximum number of connections the built in connection pool will open per host. + * + *

    + * Defaults: + *

    + * + *
    +     * {@link Protocol#VST} == 1
    +     * {@link Protocol#HTTP_JSON} == 20
    +     * {@link Protocol#HTTP_VPACK} == 20
    +     * 
    + * + * @param maxConnections max number of connections + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T maxConnections(final Integer maxConnections) { + config.setMaxConnections(maxConnections); + return (T) this; + } + + /** + * Set the maximum time to life of a connection. After this time the connection will be closed automatically. + * + * @param connectionTtl the maximum time to life of a connection in milliseconds + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T connectionTtl(final Long connectionTtl) { + config.setConnectionTtl(connectionTtl); + return (T) this; + } + + /** + * Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request + * every {@code keepAliveInterval} seconds, to avoid to be closed due to inactivity by the server (or by the + * external environment, eg. firewall, intermediate routers, operating system). + * + * @param keepAliveInterval interval in seconds + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T keepAliveInterval(final Integer keepAliveInterval) { + config.setKeepAliveInterval(keepAliveInterval); + return (T) this; + } + + /** + * Whether or not the driver should acquire a list of available coordinators in an ArangoDB cluster or a single + * server with active failover. In case of Active-Failover deployment set to {@code true} to enable automatic + * master discovery. + * + *

    + * The host list will be used for failover and load balancing. + *

    + * + * @param acquireHostList whether or not automatically acquire a list of available hosts (default: false) + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T acquireHostList(final Boolean acquireHostList) { + config.setAcquireHostList(acquireHostList); + return (T) this; + } + + /** + * Setting the Interval for acquireHostList + * + * @param acquireHostListInterval Interval in milliseconds + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T acquireHostListInterval(final Integer acquireHostListInterval) { + config.setAcquireHostListInterval(acquireHostListInterval); + return (T) this; + } + + /** + * Sets the load balancing strategy to be used in an ArangoDB cluster setup. In case of Active-Failover + * deployment set to {@link LoadBalancingStrategy#NONE} or not set at all, since that would be the default. + * + * @param loadBalancingStrategy the load balancing strategy to be used (default: + * {@link LoadBalancingStrategy#NONE} + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T loadBalancingStrategy(final LoadBalancingStrategy loadBalancingStrategy) { + config.setLoadBalancingStrategy(loadBalancingStrategy); + return (T) this; + } + + /** + * Setting the amount of samples kept for queue time metrics + * + * @param responseQueueTimeSamples amount of samples to keep + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T responseQueueTimeSamples(final Integer responseQueueTimeSamples) { + config.setResponseQueueTimeSamples(responseQueueTimeSamples); + return (T) this; + } + + /** + * Sets the serde for the user data. + * This is used to serialize and deserialize all the data payload such as: + * - documents, vertexes, edges + * - AQL bind vars + * - body payload of requests and responses in {@link ArangoDB#execute(Request, Class)} + *

    + * However, note that the following types will always be serialized and deserialized using the internal serde: + * - {@link com.fasterxml.jackson.databind.JsonNode} + * - {@link com.arangodb.util.RawJson} + * - {@link com.arangodb.util.RawBytes} + * - {@link com.arangodb.entity.BaseDocument} + * - {@link com.arangodb.entity.BaseEdgeDocument} + * + * @param serde custom serde for the user data + * @return {@link ArangoDB.Builder} + */ + @SuppressWarnings("unchecked") + public T serde(final ArangoSerde serde) { + config.setUserDataSerde(serde); + return (T) this; + } + + protected ProtocolProvider protocolProvider(Protocol protocol) { + ServiceLoader loader = ServiceLoader.load(ProtocolProvider.class); + for (ProtocolProvider p : loader) { + if (p.supportsProtocol(protocol)) { + return p; + } + } + throw new ArangoDBException("No ProtocolProvider found for protocol: " + protocol); + } + + protected HostHandler createHostHandler(final HostResolver hostResolver) { + + final HostHandler hostHandler; + + LoadBalancingStrategy loadBalancingStrategy = config.getLoadBalancingStrategy(); + if (loadBalancingStrategy != null) { + switch (loadBalancingStrategy) { + case ONE_RANDOM: + hostHandler = new RandomHostHandler(hostResolver, new FallbackHostHandler(hostResolver)); + break; + case ROUND_ROBIN: + hostHandler = new RoundRobinHostHandler(hostResolver); + break; + case NONE: + default: + hostHandler = new FallbackHostHandler(hostResolver); + break; + } + } else { + hostHandler = new FallbackHostHandler(hostResolver); + } + + LOG.debug("HostHandler is {}", hostHandler.getClass().getSimpleName()); + + return new DirtyReadHostHandler(hostHandler, new RoundRobinHostHandler(hostResolver)); + } + + protected HostResolver createHostResolver(final Collection hosts, final ConnectionFactory connectionFactory) { + Boolean acquireHostList = config.getAcquireHostList(); + if (acquireHostList != null && acquireHostList) { + LOG.debug("acquireHostList -> Use ExtendedHostResolver"); + return new ExtendedHostResolver(new ArrayList<>(hosts), config, connectionFactory, + config.getAcquireHostListInterval()); + } else { + LOG.debug("Use SimpleHostResolver"); + return new SimpleHostResolver(new ArrayList<>(hosts)); + } + + } + + protected Collection createHostList(final ConnectionFactory connectionFactory) { + final Collection hostList = new ArrayList<>(); + for (final HostDescription host : config.getHosts()) { + hostList.add(HostUtils.createHost(host, config, connectionFactory)); + } + return hostList; + } +} diff --git a/core/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/core/src/main/java/com/arangodb/internal/InternalArangoDatabase.java new file mode 100644 index 000000000..fcde6ad9b --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/InternalArangoDatabase.java @@ -0,0 +1,385 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.DbName; +import com.arangodb.entity.*; +import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; +import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; +import com.arangodb.internal.util.RequestUtils; +import com.arangodb.model.*; +import com.arangodb.model.arangosearch.*; + +import java.util.Collection; +import java.util.Map; + +import static com.arangodb.internal.serde.SerdeUtils.constructListType; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +public abstract class InternalArangoDatabase, EXECUTOR extends ArangoExecutor> extends ArangoExecuteable { + + protected static final String PATH_API_DATABASE = "/_api/database"; + private static final String PATH_API_VERSION = "/_api/version"; + private static final String PATH_API_ENGINE = "/_api/engine"; + private static final String PATH_API_CURSOR = "/_api/cursor"; + private static final String PATH_API_TRANSACTION = "/_api/transaction"; + private static final String PATH_API_BEGIN_STREAM_TRANSACTION = "/_api/transaction/begin"; + private static final String PATH_API_AQLFUNCTION = "/_api/aqlfunction"; + private static final String PATH_API_EXPLAIN = "/_api/explain"; + private static final String PATH_API_QUERY = "/_api/query"; + private static final String PATH_API_QUERY_CACHE = "/_api/query-cache"; + private static final String PATH_API_QUERY_CACHE_PROPERTIES = "/_api/query-cache/properties"; + private static final String PATH_API_QUERY_PROPERTIES = "/_api/query/properties"; + private static final String PATH_API_QUERY_CURRENT = "/_api/query/current"; + private static final String PATH_API_QUERY_SLOW = "/_api/query/slow"; + private static final String PATH_API_ADMIN_ROUTING_RELOAD = "/_admin/routing/reload"; + private static final String PATH_API_USER = "/_api/user"; + + private static final String TRANSACTION_ID = "x-arango-trx-id"; + + private final DbName dbName; + private final A arango; + + protected InternalArangoDatabase(final A arango, final DbName dbName) { + super(arango.executor, arango.serde); + this.arango = arango; + this.dbName = dbName; + } + + public A arango() { + return arango; + } + + public DbName dbName() { + return dbName; + } + + protected ResponseDeserializer> getDatabaseResponseDeserializer() { + return arango.getDatabaseResponseDeserializer(); + } + + protected InternalRequest getAccessibleDatabasesRequest() { + return request(dbName, RequestType.GET, PATH_API_DATABASE, "user"); + } + + protected InternalRequest getVersionRequest() { + return request(dbName, RequestType.GET, PATH_API_VERSION); + } + + protected InternalRequest getEngineRequest() { + return request(dbName, RequestType.GET, PATH_API_ENGINE); + } + + protected InternalRequest createCollectionRequest(final String name, final CollectionCreateOptions options) { + + byte[] body = getSerde().serialize(OptionsBuilder.build(options != null ? options : + new CollectionCreateOptions(), name)); + + return request(dbName, RequestType.POST, InternalArangoCollection.PATH_API_COLLECTION).setBody(body); + } + + protected InternalRequest getCollectionsRequest(final CollectionsReadOptions options) { + final InternalRequest request; + request = request(dbName, RequestType.GET, InternalArangoCollection.PATH_API_COLLECTION); + final CollectionsReadOptions params = (options != null ? options : new CollectionsReadOptions()); + request.putQueryParam("excludeSystem", params.getExcludeSystem()); + return request; + } + + protected ResponseDeserializer> getCollectionsResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + constructListType(CollectionEntity.class)); + } + + protected InternalRequest dropRequest() { + return request(DbName.SYSTEM, RequestType.DELETE, PATH_API_DATABASE, dbName.get()); + } + + protected ResponseDeserializer createDropResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + Boolean.class); + } + + protected InternalRequest grantAccessRequest(final String user, final Permissions permissions) { + return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, + dbName.get()).setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + } + + protected InternalRequest resetAccessRequest(final String user) { + return request(DbName.SYSTEM, RequestType.DELETE, PATH_API_USER, user, ArangoRequestParam.DATABASE, + dbName.get()); + } + + protected InternalRequest updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { + return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get() + , "*").setBody(getSerde().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); + } + + protected InternalRequest getPermissionsRequest(final String user) { + return request(DbName.SYSTEM, RequestType.GET, PATH_API_USER, user, ArangoRequestParam.DATABASE, dbName.get()); + } + + protected ResponseDeserializer getPermissionsResponseDeserialzer() { + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + Permissions.class); + } + + protected InternalRequest queryRequest(final String query, final Map bindVars, + final AqlQueryOptions options) { + final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); + final InternalRequest request = request(dbName, RequestType.POST, PATH_API_CURSOR) + .setBody(getSerde().serialize(OptionsBuilder.build(opt, query, bindVars))); + if (Boolean.TRUE.equals(opt.getAllowDirtyRead())) { + RequestUtils.allowDirtyRead(request); + } + request.putHeaderParam(TRANSACTION_ID, opt.getStreamTransactionId()); + return request; + } + + protected InternalRequest queryNextRequest(final String id, final AqlQueryOptions options, Map meta) { + + final InternalRequest request = request(dbName, RequestType.POST, PATH_API_CURSOR, id); + request.putHeaderParams(meta); + + final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); + + if (Boolean.TRUE.equals(opt.getAllowDirtyRead())) { + RequestUtils.allowDirtyRead(request); + } + request.putHeaderParam(TRANSACTION_ID, opt.getStreamTransactionId()); + return request; + } + + protected InternalRequest queryCloseRequest(final String id, final AqlQueryOptions options, Map meta) { + + final InternalRequest request = request(dbName, RequestType.DELETE, PATH_API_CURSOR, id); + request.putHeaderParams(meta); + + final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); + + if (Boolean.TRUE.equals(opt.getAllowDirtyRead())) { + RequestUtils.allowDirtyRead(request); + } + request.putHeaderParam(TRANSACTION_ID, opt.getStreamTransactionId()); + return request; + } + + protected InternalRequest explainQueryRequest(final String query, final Map bindVars, + final AqlQueryExplainOptions options) { + final AqlQueryExplainOptions opt = options != null ? options : new AqlQueryExplainOptions(); + return request(dbName, RequestType.POST, PATH_API_EXPLAIN) + .setBody(getSerde().serialize(OptionsBuilder.build(opt, query, bindVars))); + } + + protected InternalRequest parseQueryRequest(final String query) { + return request(dbName, RequestType.POST, PATH_API_QUERY).setBody(getSerde().serialize(OptionsBuilder.build(new AqlQueryParseOptions(), query))); + } + + protected InternalRequest clearQueryCacheRequest() { + return request(dbName, RequestType.DELETE, PATH_API_QUERY_CACHE); + } + + protected InternalRequest getQueryCachePropertiesRequest() { + return request(dbName, RequestType.GET, PATH_API_QUERY_CACHE_PROPERTIES); + } + + protected InternalRequest setQueryCachePropertiesRequest(final QueryCachePropertiesEntity properties) { + return request(dbName, RequestType.PUT, PATH_API_QUERY_CACHE_PROPERTIES).setBody(getSerde().serialize(properties)); + } + + protected InternalRequest getQueryTrackingPropertiesRequest() { + return request(dbName, RequestType.GET, PATH_API_QUERY_PROPERTIES); + } + + protected InternalRequest setQueryTrackingPropertiesRequest(final QueryTrackingPropertiesEntity properties) { + return request(dbName, RequestType.PUT, PATH_API_QUERY_PROPERTIES).setBody(getSerde().serialize(properties)); + } + + protected InternalRequest getCurrentlyRunningQueriesRequest() { + return request(dbName, RequestType.GET, PATH_API_QUERY_CURRENT); + } + + protected InternalRequest getSlowQueriesRequest() { + return request(dbName, RequestType.GET, PATH_API_QUERY_SLOW); + } + + protected InternalRequest clearSlowQueriesRequest() { + return request(dbName, RequestType.DELETE, PATH_API_QUERY_SLOW); + } + + protected InternalRequest killQueryRequest(final String id) { + return request(dbName, RequestType.DELETE, PATH_API_QUERY, id); + } + + protected InternalRequest createAqlFunctionRequest(final String name, final String code, + final AqlFunctionCreateOptions options) { + return request(dbName, RequestType.POST, PATH_API_AQLFUNCTION).setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : new AqlFunctionCreateOptions(), name, code))); + } + + protected InternalRequest deleteAqlFunctionRequest(final String name, final AqlFunctionDeleteOptions options) { + final InternalRequest request = request(dbName, RequestType.DELETE, PATH_API_AQLFUNCTION, name); + final AqlFunctionDeleteOptions params = options != null ? options : new AqlFunctionDeleteOptions(); + request.putQueryParam("group", params.getGroup()); + return request; + } + + protected ResponseDeserializer deleteAqlFunctionResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), "/deletedCount", Integer.class); + } + + protected InternalRequest getAqlFunctionsRequest(final AqlFunctionGetOptions options) { + final InternalRequest request = request(dbName, RequestType.GET, PATH_API_AQLFUNCTION); + final AqlFunctionGetOptions params = options != null ? options : new AqlFunctionGetOptions(); + request.putQueryParam("namespace", params.getNamespace()); + return request; + } + + protected ResponseDeserializer> getAqlFunctionsResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + constructListType(AqlFunctionEntity.class)); + } + + protected InternalRequest createGraphRequest(final String name, final Collection edgeDefinitions, + final GraphCreateOptions options) { + return request(dbName, RequestType.POST, InternalArangoGraph.PATH_API_GHARIAL).setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : new GraphCreateOptions(), name, edgeDefinitions))); + } + + protected ResponseDeserializer createGraphResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), "/graph", GraphEntity.class); + } + + protected InternalRequest getGraphsRequest() { + return request(dbName, RequestType.GET, InternalArangoGraph.PATH_API_GHARIAL); + } + + protected ResponseDeserializer> getGraphsResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), "/graphs", + constructListType(GraphEntity.class)); + } + + protected InternalRequest transactionRequest(final String action, final TransactionOptions options) { + return request(dbName, RequestType.POST, PATH_API_TRANSACTION).setBody(getSerde().serialize(OptionsBuilder.build(options != null ? options : new TransactionOptions(), action))); + } + + protected ResponseDeserializer transactionResponseDeserializer(final Class type) { + return response -> { + byte[] userContent = getSerde().extract(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER); + return getSerde().deserializeUserData(userContent, type); + }; + } + + protected InternalRequest beginStreamTransactionRequest(final StreamTransactionOptions options) { + StreamTransactionOptions opts = options != null ? options : new StreamTransactionOptions(); + InternalRequest r = request(dbName, RequestType.POST, PATH_API_BEGIN_STREAM_TRANSACTION).setBody(getSerde().serialize(opts)); + if(Boolean.TRUE.equals(opts.getAllowDirtyRead())) { + RequestUtils.allowDirtyRead(r); + } + return r; + } + + protected InternalRequest abortStreamTransactionRequest(String id) { + return request(dbName, RequestType.DELETE, PATH_API_TRANSACTION, id); + } + + protected InternalRequest getStreamTransactionsRequest() { + return request(dbName, RequestType.GET, PATH_API_TRANSACTION); + } + + protected InternalRequest getStreamTransactionRequest(String id) { + return request(dbName, RequestType.GET, PATH_API_TRANSACTION, id); + } + + protected ResponseDeserializer> transactionsResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), "/transactions", + constructListType(TransactionEntity.class)); + } + + protected InternalRequest commitStreamTransactionRequest(String id) { + return request(dbName, RequestType.PUT, PATH_API_TRANSACTION, id); + } + + protected ResponseDeserializer streamTransactionResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + StreamTransactionEntity.class); + } + + protected InternalRequest getInfoRequest() { + return request(dbName, RequestType.GET, PATH_API_DATABASE, "current"); + } + + protected ResponseDeserializer getInfoResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + DatabaseEntity.class); + } + + protected InternalRequest reloadRoutingRequest() { + return request(dbName, RequestType.POST, PATH_API_ADMIN_ROUTING_RELOAD); + } + + protected InternalRequest getViewsRequest() { + return request(dbName, RequestType.GET, InternalArangoView.PATH_API_VIEW); + } + + protected ResponseDeserializer> getViewsResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + constructListType(ViewEntity.class)); + } + + protected InternalRequest createViewRequest(final String name, final ViewType type) { + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getSerde().serialize(OptionsBuilder.build(new ViewCreateOptions(), name, type))); + } + + protected InternalRequest createArangoSearchRequest(final String name, final ArangoSearchCreateOptions options) { + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getSerde().serialize(ArangoSearchOptionsBuilder.build(options != null ? options : new ArangoSearchCreateOptions(), name))); + } + + protected InternalRequest createSearchAliasRequest(final String name, final SearchAliasCreateOptions options) { + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(getSerde().serialize( + SearchAliasOptionsBuilder.build(options != null ? options : new SearchAliasCreateOptions(), name))); + } + + protected InternalRequest getAnalyzerRequest(final String name) { + return request(dbName, RequestType.GET, InternalArangoView.PATH_API_ANALYZER, name); + } + + protected InternalRequest getAnalyzersRequest() { + return request(dbName, RequestType.GET, InternalArangoView.PATH_API_ANALYZER); + } + + protected ResponseDeserializer> getSearchAnalyzersResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER, + constructListType(SearchAnalyzer.class)); + } + + protected InternalRequest createAnalyzerRequest(final SearchAnalyzer options) { + return request(dbName, RequestType.POST, InternalArangoView.PATH_API_ANALYZER).setBody(getSerde().serialize(options)); + } + + protected InternalRequest deleteAnalyzerRequest(final String name, final AnalyzerDeleteOptions options) { + InternalRequest request = request(dbName, RequestType.DELETE, InternalArangoView.PATH_API_ANALYZER, name); + request.putQueryParam("force", options != null ? options.getForce() : null); + return request; + } + +} diff --git a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java b/core/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java similarity index 52% rename from src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java rename to core/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java index 44ad70837..37ee04fc1 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java +++ b/core/src/main/java/com/arangodb/internal/InternalArangoEdgeCollection.java @@ -23,34 +23,27 @@ import com.arangodb.entity.EdgeEntity; import com.arangodb.entity.EdgeUpdateEntity; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; -import com.arangodb.util.ArangoSerializer; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; - -import java.util.HashMap; -import java.util.Map; /** * @author Mark Vollmary */ -public abstract class InternalArangoEdgeCollection, D extends InternalArangoDatabase, G extends InternalArangoGraph, E extends ArangoExecutor> +public abstract class InternalArangoEdgeCollection, D extends InternalArangoDatabase, G extends InternalArangoGraph, E extends ArangoExecutor> extends ArangoExecuteable { private static final String PATH_API_GHARIAL = "/_api/gharial"; - private static final String EDGE = "edge"; - private static final String TRANSACTION_ID = "x-arango-trx-id"; + private static final String EDGE_PATH = "edge"; + private static final String EDGE_JSON_POINTER = "/edge"; private final G graph; private final String name; protected InternalArangoEdgeCollection(final G graph, final String name) { - super(graph.executor, graph.util, graph.context); + super(graph.executor, graph.serde); this.graph = graph; this.name = name; } @@ -63,95 +56,71 @@ public String name() { return name; } - protected Request insertEdgeRequest(final T value, final EdgeCreateOptions options) { - final Request request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), EDGE, + protected InternalRequest insertEdgeRequest(final T value, final EdgeCreateOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), EDGE_PATH, name); final EdgeCreateOptions params = (options != null ? options : new EdgeCreateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.setBody(util(Serializer.CUSTOM).serialize(value)); + request.setBody(getSerde().serializeUserData(value)); return request; } - protected ResponseDeserializer insertEdgeResponseDeserializer(final T value) { - return response -> { - final VPackSlice body = response.getBody().get(EDGE); - final EdgeEntity doc = util().deserialize(body, EdgeEntity.class); - final Map values = new HashMap<>(); - values.put(DocumentFields.ID, doc.getId()); - values.put(DocumentFields.KEY, doc.getKey()); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - return doc; - }; + protected ResponseDeserializer insertEdgeResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), EDGE_JSON_POINTER, EdgeEntity.class); } - protected Request getEdgeRequest(final String key, final GraphDocumentReadOptions options) { - final Request request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), EDGE, + protected InternalRequest getEdgeRequest(final String key, final GraphDocumentReadOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), EDGE_PATH, DocumentUtil.createDocumentHandle(name, key)); final GraphDocumentReadOptions params = (options != null ? options : new GraphDocumentReadOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - if (params.getAllowDirtyRead() == Boolean.TRUE) { + if (Boolean.TRUE.equals(params.getAllowDirtyRead())) { RequestUtils.allowDirtyRead(request); } return request; } protected ResponseDeserializer getEdgeResponseDeserializer(final Class type) { - return response -> util(Serializer.CUSTOM).deserialize(response.getBody().get(EDGE), type); + return response -> getSerde().deserializeUserData(getSerde().extract(response.getBody(), EDGE_JSON_POINTER), type); } - protected Request replaceEdgeRequest(final String key, final T value, final EdgeReplaceOptions options) { - final Request request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), EDGE, + protected InternalRequest replaceEdgeRequest(final String key, final T value, final EdgeReplaceOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), EDGE_PATH, DocumentUtil.createDocumentHandle(name, key)); final EdgeReplaceOptions params = (options != null ? options : new EdgeReplaceOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody(util(Serializer.CUSTOM).serialize(value)); + request.setBody(getSerde().serializeUserData(value)); return request; } - protected ResponseDeserializer replaceEdgeResponseDeserializer(final T value) { - return response -> { - final VPackSlice body = response.getBody().get(EDGE); - final EdgeUpdateEntity doc = util().deserialize(body, EdgeUpdateEntity.class); - final Map values = new HashMap<>(); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - return doc; - }; + protected ResponseDeserializer replaceEdgeResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), EDGE_JSON_POINTER, EdgeUpdateEntity.class); } - protected Request updateEdgeRequest(final String key, final T value, final EdgeUpdateOptions options) { - final Request request; - request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), EDGE, + protected InternalRequest updateEdgeRequest(final String key, final T value, final EdgeUpdateOptions options) { + final InternalRequest request; + request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), EDGE_PATH, DocumentUtil.createDocumentHandle(name, key)); final EdgeUpdateOptions params = (options != null ? options : new EdgeUpdateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.KEEP_NULL, params.getKeepNull()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody( - util(Serializer.CUSTOM).serialize(value, new ArangoSerializer.Options().serializeNullValues(true))); + request.setBody(getSerde().serializeUserData(value)); return request; } - protected ResponseDeserializer updateEdgeResponseDeserializer(final T value) { - return response -> { - final VPackSlice body = response.getBody().get(EDGE); - final EdgeUpdateEntity doc = util().deserialize(body, EdgeUpdateEntity.class); - final Map values = new HashMap<>(); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - return doc; - }; + protected ResponseDeserializer updateEdgeResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), EDGE_JSON_POINTER, EdgeUpdateEntity.class); } - protected Request deleteEdgeRequest(final String key, final EdgeDeleteOptions options) { - final Request request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), EDGE, + protected InternalRequest deleteEdgeRequest(final String key, final EdgeDeleteOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), EDGE_PATH, DocumentUtil.createDocumentHandle(name, key)); final EdgeDeleteOptions params = (options != null ? options : new EdgeDeleteOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); diff --git a/src/main/java/com/arangodb/internal/InternalArangoGraph.java b/core/src/main/java/com/arangodb/internal/InternalArangoGraph.java similarity index 59% rename from src/main/java/com/arangodb/internal/InternalArangoGraph.java rename to core/src/main/java/com/arangodb/internal/InternalArangoGraph.java index a03e090e6..975902459 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoGraph.java +++ b/core/src/main/java/com/arangodb/internal/InternalArangoGraph.java @@ -25,20 +25,20 @@ import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; import com.arangodb.model.OptionsBuilder; import com.arangodb.model.VertexCollectionCreateOptions; -import com.arangodb.velocypack.Type; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; import java.util.Collection; +import static com.arangodb.internal.serde.SerdeUtils.constructListType; + /** * @author Mark Vollmary */ -public abstract class InternalArangoGraph, D extends InternalArangoDatabase, E extends ArangoExecutor> +public abstract class InternalArangoGraph, D extends InternalArangoDatabase, + E extends ArangoExecutor> extends ArangoExecuteable { protected static final String PATH_API_GHARIAL = "/_api/gharial"; - private static final String GRAPH = "graph"; + private static final String GRAPH = "/graph"; private static final String VERTEX = "vertex"; private static final String EDGE = "edge"; @@ -46,7 +46,7 @@ public abstract class InternalArangoGraph, D exten private final String name; protected InternalArangoGraph(final D db, final String name) { - super(db.executor, db.util, db.context); + super(db.executor, db.serde); this.db = db; this.name = name; } @@ -59,19 +59,19 @@ public String name() { return name; } - protected Request dropRequest() { + protected InternalRequest dropRequest() { return dropRequest(false); } - protected Request dropRequest(final boolean dropCollections) { - final Request request = request(db.dbName(), RequestType.DELETE, PATH_API_GHARIAL, name); + protected InternalRequest dropRequest(final boolean dropCollections) { + final InternalRequest request = request(db.dbName(), RequestType.DELETE, PATH_API_GHARIAL, name); if (dropCollections) { request.putQueryParam("dropCollections", true); } return request; } - protected Request getInfoRequest() { + protected InternalRequest getInfoRequest() { return request(db.dbName(), RequestType.GET, PATH_API_GHARIAL, name); } @@ -79,18 +79,18 @@ protected ResponseDeserializer getInfoResponseDeserializer() { return addVertexCollectionResponseDeserializer(); } - protected Request getVertexCollectionsRequest() { + protected InternalRequest getVertexCollectionsRequest() { return request(db.dbName(), RequestType.GET, PATH_API_GHARIAL, name, VERTEX); } protected ResponseDeserializer> getVertexCollectionsResponseDeserializer() { - return response -> util().deserialize(response.getBody().get("collections"), new Type>() { - }.getType()); + return response -> getSerde().deserialize(response.getBody(), "/collections", + constructListType(String.class)); } - protected Request addVertexCollectionRequest(final String name, final VertexCollectionCreateOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name(), VERTEX); - request.setBody(util().serialize(OptionsBuilder.build(options, name))); + protected InternalRequest addVertexCollectionRequest(final String name, final VertexCollectionCreateOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name(), VERTEX); + request.setBody(getSerde().serialize(OptionsBuilder.build(options, name))); return request; } @@ -98,42 +98,42 @@ protected ResponseDeserializer addVertexCollectionResponseDeseriali return addEdgeDefinitionResponseDeserializer(); } - protected Request getEdgeDefinitionsRequest() { + protected InternalRequest getEdgeDefinitionsRequest() { return request(db.dbName(), RequestType.GET, PATH_API_GHARIAL, name, EDGE); } protected ResponseDeserializer> getEdgeDefinitionsDeserializer() { - return response -> util().deserialize(response.getBody().get("collections"), new Type>() { - }.getType()); + return response -> getSerde().deserialize(response.getBody(), "/collections", + constructListType(String.class)); } - protected Request addEdgeDefinitionRequest(final EdgeDefinition definition) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name, EDGE); - request.setBody(util().serialize(definition)); + protected InternalRequest addEdgeDefinitionRequest(final EdgeDefinition definition) { + final InternalRequest request = request(db.dbName(), RequestType.POST, PATH_API_GHARIAL, name, EDGE); + request.setBody(getSerde().serialize(definition)); return request; } protected ResponseDeserializer addEdgeDefinitionResponseDeserializer() { - return response -> util().deserialize(response.getBody().get(GRAPH), GraphEntity.class); + return response -> getSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); } - protected Request replaceEdgeDefinitionRequest(final EdgeDefinition definition) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_GHARIAL, name, EDGE, + protected InternalRequest replaceEdgeDefinitionRequest(final EdgeDefinition definition) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_GHARIAL, name, EDGE, definition.getCollection()); - request.setBody(util().serialize(definition)); + request.setBody(getSerde().serialize(definition)); return request; } protected ResponseDeserializer replaceEdgeDefinitionResponseDeserializer() { - return response -> util().deserialize(response.getBody().get(GRAPH), GraphEntity.class); + return response -> getSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); } - protected Request removeEdgeDefinitionRequest(final String definitionName) { + protected InternalRequest removeEdgeDefinitionRequest(final String definitionName) { return request(db.dbName(), RequestType.DELETE, PATH_API_GHARIAL, name, EDGE, definitionName); } protected ResponseDeserializer removeEdgeDefinitionResponseDeserializer() { - return response -> util().deserialize(response.getBody().get(GRAPH), GraphEntity.class); + return response -> getSerde().deserialize(response.getBody(), GRAPH, GraphEntity.class); } } diff --git a/src/main/java/com/arangodb/internal/InternalArangoRoute.java b/core/src/main/java/com/arangodb/internal/InternalArangoRoute.java similarity index 84% rename from src/main/java/com/arangodb/internal/InternalArangoRoute.java rename to core/src/main/java/com/arangodb/internal/InternalArangoRoute.java index 9c6a4171a..86ac9d047 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoRoute.java +++ b/core/src/main/java/com/arangodb/internal/InternalArangoRoute.java @@ -20,9 +20,6 @@ package com.arangodb.internal; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; - import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -30,7 +27,8 @@ /** * @author Mark Vollmary */ -public abstract class InternalArangoRoute, D extends InternalArangoDatabase, E extends ArangoExecutor> +public abstract class InternalArangoRoute, D extends InternalArangoDatabase, + E extends ArangoExecutor> extends ArangoExecuteable { protected final D db; @@ -41,7 +39,7 @@ public abstract class InternalArangoRoute, D exten protected Object body; protected InternalArangoRoute(final D db, final String path, final Map headerParam) { - super(db.executor, db.util, db.context); + super(db.executor, db.serde); this.db = db; this.path = path; this.queryParam = new HashMap<>(); @@ -65,8 +63,8 @@ public void _withBody(final Object body) { this.body = body; } - protected Request createRequest(final RequestType requestType) { - final Request request = request(db.dbName(), requestType, path); + protected InternalRequest createRequest(final RequestType requestType) { + final InternalRequest request = request(db.dbName(), requestType, path); for (final Entry param : headerParam.entrySet()) { request.putHeaderParam(param.getKey(), param.getValue()); } @@ -74,7 +72,7 @@ protected Request createRequest(final RequestType requestType) { request.putQueryParam(param.getKey(), param.getValue()); } if (body != null) { - request.setBody(util().serialize(body)); + request.setBody(getSerde().serialize(body)); } return request; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoSearch.java b/core/src/main/java/com/arangodb/internal/InternalArangoSearch.java similarity index 56% rename from src/main/java/com/arangodb/internal/InternalArangoSearch.java rename to core/src/main/java/com/arangodb/internal/InternalArangoSearch.java index dac8d35e8..fc33ccfe4 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoSearch.java +++ b/core/src/main/java/com/arangodb/internal/InternalArangoSearch.java @@ -21,32 +21,33 @@ package com.arangodb.internal; import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; /** * @author Mark Vollmary */ -public class InternalArangoSearch, D extends InternalArangoDatabase, E extends ArangoExecutor> +public class InternalArangoSearch, D extends InternalArangoDatabase, + E extends ArangoExecutor> extends InternalArangoView { + private static final String PROPERTIES_PATH = "properties"; + protected InternalArangoSearch(final D db, final String name) { super(db, name); } - protected Request getPropertiesRequest() { - return request(db.dbName(), RequestType.GET, PATH_API_VIEW, name, "properties"); + protected InternalRequest getPropertiesRequest() { + return request(db.dbName(), RequestType.GET, PATH_API_VIEW, name, PROPERTIES_PATH); } - protected Request replacePropertiesRequest(final ArangoSearchPropertiesOptions options) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "properties"); - request.setBody(util().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); + protected InternalRequest replacePropertiesRequest(final ArangoSearchPropertiesOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, PROPERTIES_PATH); + request.setBody(getSerde().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); return request; } - protected Request updatePropertiesRequest(final ArangoSearchPropertiesOptions options) { - final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, "properties"); - request.setBody(util().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); + protected InternalRequest updatePropertiesRequest(final ArangoSearchPropertiesOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, PROPERTIES_PATH); + request.setBody(getSerde().serialize(options != null ? options : new ArangoSearchPropertiesOptions())); return request; } diff --git a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java b/core/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java similarity index 52% rename from src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java rename to core/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java index 0472adbb9..204aaf532 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java +++ b/core/src/main/java/com/arangodb/internal/InternalArangoVertexCollection.java @@ -23,34 +23,27 @@ import com.arangodb.entity.VertexEntity; import com.arangodb.entity.VertexUpdateEntity; import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; import com.arangodb.internal.util.DocumentUtil; import com.arangodb.internal.util.RequestUtils; import com.arangodb.model.*; -import com.arangodb.util.ArangoSerializer; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; - -import java.util.HashMap; -import java.util.Map; /** * @author Mark Vollmary */ -public abstract class InternalArangoVertexCollection, D extends InternalArangoDatabase, G extends InternalArangoGraph, E extends ArangoExecutor> +public abstract class InternalArangoVertexCollection, + D extends InternalArangoDatabase, G extends InternalArangoGraph, E extends ArangoExecutor> extends ArangoExecuteable { private static final String PATH_API_GHARIAL = "/_api/gharial"; - private static final String VERTEX = "vertex"; - + private static final String VERTEX_PATH = "vertex"; + private static final String VERTEX_JSON_POINTER = "/vertex"; private static final String TRANSACTION_ID = "x-arango-trx-id"; private final G graph; private final String name; protected InternalArangoVertexCollection(final G graph, final String name) { - super(graph.executor, graph.util, graph.context); + super(graph.executor, graph.serde); this.graph = graph; this.name = name; } @@ -63,99 +56,76 @@ public String name() { return name; } - protected Request dropRequest() { - return request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), VERTEX, name); + protected InternalRequest dropRequest() { + return request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, name); } - protected Request insertVertexRequest(final T value, final VertexCreateOptions options) { - final Request request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), VERTEX, + protected InternalRequest insertVertexRequest(final T value, final VertexCreateOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.POST, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, name); final VertexCreateOptions params = (options != null ? options : new VertexCreateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.setBody(util(Serializer.CUSTOM).serialize(value)); + request.setBody(getSerde().serializeUserData(value)); return request; } - protected ResponseDeserializer insertVertexResponseDeserializer(final T value) { - return response -> { - final VPackSlice body = response.getBody().get(VERTEX); - final VertexEntity doc = util().deserialize(body, VertexEntity.class); - final Map values = new HashMap<>(); - values.put(DocumentFields.ID, doc.getId()); - values.put(DocumentFields.KEY, doc.getKey()); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - return doc; - }; + protected ResponseDeserializer insertVertexResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), VERTEX_JSON_POINTER, VertexEntity.class); } - protected Request getVertexRequest(final String key, final GraphDocumentReadOptions options) { - final Request request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), VERTEX, + protected InternalRequest getVertexRequest(final String key, final GraphDocumentReadOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.GET, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, DocumentUtil.createDocumentHandle(name, key)); final GraphDocumentReadOptions params = (options != null ? options : new GraphDocumentReadOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - if (params.getAllowDirtyRead() == Boolean.TRUE) { + if (Boolean.TRUE.equals(params.getAllowDirtyRead())) { RequestUtils.allowDirtyRead(request); } return request; } protected ResponseDeserializer getVertexResponseDeserializer(final Class type) { - return response -> util(Serializer.CUSTOM).deserialize(response.getBody().get(VERTEX), type); + return response -> getSerde().deserializeUserData(getSerde().extract(response.getBody(), VERTEX_JSON_POINTER), type); } - protected Request replaceVertexRequest(final String key, final T value, final VertexReplaceOptions options) { - final Request request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), VERTEX, + protected InternalRequest replaceVertexRequest(final String key, final T value, final VertexReplaceOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.PUT, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, DocumentUtil.createDocumentHandle(name, key)); final VertexReplaceOptions params = (options != null ? options : new VertexReplaceOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody(util(Serializer.CUSTOM).serialize(value)); + request.setBody(getSerde().serializeUserData(value)); return request; } - protected ResponseDeserializer replaceVertexResponseDeserializer(final T value) { - return response -> { - final VPackSlice body = response.getBody().get(VERTEX); - final VertexUpdateEntity doc = util().deserialize(body, VertexUpdateEntity.class); - final Map values = new HashMap<>(); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - return doc; - }; + protected ResponseDeserializer replaceVertexResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), VERTEX_JSON_POINTER, VertexUpdateEntity.class); } - protected Request updateVertexRequest(final String key, final T value, final VertexUpdateOptions options) { - final Request request; - request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), VERTEX, + protected InternalRequest updateVertexRequest(final String key, final T value, final VertexUpdateOptions options) { + final InternalRequest request; + request = request(graph.db().dbName(), RequestType.PATCH, PATH_API_GHARIAL, graph.name(), VERTEX_PATH, DocumentUtil.createDocumentHandle(name, key)); final VertexUpdateOptions params = (options != null ? options : new VertexUpdateOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.putQueryParam(ArangoRequestParam.KEEP_NULL, params.getKeepNull()); request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.setBody( - util(Serializer.CUSTOM).serialize(value, new ArangoSerializer.Options().serializeNullValues(true))); + request.setBody(getSerde().serializeUserData(value)); return request; } - protected ResponseDeserializer updateVertexResponseDeserializer(final T value) { - return response -> { - final VPackSlice body = response.getBody().get(VERTEX); - final VertexUpdateEntity doc = util().deserialize(body, VertexUpdateEntity.class); - final Map values = new HashMap<>(); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - return doc; - }; + protected ResponseDeserializer updateVertexResponseDeserializer() { + return response -> getSerde().deserialize(response.getBody(), VERTEX_JSON_POINTER, VertexUpdateEntity.class); } - protected Request deleteVertexRequest(final String key, final VertexDeleteOptions options) { - final Request request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), VERTEX, + protected InternalRequest deleteVertexRequest(final String key, final VertexDeleteOptions options) { + final InternalRequest request = request(graph.db().dbName(), RequestType.DELETE, PATH_API_GHARIAL, graph.name(), + VERTEX_PATH, DocumentUtil.createDocumentHandle(name, key)); final VertexDeleteOptions params = (options != null ? options : new VertexDeleteOptions()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); diff --git a/src/main/java/com/arangodb/internal/InternalArangoView.java b/core/src/main/java/com/arangodb/internal/InternalArangoView.java similarity index 74% rename from src/main/java/com/arangodb/internal/InternalArangoView.java rename to core/src/main/java/com/arangodb/internal/InternalArangoView.java index 1fa76f015..38b042695 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoView.java +++ b/core/src/main/java/com/arangodb/internal/InternalArangoView.java @@ -22,14 +22,13 @@ import com.arangodb.model.OptionsBuilder; import com.arangodb.model.ViewRenameOptions; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; /** * @author Mark Vollmary * @author Michele Rastelli */ -public abstract class InternalArangoView, D extends InternalArangoDatabase, E extends ArangoExecutor> +public abstract class InternalArangoView, D extends InternalArangoDatabase, + E extends ArangoExecutor> extends ArangoExecuteable { protected static final String PATH_API_VIEW = "/_api/view"; @@ -39,7 +38,7 @@ public abstract class InternalArangoView, D extend protected volatile String name; protected InternalArangoView(final D db, final String name) { - super(db.executor, db.util, db.context); + super(db.executor, db.serde); this.db = db; this.name = name; } @@ -52,17 +51,17 @@ public String name() { return name; } - protected Request dropRequest() { + protected InternalRequest dropRequest() { return request(db.dbName(), RequestType.DELETE, PATH_API_VIEW, name); } - protected Request renameRequest(final String newName) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "rename"); - request.setBody(util().serialize(OptionsBuilder.build(new ViewRenameOptions(), newName))); + protected InternalRequest renameRequest(final String newName) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, "rename"); + request.setBody(getSerde().serialize(OptionsBuilder.build(new ViewRenameOptions(), newName))); return request; } - protected Request getInfoRequest() { + protected InternalRequest getInfoRequest() { return request(db.dbName(), RequestType.GET, PATH_API_VIEW, name); } diff --git a/src/main/java/com/arangodb/velocystream/Request.java b/core/src/main/java/com/arangodb/internal/InternalRequest.java similarity index 52% rename from src/main/java/com/arangodb/velocystream/Request.java rename to core/src/main/java/com/arangodb/internal/InternalRequest.java index c57e22a81..912062cf0 100644 --- a/src/main/java/com/arangodb/velocystream/Request.java +++ b/core/src/main/java/com/arangodb/internal/InternalRequest.java @@ -18,43 +18,34 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.velocystream; +package com.arangodb.internal; import com.arangodb.DbName; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.annotations.Expose; +import java.util.Collections; import java.util.HashMap; +import java.util.Locale; import java.util.Map; /** * @author Mark Vollmary */ -public class Request { +public class InternalRequest { - private int version = 1; - private int type = 1; private final DbName dbName; private final RequestType requestType; - private final String request; + private final String path; private final Map queryParam; private final Map headerParam; - @Expose(serialize = false) - private VPackSlice body; - - /** - * @deprecated Use {@link #Request(DbName, RequestType, String)} instead - */ - @Deprecated - public Request(final String database, final RequestType requestType, final String path) { - this(DbName.of(database), requestType, path); - } + private int version = 1; + private int type = 1; + private byte[] body; - public Request(final DbName dbName, final RequestType requestType, final String path) { + public InternalRequest(final DbName dbName, final RequestType requestType, final String path) { super(); this.dbName = dbName; this.requestType = requestType; - this.request = path; + this.path = path; body = null; queryParam = new HashMap<>(); headerParam = new HashMap<>(); @@ -64,7 +55,7 @@ public int getVersion() { return version; } - public Request setVersion(final int version) { + public InternalRequest setVersion(final int version) { this.version = version; return this; } @@ -73,19 +64,11 @@ public int getType() { return type; } - public Request setType(final int type) { + public InternalRequest setType(final int type) { this.type = type; return this; } - /** - * @deprecated Use {@link #getDbName()} instead - */ - @Deprecated - public String getDatabase() { - return getDbName().get(); - } - public DbName getDbName() { return dbName; } @@ -94,39 +77,72 @@ public RequestType getRequestType() { return requestType; } - public String getRequest() { - return request; + public String getPath() { + return path; } public Map getQueryParam() { return queryParam; } - public Request putQueryParam(final String key, final Object value) { + public InternalRequest putQueryParam(final String key, final Object value) { if (value != null) { queryParam.put(key, value.toString()); } return this; } + public InternalRequest putQueryParams(final Map params) { + if (params != null) { + for (Map.Entry it : params.entrySet()) { + putQueryParam(it.getKey(), it.getValue()); + } + } + return this; + } + public Map getHeaderParam() { - return headerParam; + return Collections.unmodifiableMap(headerParam); } - public Request putHeaderParam(final String key, final String value) { + public boolean containsHeaderParam(final String key) { + return headerParam.containsKey(key.toLowerCase(Locale.ROOT)); + } + + public InternalRequest putHeaderParam(final String key, final String value) { if (value != null) { - headerParam.put(key, value); + headerParam.put(key.toLowerCase(Locale.ROOT), value); + } + return this; + } + + public InternalRequest putHeaderParams(final Map params) { + if (params != null) { + for (Map.Entry it : params.entrySet()) { + putHeaderParam(it.getKey(), it.getValue()); + } } return this; } - public VPackSlice getBody() { + public byte[] getBody() { return body; } - public Request setBody(final VPackSlice body) { + public InternalRequest setBody(final byte[] body) { this.body = body; return this; } + @Override + public String toString() { + return "{" + + "requestType=" + requestType + + ", database='" + dbName + '\'' + + ", url='" + path + '\'' + + ", parameters=" + queryParam + + ", headers=" + headerParam + + '}'; + } + } diff --git a/src/main/java/com/arangodb/velocystream/Response.java b/core/src/main/java/com/arangodb/internal/InternalResponse.java similarity index 58% rename from src/main/java/com/arangodb/velocystream/Response.java rename to core/src/main/java/com/arangodb/internal/InternalResponse.java index 9e3811793..3e0ba6bbb 100644 --- a/src/main/java/com/arangodb/velocystream/Response.java +++ b/core/src/main/java/com/arangodb/internal/InternalResponse.java @@ -1,86 +1,105 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.velocystream; - -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.annotations.Expose; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class Response { - - private int version = 1; - private int type = 2; - private int responseCode; - private Map meta; - @Expose(deserialize = false) - private VPackSlice body = null; - - public Response() { - super(); - meta = new HashMap<>(); - } - - public int getVersion() { - return version; - } - - public void setVersion(final int version) { - this.version = version; - } - - public int getType() { - return type; - } - - public void setType(final int type) { - this.type = type; - } - - public int getResponseCode() { - return responseCode; - } - - public void setResponseCode(final int responseCode) { - this.responseCode = responseCode; - } - - public Map getMeta() { - return meta; - } - - public void setMeta(final Map meta) { - this.meta = meta; - } - - public VPackSlice getBody() { - return body; - } - - public void setBody(final VPackSlice body) { - this.body = body; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** + * @author Mark Vollmary + */ +public class InternalResponse { + + private int version = 1; + private int type = 2; + private int responseCode; + private final Map meta; + private byte[] body = null; + + public InternalResponse() { + super(); + meta = new HashMap<>(); + } + + public int getVersion() { + return version; + } + + public void setVersion(final int version) { + this.version = version; + } + + public int getType() { + return type; + } + + public void setType(final int type) { + this.type = type; + } + + public int getResponseCode() { + return responseCode; + } + + public void setResponseCode(final int responseCode) { + this.responseCode = responseCode; + } + + public Map getMeta() { + return Collections.unmodifiableMap(meta); + } + + public String getMeta(final String key) { + return meta.get(key.toLowerCase(Locale.ROOT)); + } + + public boolean containsMeta(final String key) { + return meta.containsKey(key.toLowerCase(Locale.ROOT)); + } + + public void putMeta(final String key, final String value) { + this.meta.put(key.toLowerCase(Locale.ROOT), value); + } + + public void putMetas(final Map meta) { + for (Map.Entry it : meta.entrySet()) { + putMeta(it.getKey(), it.getValue()); + } + } + + public byte[] getBody() { + return body; + } + + public void setBody(final byte[] body) { + this.body = body; + } + + @Override + public String toString() { + return "{" + + "statusCode=" + responseCode + + ", headers=" + meta + + '}'; + } +} diff --git a/core/src/main/java/com/arangodb/internal/InternalSearchAlias.java b/core/src/main/java/com/arangodb/internal/InternalSearchAlias.java new file mode 100644 index 000000000..97abc1745 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/InternalSearchAlias.java @@ -0,0 +1,50 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.model.arangosearch.SearchAliasPropertiesOptions; + +public class InternalSearchAlias, D extends InternalArangoDatabase, E extends ArangoExecutor> + extends InternalArangoView { + + private static final String PROPERTIES_PATH = "properties"; + + protected InternalSearchAlias(final D db, final String name) { + super(db, name); + } + + protected InternalRequest getPropertiesRequest() { + return request(db.dbName(), RequestType.GET, PATH_API_VIEW, name, PROPERTIES_PATH); + } + + protected InternalRequest replacePropertiesRequest(final SearchAliasPropertiesOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.PUT, PATH_API_VIEW, name, PROPERTIES_PATH); + request.setBody(getSerde().serialize(options != null ? options : new SearchAliasPropertiesOptions())); + return request; + } + + protected InternalRequest updatePropertiesRequest(final SearchAliasPropertiesOptions options) { + final InternalRequest request = request(db.dbName(), RequestType.PATCH, PATH_API_VIEW, name, PROPERTIES_PATH); + request.setBody(getSerde().serialize(options != null ? options : new SearchAliasPropertiesOptions())); + return request; + } + +} diff --git a/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java b/core/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java similarity index 99% rename from src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java rename to core/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java index 42abe46e9..c3ac91a19 100644 --- a/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java +++ b/core/src/main/java/com/arangodb/internal/QueueTimeMetricsImpl.java @@ -59,17 +59,14 @@ void clear() { private static class CircularFifoQueue { private final QueueTimeSample[] elements; - - /** - * Array index of the oldest queue element. - */ - private int start; - /** * Capacity of the queue. */ private final int size; - + /** + * Array index of the oldest queue element. + */ + private int start; /** * Amount of elements in the queue. */ diff --git a/src/main/java/com/arangodb/velocystream/RequestType.java b/core/src/main/java/com/arangodb/internal/RequestType.java similarity index 64% rename from src/main/java/com/arangodb/velocystream/RequestType.java rename to core/src/main/java/com/arangodb/internal/RequestType.java index f9f18192f..5b9d27aae 100644 --- a/src/main/java/com/arangodb/velocystream/RequestType.java +++ b/core/src/main/java/com/arangodb/internal/RequestType.java @@ -1,58 +1,72 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.velocystream; - -/** - * @author Mark Vollmary - */ -public enum RequestType { - - DELETE(0), - GET(1), - POST(2), - PUT(3), - HEAD(4), - PATCH(5), - OPTIONS(6), - VSTREAM_CRED(7), - VSTREAM_REGISTER(8), - VSTREAM_STATUS(9), - ILLEGAL(10); - - private final int type; - - RequestType(final int type) { - this.type = type; - } - - public int getType() { - return type; - } - - public static RequestType fromType(final int type) { - for (final RequestType rType : RequestType.values()) { - if (rType.type == type) { - return rType; - } - } - return null; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.Request; + +/** + * @author Mark Vollmary + */ +public enum RequestType { + + DELETE(0), + GET(1), + POST(2), + PUT(3), + HEAD(4), + PATCH(5), + OPTIONS(6), + VSTREAM_CRED(7), + VSTREAM_REGISTER(8), + VSTREAM_STATUS(9), + ILLEGAL(10); + + private final int type; + + RequestType(final int type) { + this.type = type; + } + + public static RequestType from(final Request.Method method) { + switch (method) { + case DELETE: + return DELETE; + case GET: + return GET; + case POST: + return POST; + case PUT: + return PUT; + case HEAD: + return HEAD; + case PATCH: + return PATCH; + case OPTIONS: + return OPTIONS; + default: + throw new IllegalArgumentException(); + } + } + + public int getType() { + return type; + } +} diff --git a/core/src/main/java/com/arangodb/internal/SearchAliasImpl.java b/core/src/main/java/com/arangodb/internal/SearchAliasImpl.java new file mode 100644 index 000000000..adb278bf0 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/SearchAliasImpl.java @@ -0,0 +1,95 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal; + +import com.arangodb.ArangoDBException; +import com.arangodb.SearchAlias; +import com.arangodb.entity.ViewEntity; +import com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity; +import com.arangodb.model.arangosearch.SearchAliasCreateOptions; +import com.arangodb.model.arangosearch.SearchAliasPropertiesOptions; + +/** + * @author Michele Rastelli + */ +public class SearchAliasImpl extends InternalSearchAlias + implements SearchAlias { + + protected SearchAliasImpl(final ArangoDatabaseImpl db, final String name) { + super(db, name); + } + + @Override + public boolean exists() { + try { + getInfo(); + return true; + } catch (final ArangoDBException e) { + if (ArangoErrors.ERROR_ARANGO_DATA_SOURCE_NOT_FOUND.equals(e.getErrorNum())) { + return false; + } + throw e; + } + } + + @Override + public void drop() { + executor.execute(dropRequest(), Void.class); + } + + @Override + public synchronized ViewEntity rename(final String newName) { + final ViewEntity result = executor.execute(renameRequest(newName), ViewEntity.class); + name = result.getName(); + return result; + } + + @Override + public ViewEntity getInfo() { + return executor.execute(getInfoRequest(), ViewEntity.class); + } + + @Override + public ViewEntity create() { + return create(new SearchAliasCreateOptions()); + } + + @Override + public ViewEntity create(final SearchAliasCreateOptions options) { + return db().createSearchAlias(name(), options); + } + + @Override + public SearchAliasPropertiesEntity getProperties() { + return executor.execute(getPropertiesRequest(), SearchAliasPropertiesEntity.class); + } + + @Override + public SearchAliasPropertiesEntity updateProperties(final SearchAliasPropertiesOptions options) { + return executor.execute(updatePropertiesRequest(options), SearchAliasPropertiesEntity.class); + } + + @Override + public SearchAliasPropertiesEntity replaceProperties(final SearchAliasPropertiesOptions options) { + return executor.execute(replacePropertiesRequest(options), SearchAliasPropertiesEntity.class); + } + +} diff --git a/core/src/main/java/com/arangodb/internal/config/ArangoConfig.java b/core/src/main/java/com/arangodb/internal/config/ArangoConfig.java new file mode 100644 index 000000000..987200ad6 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/config/ArangoConfig.java @@ -0,0 +1,275 @@ +package com.arangodb.internal.config; + +import com.arangodb.ArangoDBException; +import com.arangodb.Protocol; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.HostDescription; +import com.arangodb.entity.LoadBalancingStrategy; +import com.arangodb.internal.ArangoDefaults; +import com.arangodb.internal.serde.ContentTypeFactory; +import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerdeProvider; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.ArangoSerdeProvider; +import com.fasterxml.jackson.databind.Module; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLContext; +import java.util.*; +import java.util.stream.Collectors; + +public class ArangoConfig { + private final List hosts = new ArrayList<>(); + private Protocol protocol; + private Integer timeout; + private String user; + private String password; + private String jwt; + private Boolean useSsl; + private SSLContext sslContext; + private Boolean verifyHost; + private Integer chunkSize; + private Integer maxConnections; + private Long connectionTtl; + private Integer keepAliveInterval; + private Boolean acquireHostList; + private Integer acquireHostListInterval; + private LoadBalancingStrategy loadBalancingStrategy; + private InternalSerde internalSerde; + private ArangoSerde userDataSerde; + private Integer responseQueueTimeSamples; + private Module protocolModule; + + private static final Logger LOG = LoggerFactory.getLogger(ArangoConfig.class); + + private static ArangoSerdeProvider serdeProvider() { + ServiceLoader loader = ServiceLoader.load(ArangoSerdeProvider.class); + Iterator it = loader.iterator(); + ArangoSerdeProvider serdeProvider; + if (!it.hasNext()) { + LOG.warn("No ArangoSerdeProvider found, using InternalSerdeProvider. Please consider registering a custom " + + "ArangoSerdeProvider to avoid depending on internal classes which are not part of the public API."); + serdeProvider = new InternalSerdeProvider(); + } else { + serdeProvider = it.next(); + if (it.hasNext()) { + throw new ArangoDBException("Found multiple serde providers! Please set explicitly the one to use."); + } + } + return serdeProvider; + } + + public ArangoConfig() { + // load default properties + loadProperties(new ArangoConfigProperties() { + }); + } + + public void loadProperties(final ArangoConfigProperties properties) { + hosts.addAll(properties.getHosts().orElse(ArangoDefaults.DEFAULT_HOSTS).stream() + .map(it -> new HostDescription(it.getHost(), it.getPort())) + .collect(Collectors.toList())); + protocol = properties.getProtocol().orElse(ArangoDefaults.DEFAULT_PROTOCOL); + timeout = properties.getTimeout().orElse(ArangoDefaults.DEFAULT_TIMEOUT); + user = properties.getUser().orElse(ArangoDefaults.DEFAULT_USER); + // FIXME: make password field Optional + password = properties.getPassword().orElse(null); + // FIXME: make jwt field Optional + jwt = properties.getJwt().orElse(null); + useSsl = properties.getUseSsl().orElse(ArangoDefaults.DEFAULT_USE_SSL); + verifyHost = properties.getVerifyHost().orElse(ArangoDefaults.DEFAULT_VERIFY_HOST); + chunkSize = properties.getChunkSize().orElse(ArangoDefaults.DEFAULT_CHUNK_SIZE); + // FIXME: make maxConnections field Optional + maxConnections = properties.getMaxConnections().orElse(null); + // FIXME: make connectionTtl field Optional + connectionTtl = properties.getConnectionTtl().orElse(null); + // FIXME: make keepAliveInterval field Optional + keepAliveInterval = properties.getKeepAliveInterval().orElse(null); + acquireHostList = properties.getAcquireHostList().orElse(ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST); + acquireHostListInterval = properties.getAcquireHostListInterval().orElse(ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST_INTERVAL); + loadBalancingStrategy = properties.getLoadBalancingStrategy().orElse(ArangoDefaults.DEFAULT_LOAD_BALANCING_STRATEGY); + responseQueueTimeSamples = properties.getResponseQueueTimeSamples().orElse(ArangoDefaults.DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES); + } + + public List getHosts() { + return hosts; + } + + public void addHost(HostDescription hostDescription) { + hosts.add(hostDescription); + } + + public Protocol getProtocol() { + return protocol; + } + + public void setProtocol(Protocol protocol) { + this.protocol = protocol; + } + + public Integer getTimeout() { + return timeout; + } + + public void setTimeout(Integer timeout) { + this.timeout = timeout; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getJwt() { + return jwt; + } + + public void setJwt(String jwt) { + this.jwt = jwt; + } + + public Boolean getUseSsl() { + return useSsl; + } + + public void setUseSsl(Boolean useSsl) { + this.useSsl = useSsl; + } + + public SSLContext getSslContext() { + return sslContext; + } + + public void setSslContext(SSLContext sslContext) { + this.sslContext = sslContext; + } + + public Boolean getVerifyHost() { + return verifyHost; + } + + public void setVerifyHost(Boolean verifyHost) { + this.verifyHost = verifyHost; + } + + public Integer getChunkSize() { + return chunkSize; + } + + public void setChunkSize(Integer chunkSize) { + this.chunkSize = chunkSize; + } + + public Integer getMaxConnections() { + if (maxConnections == null) { + maxConnections = getDefaultMaxConnections(); + } + return maxConnections; + } + + private int getDefaultMaxConnections() { + int defaultMaxConnections; + switch (getProtocol()) { + case VST: + defaultMaxConnections = ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT; + break; + case HTTP_JSON: + case HTTP_VPACK: + defaultMaxConnections = ArangoDefaults.MAX_CONNECTIONS_HTTP_DEFAULT; + break; + case HTTP2_JSON: + case HTTP2_VPACK: + defaultMaxConnections = ArangoDefaults.MAX_CONNECTIONS_HTTP2_DEFAULT; + break; + default: + throw new IllegalArgumentException(); + } + return defaultMaxConnections; + } + + public void setMaxConnections(Integer maxConnections) { + this.maxConnections = maxConnections; + } + + public Long getConnectionTtl() { + return connectionTtl; + } + + public void setConnectionTtl(Long connectionTtl) { + this.connectionTtl = connectionTtl; + } + + public Integer getKeepAliveInterval() { + return keepAliveInterval; + } + + public void setKeepAliveInterval(Integer keepAliveInterval) { + this.keepAliveInterval = keepAliveInterval; + } + + public Boolean getAcquireHostList() { + return acquireHostList; + } + + public void setAcquireHostList(Boolean acquireHostList) { + this.acquireHostList = acquireHostList; + } + + public Integer getAcquireHostListInterval() { + return acquireHostListInterval; + } + + public void setAcquireHostListInterval(Integer acquireHostListInterval) { + this.acquireHostListInterval = acquireHostListInterval; + } + + public LoadBalancingStrategy getLoadBalancingStrategy() { + return loadBalancingStrategy; + } + + public void setLoadBalancingStrategy(LoadBalancingStrategy loadBalancingStrategy) { + this.loadBalancingStrategy = loadBalancingStrategy; + } + + public ArangoSerde getUserDataSerde() { + if (userDataSerde == null) { + userDataSerde = serdeProvider().of(ContentTypeFactory.of(getProtocol())); + } + return userDataSerde; + } + + public InternalSerde getInternalSerde() { + if (internalSerde == null) { + internalSerde = InternalSerdeProvider.create(ContentTypeFactory.of(getProtocol()), getUserDataSerde(), protocolModule); + } + return internalSerde; + } + + public void setUserDataSerde(ArangoSerde userDataSerde) { + this.userDataSerde = userDataSerde; + } + + public Integer getResponseQueueTimeSamples() { + return responseQueueTimeSamples; + } + + public void setResponseQueueTimeSamples(Integer responseQueueTimeSamples) { + this.responseQueueTimeSamples = responseQueueTimeSamples; + } + + public void setProtocolModule(Module m) { + protocolModule = m; + } +} diff --git a/core/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java b/core/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java new file mode 100644 index 000000000..7484c6e23 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/config/ArangoConfigPropertiesImpl.java @@ -0,0 +1,148 @@ +package com.arangodb.internal.config; + +import com.arangodb.ArangoDBException; +import com.arangodb.Protocol; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.HostDescription; +import com.arangodb.entity.LoadBalancingStrategy; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Properties; + +/** + * ArangoConfigProperties implementation that reads configuration entries from local file. Properties path prefix can be + * configured, so that it is possible to distinguish configurations for multiple driver instances in the same file. + */ +public final class ArangoConfigPropertiesImpl implements ArangoConfigProperties { + private static final String DEFAULT_PREFIX = "arangodb"; + private static final String DEFAULT_PROPERTY_FILE = "arangodb.properties"; + private final Properties properties; + private final String prefix; + + public ArangoConfigPropertiesImpl() { + this(DEFAULT_PROPERTY_FILE, DEFAULT_PREFIX); + } + + public ArangoConfigPropertiesImpl(final String fileName) { + this(fileName, DEFAULT_PREFIX); + } + + public ArangoConfigPropertiesImpl(final String fileName, final String prefix) { + properties = initProperties(fileName); + this.prefix = initPrefix(prefix); + } + + private String initPrefix(String p) { + if (p == null) { + return ""; + } else { + return p + "."; + } + } + + private Properties initProperties(String fileName) { + Properties p = new Properties(); + try (InputStream is = getClass().getClassLoader().getResourceAsStream(fileName)) { + p.load(is); + } catch (Exception e) { + throw new ArangoDBException("Got exception while reading properties file " + fileName, e); + } + return p; + } + + private String getProperty(String key) { + return properties.getProperty(prefix + key); + } + + @Override + public Optional> getHosts() { + return Optional.ofNullable(getProperty("hosts")) + .map(s -> { + List hostDescriptions = new ArrayList<>(); + String[] hosts = s.split(","); + for (String host : hosts) { + hostDescriptions.add(HostDescription.parse(host)); + } + return hostDescriptions; + }); + } + + @Override + public Optional getProtocol() { + return Optional.ofNullable(getProperty("protocol")).map(Protocol::valueOf); + } + + @Override + public Optional getUser() { + return Optional.ofNullable(getProperty("user")); + } + + @Override + public Optional getPassword() { + return Optional.ofNullable(getProperty("password")); + } + + @Override + public Optional getJwt() { + return Optional.ofNullable(getProperty("jwt")); + } + + @Override + public Optional getTimeout() { + return Optional.ofNullable(getProperty("timeout")).map(Integer::valueOf); + } + + @Override + public Optional getUseSsl() { + return Optional.ofNullable(getProperty("useSsl")).map(Boolean::valueOf); + } + + @Override + public Optional getVerifyHost() { + return Optional.ofNullable(getProperty("verifyHost")).map(Boolean::valueOf); + } + + @Override + public Optional getChunkSize() { + return Optional.ofNullable(getProperty("chunkSize")).map(Integer::valueOf); + } + + @Override + public Optional getMaxConnections() { + return Optional.ofNullable(getProperty("maxConnections")).map(Integer::valueOf); + } + + @Override + public Optional getConnectionTtl() { + return Optional.ofNullable(getProperty("connectionTtl")).map(Long::valueOf); + } + + @Override + public Optional getKeepAliveInterval() { + return Optional.ofNullable(getProperty("keepAliveInterval")).map(Integer::valueOf); + } + + @Override + public Optional getAcquireHostList() { + return Optional.ofNullable(getProperty("acquireHostList")).map(Boolean::valueOf); + } + + @Override + public Optional getAcquireHostListInterval() { + return Optional.ofNullable(getProperty("acquireHostListInterval")).map(Integer::valueOf); + } + + @Override + public Optional getLoadBalancingStrategy() { + return Optional.ofNullable(getProperty("loadBalancingStrategy")).map(LoadBalancingStrategy::valueOf); + } + + @Override + public Optional getResponseQueueTimeSamples() { + return Optional.ofNullable(getProperty("responseQueueTimeSamples")).map(Integer::valueOf); + } + +} diff --git a/src/main/java/com/arangodb/Function.java b/core/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java similarity index 68% rename from src/main/java/com/arangodb/Function.java rename to core/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java index b0af90c5b..958446e67 100644 --- a/src/main/java/com/arangodb/Function.java +++ b/core/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java @@ -18,21 +18,21 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb; +package com.arangodb.internal.cursor; + +import com.arangodb.ArangoIterable; + +import java.util.stream.Stream; +import java.util.stream.StreamSupport; /** - * @param the type of the input to the function - * @param the type of the result of the function * @author Mark Vollmary */ -public interface Function { +public abstract class AbstractArangoIterable implements ArangoIterable { - /** - * Applies this function to the given argument. - * - * @param t the function argument - * @return the function result - */ - R apply(T t); + @Override + public Stream stream() { + return StreamSupport.stream(spliterator(), false); + } } diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java b/core/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java similarity index 81% rename from src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java rename to core/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java index 228989657..2dfdbd194 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java +++ b/core/src/main/java/com/arangodb/internal/cursor/ArangoCursorImpl.java @@ -22,13 +22,12 @@ import com.arangodb.ArangoCursor; import com.arangodb.ArangoIterator; -import com.arangodb.Consumer; -import com.arangodb.entity.CursorEntity; -import com.arangodb.entity.CursorEntity.Extras; -import com.arangodb.entity.CursorEntity.Stats; -import com.arangodb.entity.CursorEntity.Warning; +import com.arangodb.entity.CursorStats; +import com.arangodb.entity.CursorWarning; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; +import com.arangodb.internal.cursor.entity.InternalCursorEntity.Extras; import java.util.ArrayList; import java.util.Collection; @@ -39,25 +38,27 @@ */ public class ArangoCursorImpl extends AbstractArangoIterable implements ArangoCursor { - private final Class type; protected final ArangoCursorIterator iterator; + private final Class type; private final String id; private final ArangoCursorExecute execute; + private final boolean isPontentialDirtyRead; public ArangoCursorImpl(final InternalArangoDatabase db, final ArangoCursorExecute execute, - final Class type, final CursorEntity result) { + final Class type, final InternalCursorEntity result) { super(); this.execute = execute; this.type = type; iterator = createIterator(this, db, execute, result); id = result.getId(); + this.isPontentialDirtyRead = Boolean.parseBoolean(result.getMeta().get("x-arango-potential-dirty-read")); } protected ArangoCursorIterator createIterator( final ArangoCursor cursor, final InternalArangoDatabase db, final ArangoCursorExecute execute, - final CursorEntity result) { + final InternalCursorEntity result) { return new ArangoCursorIterator<>(cursor, execute, db, result); } @@ -77,13 +78,13 @@ public Integer getCount() { } @Override - public Stats getStats() { + public CursorStats getStats() { final Extras extra = iterator.getResult().getExtra(); return extra != null ? extra.getStats() : null; } @Override - public Collection getWarnings() { + public Collection getWarnings() { final Extras extra = iterator.getResult().getExtra(); return extra != null ? extra.getWarnings() : null; } @@ -91,7 +92,7 @@ public Collection getWarnings() { @Override public boolean isCached() { final Boolean cached = iterator.getResult().getCached(); - return Boolean.TRUE == cached; + return Boolean.TRUE.equals(cached); } @Override @@ -120,6 +121,11 @@ public List asListRemaining() { return remaining; } + @Override + public boolean isPotentialDirtyRead() { + return isPontentialDirtyRead; + } + @Override public void remove() { throw new UnsupportedOperationException(); @@ -130,11 +136,4 @@ public ArangoIterator iterator() { return iterator; } - @Override - public void foreach(final Consumer action) { - while (hasNext()) { - action.accept(next()); - } - } - } diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java b/core/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java similarity index 73% rename from src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java rename to core/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java index b67ed820d..e6d681045 100644 --- a/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java +++ b/core/src/main/java/com/arangodb/internal/cursor/ArangoCursorIterator.java @@ -22,11 +22,10 @@ import com.arangodb.ArangoCursor; import com.arangodb.ArangoIterator; -import com.arangodb.entity.CursorEntity; import com.arangodb.internal.ArangoCursorExecute; import com.arangodb.internal.InternalArangoDatabase; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; -import com.arangodb.velocypack.VPackSlice; +import com.arangodb.internal.cursor.entity.InternalCursorEntity; +import com.fasterxml.jackson.databind.JsonNode; import java.util.Iterator; import java.util.NoSuchElementException; @@ -37,24 +36,23 @@ */ public class ArangoCursorIterator implements ArangoIterator { - private CursorEntity result; - private Iterator arrayIterator; - private final ArangoCursor cursor; private final InternalArangoDatabase db; private final ArangoCursorExecute execute; + private InternalCursorEntity result; + private Iterator arrayIterator; protected ArangoCursorIterator(final ArangoCursor cursor, final ArangoCursorExecute execute, - final InternalArangoDatabase db, final CursorEntity result) { + final InternalArangoDatabase db, final InternalCursorEntity result) { super(); this.cursor = cursor; this.execute = execute; this.db = db; this.result = result; - arrayIterator = result.getResult().arrayIterator(); + arrayIterator = result.getResult().iterator(); } - public CursorEntity getResult() { + public InternalCursorEntity getResult() { return result; } @@ -65,18 +63,18 @@ public boolean hasNext() { @Override public T next() { - if (!arrayIterator.hasNext() && result.getHasMore()) { + if (!arrayIterator.hasNext() && Boolean.TRUE.equals(result.getHasMore())) { result = execute.next(cursor.getId(), result.getMeta()); - arrayIterator = result.getResult().arrayIterator(); + arrayIterator = result.getResult().iterator(); } if (!hasNext()) { throw new NoSuchElementException(); } - return deserialize(arrayIterator.next(), cursor.getType()); + return deserialize(db.getSerde().serialize(arrayIterator.next()), cursor.getType()); } - protected R deserialize(final VPackSlice result, final Class type) { - return db.util(Serializer.CUSTOM).deserialize(result, type); + protected R deserialize(final byte[] result, final Class type) { + return db.getSerde().deserializeUserData(result, type); } @Override diff --git a/src/main/java/com/arangodb/entity/CursorEntity.java b/core/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java similarity index 58% rename from src/main/java/com/arangodb/entity/CursorEntity.java rename to core/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java index 66a9a7010..535715e3b 100644 --- a/src/main/java/com/arangodb/entity/CursorEntity.java +++ b/core/src/main/java/com/arangodb/internal/cursor/entity/InternalCursorEntity.java @@ -18,12 +18,16 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.entity; +package com.arangodb.internal.cursor.entity; -import com.arangodb.velocypack.VPackSlice; +import com.arangodb.entity.CursorStats; +import com.arangodb.entity.CursorWarning; +import com.arangodb.entity.MetaAware; +import com.fasterxml.jackson.databind.JsonNode; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.Map; /** @@ -31,14 +35,14 @@ * @see API * Documentation */ -public class CursorEntity implements Entity, MetaAware { +public final class InternalCursorEntity implements MetaAware { + private final Extras extra = new Extras(); private String id; private Integer count; - private Extras extra = new Extras(); private Boolean cached; private Boolean hasMore; - private VPackSlice result; + private JsonNode result; private Map meta; @@ -81,99 +85,46 @@ public Boolean getHasMore() { } /** - * @return an vpack-array of result documents (might be empty if query has no results) + * @return an array of result documents (might be empty if query has no results) */ - public VPackSlice getResult() { + public JsonNode getResult() { return result; } + @Override public Map getMeta() { - return meta; + if (meta == null) return Collections.emptyMap(); + return Collections.unmodifiableMap(meta); + } + + @Override + public void setMeta(Map meta) { + this.meta = cleanupMeta(new HashMap<>(meta)); } /** * @return remove not allowed (valid storable) meta information */ public Map cleanupMeta(Map meta) { - meta.remove("Content-Length"); - meta.remove("Transfer-Encoding"); - meta.remove("X-Arango-Queue-Time-Seconds"); + meta.remove("content-length"); + meta.remove("transfer-encoding"); + meta.remove("x-arango-queue-time-seconds"); return meta; } - public void setMeta(Map meta) { - this.meta = cleanupMeta(meta); - } - - public static class Warning { - - private Integer code; - private String message; - - public Integer getCode() { - return code; - } - - public String getMessage() { - return message; - } - - } - - public static class Extras { - private Stats stats; - private Collection warnings = Collections.emptyList(); + public static final class Extras { + private final Collection warnings = Collections.emptyList(); + private CursorStats stats; - public Stats getStats() { + public CursorStats getStats() { return stats; } - public Collection getWarnings() { + public Collection getWarnings() { return warnings; } } - public static class Stats { - private Long writesExecuted; - private Long writesIgnored; - private Long scannedFull; - private Long scannedIndex; - private Long filtered; - private Long fullCount; - private Double executionTime; - private Long peakMemoryUsage; - - public Long getWritesExecuted() { - return writesExecuted; - } - - public Long getWritesIgnored() { - return writesIgnored; - } - - public Long getScannedFull() { - return scannedFull; - } - - public Long getScannedIndex() { - return scannedIndex; - } - - public Long getFiltered() { - return filtered; - } - - public Long getFullCount() { - return fullCount; - } - - public Double getExecutionTime() { - return executionTime; - } - - public Long getPeakMemoryUsage() { - return peakMemoryUsage; - } - } } + diff --git a/src/main/java/com/arangodb/internal/net/AccessType.java b/core/src/main/java/com/arangodb/internal/net/AccessType.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/AccessType.java rename to core/src/main/java/com/arangodb/internal/net/AccessType.java diff --git a/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java b/core/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java similarity index 96% rename from src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java rename to core/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java index 8b7c37010..bf8e0c9cd 100644 --- a/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java +++ b/core/src/main/java/com/arangodb/internal/net/ArangoDBRedirectException.java @@ -1,42 +1,42 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.net; - -import com.arangodb.ArangoDBException; - -/** - * @author Mark Vollmary - */ -public class ArangoDBRedirectException extends ArangoDBException { - - private static final long serialVersionUID = -94810262465567613L; - private final String location; - - public ArangoDBRedirectException(final String message, final String location) { - super(message); - this.location = location; - } - - public String getLocation() { - return location; - } - -} +/* + * DISCLAIMER + * + * Copyright 2017 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal.net; + +import com.arangodb.ArangoDBException; + +/** + * @author Mark Vollmary + */ +public class ArangoDBRedirectException extends ArangoDBException { + + private static final long serialVersionUID = -94810262465567613L; + private final String location; + + public ArangoDBRedirectException(final String message, final String location) { + super(message); + this.location = location; + } + + public String getLocation() { + return location; + } + +} diff --git a/core/src/main/java/com/arangodb/internal/net/AsyncCommunication.java b/core/src/main/java/com/arangodb/internal/net/AsyncCommunication.java new file mode 100644 index 000000000..abb630780 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/net/AsyncCommunication.java @@ -0,0 +1,14 @@ +package com.arangodb.internal.net; + +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; + +import java.io.Closeable; +import java.util.concurrent.CompletableFuture; + +public interface AsyncCommunication extends Closeable { + + CompletableFuture execute(final InternalRequest request, final HostHandle hostHandle); + void setJwt(String jwt); + +} diff --git a/core/src/main/java/com/arangodb/internal/net/AsyncProtocolProvider.java b/core/src/main/java/com/arangodb/internal/net/AsyncProtocolProvider.java new file mode 100644 index 000000000..d77a8e2a9 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/net/AsyncProtocolProvider.java @@ -0,0 +1,18 @@ +package com.arangodb.internal.net; + + +import com.arangodb.Protocol; +import com.arangodb.internal.config.ArangoConfig; +import com.fasterxml.jackson.databind.Module; + +public interface AsyncProtocolProvider { + + boolean supportsProtocol(Protocol protocol); + + ConnectionFactory createConnectionFactory(); + + AsyncCommunication createCommunication(ArangoConfig config, HostHandler hostHandler); + + Module protocolModule(); + +} diff --git a/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java b/core/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java similarity index 77% rename from src/main/java/com/arangodb/internal/net/CommunicationProtocol.java rename to core/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java index 31e9a38ea..a7f5d2b75 100644 --- a/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java +++ b/core/src/main/java/com/arangodb/internal/net/CommunicationProtocol.java @@ -1,38 +1,37 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.net; - -import com.arangodb.ArangoDBException; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; - -import java.io.Closeable; - -/** - * @author Mark Vollmary - */ -public interface CommunicationProtocol extends Closeable { - - Response execute(final Request request, HostHandle hostHandle) throws ArangoDBException; - - void setJwt(String jwt); - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal.net; + +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; + +import java.io.Closeable; + +/** + * @author Mark Vollmary + */ +public interface CommunicationProtocol extends Closeable { + + InternalResponse execute(final InternalRequest request, HostHandle hostHandle); + + void setJwt(String jwt); + +} diff --git a/src/main/java/com/arangodb/internal/net/Connection.java b/core/src/main/java/com/arangodb/internal/net/Connection.java similarity index 100% rename from src/main/java/com/arangodb/internal/net/Connection.java rename to core/src/main/java/com/arangodb/internal/net/Connection.java diff --git a/src/main/java/com/arangodb/internal/net/ConnectionFactory.java b/core/src/main/java/com/arangodb/internal/net/ConnectionFactory.java similarity index 83% rename from src/main/java/com/arangodb/internal/net/ConnectionFactory.java rename to core/src/main/java/com/arangodb/internal/net/ConnectionFactory.java index 4987a40cb..ed3d5571c 100644 --- a/src/main/java/com/arangodb/internal/net/ConnectionFactory.java +++ b/core/src/main/java/com/arangodb/internal/net/ConnectionFactory.java @@ -20,11 +20,12 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; + /** * @author Mark Vollmary */ public interface ConnectionFactory { - - Connection create(final HostDescription host); - + Connection create(ArangoConfig config, HostDescription host); } diff --git a/src/main/java/com/arangodb/internal/net/ConnectionPool.java b/core/src/main/java/com/arangodb/internal/net/ConnectionPool.java similarity index 95% rename from src/main/java/com/arangodb/internal/net/ConnectionPool.java rename to core/src/main/java/com/arangodb/internal/net/ConnectionPool.java index d1ad313d0..91c12bb02 100644 --- a/src/main/java/com/arangodb/internal/net/ConnectionPool.java +++ b/core/src/main/java/com/arangodb/internal/net/ConnectionPool.java @@ -20,6 +20,8 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; + import java.io.Closeable; /** diff --git a/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java b/core/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java similarity index 80% rename from src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java rename to core/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java index cf275e6db..0de7d3474 100644 --- a/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java +++ b/core/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java @@ -20,11 +20,9 @@ package com.arangodb.internal.net; -import com.arangodb.internal.velocystream.internal.VstConnection; -import com.arangodb.internal.velocystream.internal.VstConnectionSync; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +import com.arangodb.ArangoDBException; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -34,20 +32,20 @@ */ public class ConnectionPoolImpl implements ConnectionPool { - private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionPoolImpl.class); - private final HostDescription host; + private final ArangoConfig config; private final int maxConnections; private final List connections; - private int current; private final ConnectionFactory factory; + private int current; private volatile String jwt = null; + private boolean closed = false; - public ConnectionPoolImpl(final HostDescription host, final Integer maxConnections, - final ConnectionFactory factory) { + public ConnectionPoolImpl(final HostDescription host, final ArangoConfig config, final ConnectionFactory factory) { super(); this.host = host; - this.maxConnections = maxConnections; + this.config = config; + this.maxConnections = config.getMaxConnections(); this.factory = factory; connections = new ArrayList<>(); current = 0; @@ -55,13 +53,16 @@ public ConnectionPoolImpl(final HostDescription host, final Integer maxConnectio @Override public Connection createConnection(final HostDescription host) { - Connection c = factory.create(host); + Connection c = factory.create(config, host); c.setJwt(jwt); return c; } @Override public synchronized Connection connection() { + if (closed) { + throw new ArangoDBException("Connection pool already closed!"); + } final Connection connection; @@ -74,10 +75,6 @@ public synchronized Connection connection() { connection = connections.get(index); } - if (connection instanceof VstConnectionSync) { - LOGGER.debug("Return Connection " + ((VstConnection) connection).getConnectionName()); - } - return connection; } @@ -91,6 +88,7 @@ public void setJwt(String jwt) { @Override public synchronized void close() throws IOException { + closed = true; for (final Connection connection : connections) { connection.close(); } diff --git a/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java b/core/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java similarity index 98% rename from src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java rename to core/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java index db3879d80..2fded0c99 100644 --- a/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java +++ b/core/src/main/java/com/arangodb/internal/net/DirtyReadHostHandler.java @@ -20,6 +20,8 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; + import java.io.IOException; /** diff --git a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java b/core/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java similarity index 68% rename from src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java rename to core/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java index eb7dd40e0..ad2c3c915 100644 --- a/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java +++ b/core/src/main/java/com/arangodb/internal/net/ExtendedHostResolver.java @@ -22,21 +22,19 @@ import com.arangodb.ArangoDBException; import com.arangodb.DbName; +import com.arangodb.config.HostDescription; import com.arangodb.internal.ArangoExecutorSync; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.RequestType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; + +import static com.arangodb.internal.serde.SerdeUtils.constructParametricType; /** * @author Mark Vollmary @@ -47,35 +45,32 @@ public class ExtendedHostResolver implements HostResolver { private final HostSet hosts; - private final Integer maxConnections; + private final ArangoConfig config; private final ConnectionFactory connectionFactory; - - private long lastUpdate; private final Integer acquireHostListInterval; - + private long lastUpdate; private ArangoExecutorSync executor; - private ArangoSerialization arangoSerialization; + private InternalSerde arangoSerialization; - public ExtendedHostResolver(final List hosts, final Integer maxConnections, + public ExtendedHostResolver(final List hosts, final ArangoConfig config, final ConnectionFactory connectionFactory, Integer acquireHostListInterval) { this.acquireHostListInterval = acquireHostListInterval; this.hosts = new HostSet(hosts); - this.maxConnections = maxConnections; + this.config = config; this.connectionFactory = connectionFactory; lastUpdate = 0; } @Override - public void init(ArangoExecutorSync executor, ArangoSerialization arangoSerialization) { + public void init(ArangoExecutorSync executor, InternalSerde arangoSerialization) { this.executor = executor; this.arangoSerialization = arangoSerialization; } @Override - public HostSet resolve(boolean initial, boolean closeConnections) { if (!initial && isExpired()) { @@ -83,33 +78,35 @@ public HostSet resolve(boolean initial, boolean closeConnections) { lastUpdate = System.currentTimeMillis(); final Collection endpoints = resolveFromServer(); - LOGGER.debug("Resolve " + endpoints.size() + " Endpoints"); - LOGGER.debug("Endpoints " + Arrays.deepToString(endpoints.toArray())); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Resolve {} Endpoints", endpoints.size()); + LOGGER.debug("Endpoints {}", Arrays.deepToString(endpoints.toArray())); + } if (!endpoints.isEmpty()) { hosts.markAllForDeletion(); } for (final String endpoint : endpoints) { - LOGGER.debug("Create HOST from " + endpoint); + LOGGER.debug("Create HOST from {}", endpoint); if (endpoint.matches(".*://.+:[0-9]+")) { final String[] s = endpoint.replaceAll(".*://", "").split(":"); if (s.length == 2) { final HostDescription description = new HostDescription(s[0], Integer.parseInt(s[1])); - hosts.addHost(HostUtils.createHost(description, maxConnections, connectionFactory)); + hosts.addHost(HostUtils.createHost(description, config, connectionFactory)); } else if (s.length == 4) { // IPV6 Address - TODO: we need a proper function to resolve AND support IPV4 & IPV6 functions // globally final HostDescription description = new HostDescription("127.0.0.1", Integer.parseInt(s[3])); - hosts.addHost(HostUtils.createHost(description, maxConnections, connectionFactory)); + hosts.addHost(HostUtils.createHost(description, config, connectionFactory)); } else { - LOGGER.warn("Skip Endpoint (Missing Port)" + endpoint); + LOGGER.warn("Skip Endpoint (Missing Port) {}", endpoint); } } else { - LOGGER.warn("Skip Endpoint (Format)" + endpoint); + LOGGER.warn("Skip Endpoint (Format) {}", endpoint); } } hosts.clearAllMarkedForDeletion(); @@ -118,25 +115,22 @@ public HostSet resolve(boolean initial, boolean closeConnections) { return hosts; } - private Collection resolveFromServer() throws ArangoDBException { + private Collection resolveFromServer() { Collection response; try { response = executor.execute( - new Request(DbName.SYSTEM, RequestType.GET, "/_api/cluster/endpoints"), + new InternalRequest(DbName.SYSTEM, RequestType.GET, "/_api/cluster/endpoints"), response1 -> { - final VPackSlice field = response1.getBody().get("endpoints"); - Collection endpoints; - if (field.isNone()) { - endpoints = Collections.emptyList(); - } else { - final Collection> tmp = arangoSerialization.deserialize(field, Collection.class); - endpoints = new ArrayList<>(); - for (final Map map : tmp) { - endpoints.add(map.get("endpoint")); - } + final List> tmp = arangoSerialization.deserialize(response1.getBody(), + "/endpoints", + constructParametricType(List.class, + constructParametricType(Map.class, String.class, String.class))); + Collection endpoints = new ArrayList<>(); + for (final Map map : tmp) { + endpoints.add(map.get("endpoint")); } return endpoints; }, null); diff --git a/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java b/core/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java similarity index 98% rename from src/main/java/com/arangodb/internal/net/FallbackHostHandler.java rename to core/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java index 241a1b270..5ea722d6d 100644 --- a/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java +++ b/core/src/main/java/com/arangodb/internal/net/FallbackHostHandler.java @@ -22,6 +22,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.ArangoDBMultipleException; +import com.arangodb.config.HostDescription; import java.util.ArrayList; import java.util.List; @@ -32,10 +33,10 @@ public class FallbackHostHandler implements HostHandler { private final HostResolver resolver; + private final List lastFailExceptions; private Host current; private Host lastSuccess; private int iterations; - private final List lastFailExceptions; private boolean firstOpened; private HostSet hosts; diff --git a/src/main/java/com/arangodb/internal/net/Host.java b/core/src/main/java/com/arangodb/internal/net/Host.java similarity index 95% rename from src/main/java/com/arangodb/internal/net/Host.java rename to core/src/main/java/com/arangodb/internal/net/Host.java index 57f4d6e80..91a6e50da 100644 --- a/src/main/java/com/arangodb/internal/net/Host.java +++ b/core/src/main/java/com/arangodb/internal/net/Host.java @@ -20,6 +20,8 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; + import java.io.IOException; /** @@ -35,10 +37,10 @@ public interface Host { void close() throws IOException; - void setMarkforDeletion(boolean markforDeletion); - boolean isMarkforDeletion(); + void setMarkforDeletion(boolean markforDeletion); + void setJwt(String jwt); } diff --git a/src/main/java/com/arangodb/internal/net/HostHandle.java b/core/src/main/java/com/arangodb/internal/net/HostHandle.java similarity index 95% rename from src/main/java/com/arangodb/internal/net/HostHandle.java rename to core/src/main/java/com/arangodb/internal/net/HostHandle.java index c26b184d3..e288c2171 100644 --- a/src/main/java/com/arangodb/internal/net/HostHandle.java +++ b/core/src/main/java/com/arangodb/internal/net/HostHandle.java @@ -20,6 +20,8 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; + /** * @author Mark Vollmary */ diff --git a/src/main/java/com/arangodb/internal/net/HostHandler.java b/core/src/main/java/com/arangodb/internal/net/HostHandler.java similarity index 96% rename from src/main/java/com/arangodb/internal/net/HostHandler.java rename to core/src/main/java/com/arangodb/internal/net/HostHandler.java index 1a3ad8d92..911a219b0 100644 --- a/src/main/java/com/arangodb/internal/net/HostHandler.java +++ b/core/src/main/java/com/arangodb/internal/net/HostHandler.java @@ -20,6 +20,8 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; + import java.io.IOException; /** diff --git a/src/main/java/com/arangodb/internal/net/HostImpl.java b/core/src/main/java/com/arangodb/internal/net/HostImpl.java similarity index 98% rename from src/main/java/com/arangodb/internal/net/HostImpl.java rename to core/src/main/java/com/arangodb/internal/net/HostImpl.java index d50b84ae1..2477bee9c 100644 --- a/src/main/java/com/arangodb/internal/net/HostImpl.java +++ b/core/src/main/java/com/arangodb/internal/net/HostImpl.java @@ -21,6 +21,7 @@ package com.arangodb.internal.net; import com.arangodb.ArangoDBException; +import com.arangodb.config.HostDescription; import java.io.IOException; @@ -73,15 +74,15 @@ public boolean isMarkforDeletion() { return markforDeletion; } + public void setMarkforDeletion(boolean markforDeletion) { + this.markforDeletion = markforDeletion; + } + @Override public void setJwt(String jwt) { connectionPool.setJwt(jwt); } - public void setMarkforDeletion(boolean markforDeletion) { - this.markforDeletion = markforDeletion; - } - @Override public int hashCode() { final int prime = 31; diff --git a/src/main/java/com/arangodb/internal/net/HostResolver.java b/core/src/main/java/com/arangodb/internal/net/HostResolver.java similarity index 87% rename from src/main/java/com/arangodb/internal/net/HostResolver.java rename to core/src/main/java/com/arangodb/internal/net/HostResolver.java index 85bdd2038..744ee9e87 100644 --- a/src/main/java/com/arangodb/internal/net/HostResolver.java +++ b/core/src/main/java/com/arangodb/internal/net/HostResolver.java @@ -21,14 +21,14 @@ package com.arangodb.internal.net; import com.arangodb.internal.ArangoExecutorSync; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.internal.serde.InternalSerde; /** * @author Mark Vollmary */ public interface HostResolver { - void init(ArangoExecutorSync executorSync, ArangoSerialization arangoSerialization); + void init(ArangoExecutorSync executorSync, InternalSerde arangoSerialization); HostSet resolve(boolean initial, boolean closeConnections); diff --git a/src/main/java/com/arangodb/internal/net/HostSet.java b/core/src/main/java/com/arangodb/internal/net/HostSet.java similarity index 89% rename from src/main/java/com/arangodb/internal/net/HostSet.java rename to core/src/main/java/com/arangodb/internal/net/HostSet.java index ddcad12bb..39c8d784f 100644 --- a/src/main/java/com/arangodb/internal/net/HostSet.java +++ b/core/src/main/java/com/arangodb/internal/net/HostSet.java @@ -34,7 +34,7 @@ public List getHostsList() { public void addHost(Host newHost) { if (hosts.contains(newHost)) { - LOGGER.debug("Host" + newHost + " already in Set"); + LOGGER.debug("Host {} already in Set", newHost); for (Host host : hosts) { if (host.equals(newHost)) { host.setMarkforDeletion(false); @@ -43,7 +43,7 @@ public void addHost(Host newHost) { } else { newHost.setJwt(jwt); hosts.add(newHost); - LOGGER.debug("Added Host " + newHost + " - now " + hosts.size() + " Hosts in List"); + LOGGER.debug("Added Host {} - now {} Hosts in List", newHost, hosts.size()); } } @@ -53,7 +53,7 @@ public void close() { for (Host host : hosts) { try { - LOGGER.debug("Try to close Host " + host); + LOGGER.debug("Try to close Host {}", host); host.close(); } catch (IOException e) { @@ -79,7 +79,7 @@ public void clearAllMarkedForDeletion() { Host host = iterable.next(); if (host.isMarkforDeletion()) { try { - LOGGER.debug("Try to close Host " + host); + LOGGER.debug("Try to close Host {}", host); host.close(); } catch (IOException e) { LOGGER.warn("Error during closing the Host " + host, e); diff --git a/core/src/main/java/com/arangodb/internal/net/ProtocolProvider.java b/core/src/main/java/com/arangodb/internal/net/ProtocolProvider.java new file mode 100644 index 000000000..583740938 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/net/ProtocolProvider.java @@ -0,0 +1,17 @@ +package com.arangodb.internal.net; + + +import com.arangodb.Protocol; +import com.arangodb.internal.config.ArangoConfig; +import com.fasterxml.jackson.databind.Module; + +public interface ProtocolProvider { + + boolean supportsProtocol(Protocol protocol); + + ConnectionFactory createConnectionFactory(); + + CommunicationProtocol createProtocol(ArangoConfig config, HostHandler hostHandler); + + Module protocolModule(); +} diff --git a/src/main/java/com/arangodb/internal/net/RandomHostHandler.java b/core/src/main/java/com/arangodb/internal/net/RandomHostHandler.java similarity index 98% rename from src/main/java/com/arangodb/internal/net/RandomHostHandler.java rename to core/src/main/java/com/arangodb/internal/net/RandomHostHandler.java index 7e7a4464b..4fd00e3b8 100644 --- a/src/main/java/com/arangodb/internal/net/RandomHostHandler.java +++ b/core/src/main/java/com/arangodb/internal/net/RandomHostHandler.java @@ -20,6 +20,8 @@ package com.arangodb.internal.net; +import com.arangodb.config.HostDescription; + import java.util.ArrayList; import java.util.Collections; diff --git a/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java b/core/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java similarity index 98% rename from src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java rename to core/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java index e7cc650ea..d980ef5cc 100644 --- a/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java +++ b/core/src/main/java/com/arangodb/internal/net/RoundRobinHostHandler.java @@ -22,6 +22,7 @@ import com.arangodb.ArangoDBException; import com.arangodb.ArangoDBMultipleException; +import com.arangodb.config.HostDescription; import java.util.ArrayList; import java.util.List; @@ -32,9 +33,9 @@ public class RoundRobinHostHandler implements HostHandler { private final HostResolver resolver; + private final List lastFailExceptions; private long current; private int fails; - private final List lastFailExceptions; private Host currentHost; private HostSet hosts; diff --git a/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java b/core/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java similarity index 89% rename from src/main/java/com/arangodb/internal/net/SimpleHostResolver.java rename to core/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java index e139e3866..1d1d8f8f5 100644 --- a/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java +++ b/core/src/main/java/com/arangodb/internal/net/SimpleHostResolver.java @@ -21,7 +21,7 @@ package com.arangodb.internal.net; import com.arangodb.internal.ArangoExecutorSync; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.internal.serde.InternalSerde; import java.util.List; @@ -38,7 +38,7 @@ public SimpleHostResolver(final List hosts) { } @Override - public void init(ArangoExecutorSync executor, ArangoSerialization arangoSerialization) { + public void init(ArangoExecutorSync executor, InternalSerde arangoSerialization) { } diff --git a/core/src/main/java/com/arangodb/internal/serde/ContentTypeFactory.java b/core/src/main/java/com/arangodb/internal/serde/ContentTypeFactory.java new file mode 100644 index 000000000..453cc2a0f --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/ContentTypeFactory.java @@ -0,0 +1,24 @@ +package com.arangodb.internal.serde; + +import com.arangodb.ContentType; +import com.arangodb.Protocol; + +public final class ContentTypeFactory { + private ContentTypeFactory() { + } + + public static ContentType of(Protocol protocol) { + switch (protocol) { + case HTTP_JSON: + case HTTP2_JSON: + return ContentType.JSON; + case VST: + case HTTP_VPACK: + case HTTP2_VPACK: + return ContentType.VPACK; + default: + throw new IllegalArgumentException("Unexpected value: " + protocol); + } + } + +} diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java b/core/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java new file mode 100644 index 000000000..d0655cfd5 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/InternalAnnotationIntrospector.java @@ -0,0 +1,66 @@ +package com.arangodb.internal.serde; + +import com.fasterxml.jackson.databind.introspect.Annotated; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +class InternalAnnotationIntrospector extends JacksonAnnotationIntrospector { + + private final transient UserDataSerializer userDataSerializer; + private final transient UserDataDeserializer userDataDeserializer; + + InternalAnnotationIntrospector( + final UserDataSerializer userDataSerializer, + final UserDataDeserializer userDataDeserializer + ) { + this.userDataSerializer = userDataSerializer; + this.userDataDeserializer = userDataDeserializer; + } + + @Override + public Object findSerializer(Annotated a) { + if (a.getAnnotation(UserData.class) != null) { + return userDataSerializer; + } else { + return super.findSerializer(a); + } + } + + @Override + public Object findContentSerializer(Annotated a) { + if (a.getAnnotation(UserDataInside.class) != null) { + return userDataSerializer; + } else { + return super.findContentSerializer(a); + } + } + + @Override + public Object findDeserializer(Annotated a) { + if (a.getAnnotation(UserData.class) != null) { + return userDataDeserializer; + } else { + return super.findDeserializer(a); + } + } + + @Override + public Object findContentDeserializer(Annotated a) { + if (a.getAnnotation(UserDataInside.class) != null) { + return userDataDeserializer; + } else { + return super.findContentDeserializer(a); + } + } + + private void writeObject(ObjectOutputStream out) throws IOException { + throw new IOException("Serialization not allowed"); + } + + private void readObject(ObjectInputStream in) throws IOException { + throw new IOException("Deserialization not allowed"); + } +} diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java b/core/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java new file mode 100644 index 000000000..6062a86a1 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/InternalDeserializers.java @@ -0,0 +1,154 @@ +package com.arangodb.internal.serde; + +import com.arangodb.entity.CollectionStatus; +import com.arangodb.entity.CollectionType; +import com.arangodb.entity.InvertedIndexPrimarySort; +import com.arangodb.entity.ReplicationFactor; +import com.arangodb.entity.arangosearch.CollectionLink; +import com.arangodb.entity.arangosearch.FieldLink; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; +import com.arangodb.internal.InternalResponse; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.TreeNode; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.*; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +public final class InternalDeserializers { + + static final JsonDeserializer RAW_JSON_DESERIALIZER = new JsonDeserializer() { + @Override + public RawJson deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + // TODO: find a way to access raw bytes directly + return RawJson.of(SerdeUtils.INSTANCE.writeJson(p.readValueAsTree())); + } + }; + + static final JsonDeserializer RAW_BYTES_DESERIALIZER = new JsonDeserializer() { + @Override + public RawBytes deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + // TODO: find a way to access raw bytes directly + ByteArrayOutputStream os = new ByteArrayOutputStream(); + try (JsonGenerator g = p.getCodec().getFactory().createGenerator(os)) { + g.writeTree(p.readValueAsTree()); + } + return RawBytes.of(os.toByteArray()); + } + }; + + static final JsonDeserializer COLLECTION_STATUS = new JsonDeserializer() { + @Override + public CollectionStatus deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { + return CollectionStatus.fromStatus(p.getIntValue()); + } + }; + + static final JsonDeserializer COLLECTION_TYPE = new JsonDeserializer() { + @Override + public CollectionType deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { + return CollectionType.fromType(p.getIntValue()); + } + }; + + static final JsonDeserializer REPLICATION_FACTOR = new JsonDeserializer() { + @Override + public ReplicationFactor deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { + TreeNode node = p.readValueAsTree(); + if (node instanceof NumericNode) { + return ReplicationFactor.of(((NumericNode) node).intValue()); + } else if (node instanceof TextNode && "satellite".equals(((TextNode) node).textValue())) { + return ReplicationFactor.ofSatellite(); + } else throw new IllegalArgumentException(); + } + }; + + @SuppressWarnings("unchecked") + static final JsonDeserializer RESPONSE = new JsonDeserializer() { + @Override + public InternalResponse deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { + final InternalResponse response = new InternalResponse(); + Iterator it = ((ArrayNode) p.readValueAsTree()).iterator(); + response.setVersion(it.next().intValue()); + response.setType(it.next().intValue()); + response.setResponseCode(it.next().intValue()); + if (it.hasNext()) { + response.putMetas(readTreeAsValue(p, ctxt, it.next(), Map.class)); + } + return response; + } + }; + + static final JsonDeserializer INVERTED_INDEX_PRIMARY_SORT_FIELD = new JsonDeserializer() { + @Override + public InvertedIndexPrimarySort.Field deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { + ObjectNode tree = p.readValueAsTree(); + String field = tree.get("field").textValue(); + InvertedIndexPrimarySort.Field.Direction direction = tree.get("asc").booleanValue() ? + InvertedIndexPrimarySort.Field.Direction.asc : InvertedIndexPrimarySort.Field.Direction.desc; + return new InvertedIndexPrimarySort.Field(field, direction); + } + }; + + private InternalDeserializers() { + } + + private static T readTreeAsValue(JsonParser p, DeserializationContext ctxt, JsonNode n, Class targetType) throws IOException { + try (TreeTraversingParser t = new TreeTraversingParser(n, p.getCodec())) { + t.nextToken(); + return ctxt.readValue(t, targetType); + } + } + + public static class CollectionLinksDeserializer extends JsonDeserializer> { + + @Override + public Collection deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + Collection out = new ArrayList<>(); + ObjectNode tree = p.readValueAsTree(); + Iterator> it = tree.fields(); + while (it.hasNext()) { + Map.Entry e = it.next(); + ObjectNode v = (ObjectNode) e.getValue(); + v.put("name", e.getKey()); + out.add(readTreeAsValue(p, ctxt, v, CollectionLink.class)); + } + return out; + } + } + + public static class FieldLinksDeserializer extends JsonDeserializer { + + @Override + public FieldLink[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + Collection out = new ArrayList<>(); + ObjectNode tree = p.readValueAsTree(); + Iterator> it = tree.fields(); + while (it.hasNext()) { + Map.Entry e = it.next(); + ObjectNode v = (ObjectNode) e.getValue(); + v.put("name", e.getKey()); + out.add(readTreeAsValue(p, ctxt, v, FieldLink.class)); + } + return out.toArray(new FieldLink[0]); + } + } + + public static class CollectionSchemaRuleDeserializer extends JsonDeserializer { + @Override + public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + return SerdeUtils.INSTANCE.writeJson(p.readValueAsTree()); + } + } + + +} diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java b/core/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java new file mode 100644 index 000000000..241e0893d --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/InternalMapperProvider.java @@ -0,0 +1,31 @@ +package com.arangodb.internal.serde; + +import com.arangodb.ArangoDBException; +import com.arangodb.ContentType; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.ServiceLoader; +import java.util.function.Supplier; + +public interface InternalMapperProvider extends Supplier { + static ObjectMapper of(final ContentType contentType) { + String formatName; + if (contentType == ContentType.JSON) { + formatName = "JSON"; + } else if (contentType == ContentType.VPACK) { + formatName = "Velocypack"; + } else { + throw new IllegalArgumentException("Unexpected value: " + contentType); + } + + ServiceLoader sl = ServiceLoader.load(JsonFactory.class); + for (JsonFactory jf : sl) { + if(formatName.equals(jf.getFormatName())){ + return new ObjectMapper(jf); + } + } + + throw new ArangoDBException("No JsonFactory found for content type: " + contentType); + } +} diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalModule.java b/core/src/main/java/com/arangodb/internal/serde/InternalModule.java new file mode 100644 index 000000000..3aeae3c24 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/InternalModule.java @@ -0,0 +1,43 @@ +package com.arangodb.internal.serde; + +import com.arangodb.entity.CollectionStatus; +import com.arangodb.entity.CollectionType; +import com.arangodb.entity.InvertedIndexPrimarySort; +import com.arangodb.entity.ReplicationFactor; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; +import com.fasterxml.jackson.databind.Module; +import com.fasterxml.jackson.databind.module.SimpleModule; + +import java.util.function.Supplier; + +enum InternalModule implements Supplier { + INSTANCE; + + private final SimpleModule module; + + InternalModule() { + module = new SimpleModule(); + + module.addSerializer(RawJson.class, InternalSerializers.RAW_JSON_SERIALIZER); + module.addSerializer(RawBytes.class, InternalSerializers.RAW_BYTES_SERIALIZER); + module.addSerializer(InternalRequest.class, InternalSerializers.REQUEST); + module.addSerializer(CollectionType.class, InternalSerializers.COLLECTION_TYPE); + + module.addDeserializer(RawJson.class, InternalDeserializers.RAW_JSON_DESERIALIZER); + module.addDeserializer(RawBytes.class, InternalDeserializers.RAW_BYTES_DESERIALIZER); + module.addDeserializer(CollectionStatus.class, InternalDeserializers.COLLECTION_STATUS); + module.addDeserializer(CollectionType.class, InternalDeserializers.COLLECTION_TYPE); + module.addDeserializer(ReplicationFactor.class, InternalDeserializers.REPLICATION_FACTOR); + module.addDeserializer(InternalResponse.class, InternalDeserializers.RESPONSE); + module.addDeserializer(InvertedIndexPrimarySort.Field.class, InternalDeserializers.INVERTED_INDEX_PRIMARY_SORT_FIELD); + } + + @Override + public Module get() { + return module; + } + +} diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java b/core/src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java new file mode 100644 index 000000000..82c0dcf4c --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/InternalParameterizedType.java @@ -0,0 +1,31 @@ +package com.arangodb.internal.serde; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +class InternalParameterizedType implements ParameterizedType { + + private final Class rawType; + private final Type[] actualRawArguments; + + InternalParameterizedType(final Class rawType, final Type[] actualRawArguments) { + this.rawType = rawType; + this.actualRawArguments = actualRawArguments; + } + + @Override + public Type getRawType() { + return rawType; + } + + @Override + public Type[] getActualTypeArguments() { + return actualRawArguments; + } + + @Override + public Type getOwnerType() { + return null; + } + +} diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalSerde.java b/core/src/main/java/com/arangodb/internal/serde/InternalSerde.java new file mode 100644 index 000000000..97e7f2333 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/InternalSerde.java @@ -0,0 +1,161 @@ +package com.arangodb.internal.serde; + +import com.arangodb.serde.ArangoSerde; +import com.arangodb.ContentType; +import com.fasterxml.jackson.databind.JsonNode; + +import java.lang.reflect.Type; +import java.util.Collection; + +public interface InternalSerde extends ArangoSerde { + + /** + * Used for logging and debugging. + * + * @param content byte array + * @return JSON string + */ + String toJsonString(byte[] content); + + /** + * Extract the nested content pointed by the json pointer. + * Used for extracting nested user data. + * + * @param content byte array + * @param jsonPointer location of data to be extracted + * @return byte array + */ + byte[] extract(byte[] content, String jsonPointer); + + /** + * Deserializes the content and binds it to the target data type. + * For data type {@link ContentType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. + * + * @param content byte array to deserialize + * @param type target data type + * @return deserialized object + */ + T deserialize(byte[] content, Type type); + + /** + * Deserializes the parsed json node and binds it to the target data type. + * + * @param node parsed json node + * @param clazz class of target data type + * @return deserialized object + */ + default T deserialize(JsonNode node, Class clazz) { + return deserialize(node, (Type) clazz); + } + + /** + * Deserializes the parsed json node and binds it to the target data type. + * + * @param node parsed json node + * @param type target data type + * @return deserialized object + */ + T deserialize(JsonNode node, Type type); + + /** + * Parses the content. + * + * @param content VPack or byte encoded JSON string + * @return root of the parsed tree + */ + JsonNode parse(byte[] content); + + /** + * Parses the content at json pointer. + * + * @param content VPack or byte encoded JSON string + * @param jsonPointer location of data to be parsed + * @return root of the parsed tree + */ + JsonNode parse(byte[] content, String jsonPointer); + + /** + * Deserializes the content at json pointer and binds it to the target data type. + * For data type {@link ContentType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. + * + * @param content byte array to deserialize + * @param jsonPointer location of data to be deserialized + * @param clazz class of target data type + * @return deserialized object + */ + default T deserialize(byte[] content, String jsonPointer, Class clazz) { + return deserialize(content, jsonPointer, (Type) clazz); + } + + /** + * Deserializes the content at json pointer and binds it to the target data type. + * For data type {@link ContentType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. + * + * @param content byte array to deserialize + * @param jsonPointer location of data to be deserialized + * @param type target data type + * @return deserialized object + */ + default T deserialize(byte[] content, String jsonPointer, Type type) { + return deserialize(parse(content, jsonPointer), type); + } + + /** + * Serializes the object into the target data type, using the user serde. + * + * @param value object to serialize + * @return serialized byte array + */ + byte[] serializeUserData(Object value); + + /** + * Serializes each element in the collection using the user serde. + * + * @param value objects to serialize + * @return serialized byte array + */ + byte[] serializeCollectionUserData(Collection value); + + /** + * Deserializes the content and binds it to the target data type, using the user serde. + * + * @param content byte array to deserialize + * @param clazz class of target data type + * @return deserialized object + */ + T deserializeUserData(byte[] content, Class clazz); + + /** + * Deserializes the content and binds it to the target data type, using the user serde. + * + * @param content byte array to deserialize + * @param type target data type + * @return deserialized object + */ + T deserializeUserData(byte[] content, Type type); + + /** + * Deserializes the parsed json node and binds it to the target data type, using the user serde. + * + * @param node parsed json node + * @param clazz class of target data type + * @return deserialized object + */ + default T deserializeUserData(JsonNode node, Class clazz) { + return deserializeUserData(node, (Type) clazz); + } + + /** + * Deserializes the parsed json node and binds it to the target data type, using the user serde. + * + * @param node parsed json node + * @param type target data type + * @return deserialized object + */ + T deserializeUserData(JsonNode node, Type type); + + /** + * @return the user serde + */ + ArangoSerde getUserSerde(); +} diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java b/core/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java new file mode 100644 index 000000000..a7de05b20 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/InternalSerdeImpl.java @@ -0,0 +1,179 @@ +package com.arangodb.internal.serde; + +import com.arangodb.ArangoDBException; +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.BaseEdgeDocument; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.Module; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import static com.arangodb.internal.serde.SerdeUtils.checkSupportedJacksonVersion; + +final class InternalSerdeImpl implements InternalSerde { + + static { + checkSupportedJacksonVersion(); + } + + private final ArangoSerde userSerde; + private final ObjectMapper mapper; + + InternalSerdeImpl(final ObjectMapper mapper, final ArangoSerde userSerde, final Module protocolModule) { + this.mapper = mapper; + this.userSerde = userSerde; + mapper.deactivateDefaultTyping(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.registerModule(InternalModule.INSTANCE.get()); + if (protocolModule != null) { + mapper.registerModule(protocolModule); + } + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.setAnnotationIntrospector(new InternalAnnotationIntrospector( + new UserDataSerializer(this), + new UserDataDeserializer(this) + )); + } + + @Override + public byte[] serialize(final Object value) { + try { + return mapper.writeValueAsBytes(value); + } catch (JsonProcessingException e) { + throw new ArangoDBException(e); + } + } + + @Override + public T deserialize(byte[] content, Class clazz) { + return deserialize(content, (Type) clazz); + } + + @Override + public String toJsonString(final byte[] content) { + try { + return SerdeUtils.INSTANCE.writeJson(mapper.readTree(content)); + } catch (IOException e) { + throw new ArangoDBException(e); + } + } + + @Override + public byte[] extract(final byte[] content, final String jsonPointer) { + try { + JsonNode target = parse(content).at(jsonPointer); + return mapper.writeValueAsBytes(target); + } catch (IOException e) { + throw new ArangoDBException(e); + } + } + + @Override + public JsonNode parse(byte[] content) { + try { + return mapper.readTree(content); + } catch (IOException e) { + throw new ArangoDBException(e); + } + } + + @Override + public JsonNode parse(byte[] content, String jsonPointer) { + try { + return mapper.readTree(content).at(jsonPointer); + } catch (IOException e) { + throw new ArangoDBException(e); + } + } + + @Override + public byte[] serializeUserData(Object value) { + if (value == null) { + return serialize(null); + } + Class clazz = value.getClass(); + if (isManagedClass(clazz)) { + return serialize(value); + } else { + return userSerde.serialize(value); + } + } + + @Override + public byte[] serializeCollectionUserData(Collection value) { + List jsonNodeCollection = value.stream() + .map(this::serializeUserData) + .map(this::parse) + .collect(Collectors.toList()); + return serialize(jsonNodeCollection); + } + + @Override + public T deserializeUserData(byte[] content, Class clazz) { + if (isManagedClass(clazz)) { + return deserialize(content, clazz); + } else { + return userSerde.deserialize(content, clazz); + } + } + + @Override + @SuppressWarnings("unchecked") + public T deserializeUserData(byte[] content, Type type) { + if (type instanceof Class) { + return deserializeUserData(content, (Class) type); + } else { + throw new UnsupportedOperationException(); + } + } + + @Override + public T deserializeUserData(JsonNode node, Type type) { + return deserializeUserData(serialize(node), type); + } + + @Override + public ArangoSerde getUserSerde() { + return userSerde; + } + + @Override + public T deserialize(final JsonNode node, final Type type) { + try { + return mapper.readerFor(mapper.constructType(type)).readValue(node); + } catch (IOException e) { + throw new ArangoDBException(e); + } + } + + @Override + public T deserialize(final byte[] content, final Type type) { + if (content == null) { + return null; + } + try { + return mapper.readerFor(mapper.constructType(type)).readValue(content); + } catch (IOException e) { + throw new ArangoDBException(e); + } + } + + private boolean isManagedClass(Class clazz) { + return JsonNode.class.isAssignableFrom(clazz) || + RawJson.class.equals(clazz) || + RawBytes.class.equals(clazz) || + BaseDocument.class.equals(clazz) || + BaseEdgeDocument.class.equals(clazz); + } +} diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java b/core/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java new file mode 100644 index 000000000..4044d6f17 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/InternalSerdeProvider.java @@ -0,0 +1,33 @@ +package com.arangodb.internal.serde; + +import com.arangodb.ContentType; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.ArangoSerdeProvider; +import com.fasterxml.jackson.databind.Module; + +public class InternalSerdeProvider implements ArangoSerdeProvider { + + /** + * Creates a new InternalSerde with default settings for the specified data type. + * + * @param contentType serialization target data type + * @return the created InternalSerde + */ + @Override + public InternalSerde of(final ContentType contentType) { + return create(contentType, null, null); + } + + /** + * Creates a new InternalSerde with default settings for the specified data type. + * + * @param contentType serialization target data type + * @param userSerde user serde + * @param protocolModule optional Jackson module to support protocol specific types + * @return the created InternalSerde + */ + public static InternalSerde create(final ContentType contentType, ArangoSerde userSerde, Module protocolModule) { + return new InternalSerdeImpl(InternalMapperProvider.of(contentType), userSerde, protocolModule); + } + +} diff --git a/core/src/main/java/com/arangodb/internal/serde/InternalSerializers.java b/core/src/main/java/com/arangodb/internal/serde/InternalSerializers.java new file mode 100644 index 000000000..813025c49 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/InternalSerializers.java @@ -0,0 +1,98 @@ +package com.arangodb.internal.serde; + +import com.arangodb.entity.CollectionType; +import com.arangodb.entity.arangosearch.CollectionLink; +import com.arangodb.entity.arangosearch.FieldLink; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; +import com.arangodb.internal.InternalRequest; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public final class InternalSerializers { + + static final JsonSerializer RAW_JSON_SERIALIZER = new JsonSerializer() { + @Override + public void serialize(RawJson value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeTree(SerdeUtils.INSTANCE.parseJson(value.getValue())); + } + }; + static final JsonSerializer RAW_BYTES_SERIALIZER = new JsonSerializer() { + @Override + public void serialize(RawBytes value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + // TODO: find a way to append raw bytes directly + // see https://github.com/FasterXML/jackson-dataformats-binary/issues/331 + try (JsonParser parser = gen.getCodec().getFactory().createParser(value.getValue())) { + gen.writeTree(parser.readValueAsTree()); + } + } + }; + static final JsonSerializer REQUEST = new JsonSerializer() { + @Override + public void serialize(InternalRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartArray(); + gen.writeNumber(value.getVersion()); + gen.writeNumber(value.getType()); + gen.writeString(value.getDbName().get()); + gen.writeNumber(value.getRequestType().getType()); + gen.writeString(value.getPath()); + gen.writeStartObject(); + for (final Map.Entry entry : value.getQueryParam().entrySet()) { + gen.writeStringField(entry.getKey(), entry.getValue()); + } + gen.writeEndObject(); + gen.writeStartObject(); + for (final Map.Entry entry : value.getHeaderParam().entrySet()) { + gen.writeStringField(entry.getKey(), entry.getValue()); + } + gen.writeEndObject(); + gen.writeEndArray(); + } + }; + static final JsonSerializer COLLECTION_TYPE = new JsonSerializer() { + @Override + public void serialize(CollectionType value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeNumber(value.getType()); + } + }; + + private InternalSerializers() { + } + + public static class CollectionSchemaRuleSerializer extends JsonSerializer { + @Override + public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeTree(SerdeUtils.INSTANCE.parseJson(value)); + } + } + + public static class FieldLinksSerializer extends JsonSerializer> { + @Override + public void serialize(Collection value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + Map mapLikeValue = new HashMap<>(); + for (FieldLink fl : value) { + mapLikeValue.put(fl.getName(), fl); + } + gen.writeObject(mapLikeValue); + } + } + + public static class CollectionLinksSerializer extends JsonSerializer> { + @Override + public void serialize(Collection value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + Map mapLikeValue = new HashMap<>(); + for (CollectionLink cl : value) { + mapLikeValue.put(cl.getName(), cl); + } + gen.writeObject(mapLikeValue); + } + } + +} diff --git a/core/src/main/java/com/arangodb/internal/serde/SerdeUtils.java b/core/src/main/java/com/arangodb/internal/serde/SerdeUtils.java new file mode 100644 index 000000000..088e0b6d2 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/SerdeUtils.java @@ -0,0 +1,84 @@ +package com.arangodb.internal.serde; + +import com.arangodb.ArangoDBException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.TypeFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public enum SerdeUtils { + INSTANCE; + + private static final Logger LOGGER = LoggerFactory.getLogger(SerdeUtils.class); + + private final ObjectMapper jsonMapper = new ObjectMapper(); + + public static Type constructListType(Class clazz) { + return TypeFactory.defaultInstance().constructCollectionType(List.class, clazz); + } + + public static Type constructParametricType(Class rawType, Type... rawArgs) { + if (rawArgs == null || rawArgs.length == 0 || rawArgs[0] == null) { + return rawType; + } else { + return new InternalParameterizedType(rawType, rawArgs); + } + } + + public static Type convertToType(final JavaType javaType) { + List args = new ArrayList<>(); + for (JavaType it : javaType.getBindings().getTypeParameters()) { + Type type = convertToType(it); + args.add(type); + } + return constructParametricType(javaType.getRawClass(), args.toArray(new Type[0])); + } + + static void checkSupportedJacksonVersion() { + Arrays.asList( + com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION, + com.fasterxml.jackson.core.json.PackageVersion.VERSION + ).forEach(version -> { + int major = version.getMajorVersion(); + int minor = version.getMinorVersion(); + if (major != 2 || minor < 10 || minor > 14) { + LOGGER.warn("Unsupported Jackson version: {}", version); + } + }); + } + + /** + * Parse a JSON string. + * + * @param json JSON string to parse + * @return root of the parsed tree + */ + public JsonNode parseJson(final String json) { + try { + return jsonMapper.readTree(json); + } catch (JsonProcessingException e) { + throw new ArangoDBException(e); + } + } + + /** + * @param data JsonNode + * @return JSON string + */ + public String writeJson(final JsonNode data) { + try { + return jsonMapper.writeValueAsString(data); + } catch (JsonProcessingException e) { + throw new ArangoDBException(e); + } + } + +} diff --git a/core/src/main/java/com/arangodb/internal/serde/UserData.java b/core/src/main/java/com/arangodb/internal/serde/UserData.java new file mode 100644 index 000000000..da9f7dc86 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/UserData.java @@ -0,0 +1,14 @@ +package com.arangodb.internal.serde; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation for fields that need to be serialized/deserialized using the user serde. + */ +@Target({ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface UserData { +} diff --git a/core/src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java b/core/src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java new file mode 100644 index 000000000..91220088b --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/UserDataDeserializer.java @@ -0,0 +1,44 @@ +package com.arangodb.internal.serde; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.deser.ContextualDeserializer; +import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; + +import java.io.IOException; +import java.lang.reflect.Type; + +import static com.arangodb.internal.serde.SerdeUtils.convertToType; + +class UserDataDeserializer extends JsonDeserializer implements ContextualDeserializer { + private final Type targetType; + private final InternalSerde serde; + + UserDataDeserializer(final InternalSerde serde) { + targetType = null; + this.serde = serde; + } + + private UserDataDeserializer(final JavaType targetType, final InternalSerde serde) { + this.targetType = convertToType(targetType); + this.serde = serde; + } + + @Override + public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + return serde.deserializeUserData(p.readValueAsTree(), targetType); + } + + @Override + public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { + return deserialize(p, ctxt); + } + + @Override + public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) { + return new UserDataDeserializer(ctxt.getContextualType(), serde); + } +} diff --git a/core/src/main/java/com/arangodb/internal/serde/UserDataInside.java b/core/src/main/java/com/arangodb/internal/serde/UserDataInside.java new file mode 100644 index 000000000..cdfd83b43 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/UserDataInside.java @@ -0,0 +1,19 @@ +package com.arangodb.internal.serde; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation for collections or map fields whose values need to be serialized/deserialized using the user serde. + */ +@Target({ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@JsonInclude(value = JsonInclude.Include.NON_NULL) +@JacksonAnnotationsInside +public @interface UserDataInside { +} diff --git a/core/src/main/java/com/arangodb/internal/serde/UserDataSerializer.java b/core/src/main/java/com/arangodb/internal/serde/UserDataSerializer.java new file mode 100644 index 000000000..351c0e460 --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/serde/UserDataSerializer.java @@ -0,0 +1,25 @@ +package com.arangodb.internal.serde; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +class UserDataSerializer extends JsonSerializer { + private final InternalSerde serde; + + UserDataSerializer(InternalSerde serde) { + this.serde = serde; + } + + @Override + public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + // TODO: find a way to append raw bytes directly + // see https://github.com/FasterXML/jackson-dataformats-binary/issues/331 + try (JsonParser parser = gen.getCodec().getFactory().createParser(serde.serializeUserData(value))) { + gen.writeTree(parser.readValueAsTree()); + } + } +} diff --git a/src/main/java/com/arangodb/internal/util/DocumentUtil.java b/core/src/main/java/com/arangodb/internal/util/DocumentUtil.java similarity index 87% rename from src/main/java/com/arangodb/internal/util/DocumentUtil.java rename to core/src/main/java/com/arangodb/internal/util/DocumentUtil.java index fb108d91c..239ad7371 100644 --- a/src/main/java/com/arangodb/internal/util/DocumentUtil.java +++ b/core/src/main/java/com/arangodb/internal/util/DocumentUtil.java @@ -29,9 +29,9 @@ */ public final class DocumentUtil { - private static final String SLASH = "/"; public static final String REGEX_KEY = "[^/]+"; public static final String REGEX_ID = "[^/]+/[^/]+"; + private static final String SLASH = "/"; private DocumentUtil() { super(); @@ -41,11 +41,11 @@ public static void validateIndexId(final String id) { validateName("index id", REGEX_ID, id); } - public static void validateDocumentKey(final String key) throws ArangoDBException { + public static void validateDocumentKey(final String key) { validateName("document key", REGEX_KEY, key); } - public static void validateDocumentId(final String id) throws ArangoDBException { + public static void validateDocumentId(final String id) { validateName("document id", REGEX_ID, id); } @@ -54,8 +54,7 @@ public static String createDocumentHandle(final String collection, final String return collection + SLASH + key; } - private static void validateName(final String type, final String regex, final CharSequence name) - throws ArangoDBException { + private static void validateName(final String type, final String regex, final CharSequence name) { if (!Pattern.matches(regex, name)) { throw new ArangoDBException(String.format("%s %s is not valid.", type, name)); } diff --git a/src/main/java/com/arangodb/internal/util/EncodeUtils.java b/core/src/main/java/com/arangodb/internal/util/EncodeUtils.java similarity index 100% rename from src/main/java/com/arangodb/internal/util/EncodeUtils.java rename to core/src/main/java/com/arangodb/internal/util/EncodeUtils.java diff --git a/src/main/java/com/arangodb/internal/util/HostUtils.java b/core/src/main/java/com/arangodb/internal/util/HostUtils.java similarity index 90% rename from src/main/java/com/arangodb/internal/util/HostUtils.java rename to core/src/main/java/com/arangodb/internal/util/HostUtils.java index 094830f5f..591ed91af 100644 --- a/src/main/java/com/arangodb/internal/util/HostUtils.java +++ b/core/src/main/java/com/arangodb/internal/util/HostUtils.java @@ -20,6 +20,8 @@ package com.arangodb.internal.util; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.*; /** @@ -44,8 +46,8 @@ public static HostDescription createFromLocation(final String location) { public static Host createHost( final HostDescription description, - final int maxConnections, + final ArangoConfig config, final ConnectionFactory factory) { - return new HostImpl(new ConnectionPoolImpl(description, maxConnections, factory), description); + return new HostImpl(new ConnectionPoolImpl(description, config, factory), description); } } diff --git a/src/main/java/com/arangodb/internal/util/RequestUtils.java b/core/src/main/java/com/arangodb/internal/util/RequestUtils.java similarity index 74% rename from src/main/java/com/arangodb/internal/util/RequestUtils.java rename to core/src/main/java/com/arangodb/internal/util/RequestUtils.java index 2b5f56b47..7074cfc3b 100644 --- a/src/main/java/com/arangodb/internal/util/RequestUtils.java +++ b/core/src/main/java/com/arangodb/internal/util/RequestUtils.java @@ -21,26 +21,26 @@ package com.arangodb.internal.util; import com.arangodb.internal.net.AccessType; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.RequestType; /** * @author Mark Vollmary */ public final class RequestUtils { - public static final String HEADER_ALLOW_DIRTY_READ = "X-Arango-Allow-Dirty-Read"; + public static final String HEADER_ALLOW_DIRTY_READ = "x-arango-allow-dirty-read"; private RequestUtils() { super(); } - public static Request allowDirtyRead(final Request request) { + public static InternalRequest allowDirtyRead(final InternalRequest request) { return request.putHeaderParam(HEADER_ALLOW_DIRTY_READ, "true"); } - public static AccessType determineAccessType(final Request request) { - if (request.getHeaderParam().containsKey(HEADER_ALLOW_DIRTY_READ)) { + public static AccessType determineAccessType(final InternalRequest request) { + if (request.containsHeaderParam(HEADER_ALLOW_DIRTY_READ)) { return AccessType.DIRTY_READ; } if (request.getRequestType() == RequestType.GET) { diff --git a/core/src/main/java/com/arangodb/internal/util/ResponseUtils.java b/core/src/main/java/com/arangodb/internal/util/ResponseUtils.java new file mode 100644 index 000000000..73030fc8c --- /dev/null +++ b/core/src/main/java/com/arangodb/internal/util/ResponseUtils.java @@ -0,0 +1,63 @@ +/* + * DISCLAIMER + * + * Copyright 2017 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal.util; + +import com.arangodb.ArangoDBException; +import com.arangodb.entity.ErrorEntity; +import com.arangodb.internal.ArangoErrors; +import com.arangodb.internal.net.ArangoDBRedirectException; +import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.InternalResponse; + +import java.util.concurrent.TimeoutException; + +/** + * @author Mark Vollmary + */ +public final class ResponseUtils { + + private static final int ERROR_STATUS = 300; + private static final int ERROR_INTERNAL = 503; + private static final String HEADER_ENDPOINT = "x-arango-endpoint"; + + private ResponseUtils() { + super(); + } + + public static void checkError(final InternalSerde util, final InternalResponse response) { + final int responseCode = response.getResponseCode(); + if (responseCode >= ERROR_STATUS) { + if (responseCode == ERROR_INTERNAL && response.containsMeta(HEADER_ENDPOINT)) { + throw new ArangoDBRedirectException(String.format("Response Code: %s", responseCode), + response.getMeta(HEADER_ENDPOINT)); + } else if (response.getBody() != null) { + final ErrorEntity errorEntity = util.deserialize(response.getBody(), ErrorEntity.class); + ArangoDBException e = new ArangoDBException(errorEntity); + if (ArangoErrors.QUEUE_TIME_VIOLATED.equals(e.getErrorNum())) { + throw new ArangoDBException(new TimeoutException().initCause(e)); + } + throw e; + } else { + throw new ArangoDBException(String.format("Response Code: %s", responseCode), responseCode); + } + } + } +} diff --git a/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java b/core/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java similarity index 80% rename from src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java rename to core/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java index a1897c491..14c7fe999 100644 --- a/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java +++ b/core/src/main/java/com/arangodb/model/AqlFunctionCreateOptions.java @@ -1,79 +1,81 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public class AqlFunctionCreateOptions { - - private String name; - private String code; - private Boolean isDeterministic; - - public AqlFunctionCreateOptions() { - super(); - } - - /** - * @param name the fully qualified name of the user functions - * @return options - */ - protected AqlFunctionCreateOptions name(final String name) { - this.name = name; - return this; - } - - protected String getName() { - return name; - } - - /** - * @param code a string representation of the function body - * @return options - */ - protected AqlFunctionCreateOptions code(final String code) { - this.code = code; - return this; - } - - protected String getCode() { - return code; - } - - /** - * @param isDeterministic an optional boolean value to indicate that the function results are fully deterministic (function - * return value solely depends on the input value and return value is the same for repeated calls with - * same input) - * @return options - */ - public AqlFunctionCreateOptions isDeterministic(final Boolean isDeterministic) { - this.isDeterministic = isDeterministic; - return this; - } - - public Boolean getIsDeterministic() { - return isDeterministic; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class AqlFunctionCreateOptions { + + private String name; + private String code; + private Boolean isDeterministic; + + public AqlFunctionCreateOptions() { + super(); + } + + /** + * @param name the fully qualified name of the user functions + * @return options + */ + AqlFunctionCreateOptions name(final String name) { + this.name = name; + return this; + } + + public String getName() { + return name; + } + + /** + * @param code a string representation of the function body + * @return options + */ + AqlFunctionCreateOptions code(final String code) { + this.code = code; + return this; + } + + public String getCode() { + return code; + } + + /** + * @param isDeterministic an optional boolean value to indicate that the function results are fully deterministic + * (function + * return value solely depends on the input value and return value is the same for + * repeated calls with + * same input) + * @return options + */ + public AqlFunctionCreateOptions isDeterministic(final Boolean isDeterministic) { + this.isDeterministic = isDeterministic; + return this; + } + + public Boolean getIsDeterministic() { + return isDeterministic; + } + +} diff --git a/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java b/core/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java similarity index 94% rename from src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java rename to core/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java index dd3cd2901..42affff7a 100644 --- a/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java +++ b/core/src/main/java/com/arangodb/model/AqlFunctionDeleteOptions.java @@ -1,52 +1,52 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public class AqlFunctionDeleteOptions { - - private Boolean group; - - public AqlFunctionDeleteOptions() { - super(); - } - - public Boolean getGroup() { - return group; - } - - /** - * @param group If set to true, then the function name provided in name is treated as a namespace prefix, and all - * functions in the specified namespace will be deleted. If set to false, the function name provided in - * name must be fully qualified, including any namespaces. - * @return options - */ - public AqlFunctionDeleteOptions group(final Boolean group) { - this.group = group; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class AqlFunctionDeleteOptions { + + private Boolean group; + + public AqlFunctionDeleteOptions() { + super(); + } + + public Boolean getGroup() { + return group; + } + + /** + * @param group If set to true, then the function name provided in name is treated as a namespace prefix, and all + * functions in the specified namespace will be deleted. If set to false, the function name provided in + * name must be fully qualified, including any namespaces. + * @return options + */ + public AqlFunctionDeleteOptions group(final Boolean group) { + this.group = group; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java b/core/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java similarity index 91% rename from src/main/java/com/arangodb/model/AqlFunctionGetOptions.java rename to core/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java index 2b4713ddb..87146d99d 100644 --- a/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java +++ b/core/src/main/java/com/arangodb/model/AqlFunctionGetOptions.java @@ -1,50 +1,50 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public class AqlFunctionGetOptions { - - private String namespace; - - public AqlFunctionGetOptions() { - super(); - } - - public String getNamespace() { - return namespace; - } - - /** - * @param namespace Returns all registered AQL user functions from namespace namespace - * @return options - */ - public AqlFunctionGetOptions namespace(final String namespace) { - this.namespace = namespace; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class AqlFunctionGetOptions { + + private String namespace; + + public AqlFunctionGetOptions() { + super(); + } + + public String getNamespace() { + return namespace; + } + + /** + * @param namespace Returns all registered AQL user functions from namespace + * @return options + */ + public AqlFunctionGetOptions namespace(final String namespace) { + this.namespace = namespace; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java b/core/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java similarity index 82% rename from src/main/java/com/arangodb/model/AqlQueryExplainOptions.java rename to core/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java index 27b962465..0c7d4bfff 100644 --- a/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java +++ b/core/src/main/java/com/arangodb/model/AqlQueryExplainOptions.java @@ -1,133 +1,137 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.velocypack.VPackSlice; - -import java.util.Collection; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - * @see API Documentation - */ -public class AqlQueryExplainOptions { - - private VPackSlice bindVars; - private String query; - private Options options; - - public AqlQueryExplainOptions() { - super(); - } - - protected VPackSlice getBindVars() { - return bindVars; - } - - /** - * @param bindVars key/value pairs representing the bind parameters - * @return options - */ - protected AqlQueryExplainOptions bindVars(final VPackSlice bindVars) { - this.bindVars = bindVars; - return this; - } - - protected String getQuery() { - return query; - } - - /** - * @param query the query which you want explained - * @return options - */ - protected AqlQueryExplainOptions query(final String query) { - this.query = query; - return this; - } - - public Integer getMaxNumberOfPlans() { - return getOptions().maxNumberOfPlans; - } - - /** - * @param maxNumberOfPlans an optional maximum number of plans that the optimizer is allowed to generate. Setting this attribute - * to a low value allows to put a cap on the amount of work the optimizer does. - * @return options - */ - public AqlQueryExplainOptions maxNumberOfPlans(final Integer maxNumberOfPlans) { - getOptions().maxNumberOfPlans = maxNumberOfPlans; - return this; - } - - public Boolean getAllPlans() { - return getOptions().allPlans; - } - - /** - * @param allPlans if set to true, all possible execution plans will be returned. The default is false, meaning only the - * optimal plan will be returned. - * @return options - */ - public AqlQueryExplainOptions allPlans(final Boolean allPlans) { - getOptions().allPlans = allPlans; - return this; - } - - public Collection getRules() { - return getOptions().getOptimizer().rules; - } - - /** - * @param rules an array of to-be-included or to-be-excluded optimizer rules can be put into this attribute, telling - * the optimizer to include or exclude specific rules. - * @return options - */ - public AqlQueryExplainOptions rules(final Collection rules) { - getOptions().getOptimizer().rules = rules; - return this; - } - - private Options getOptions() { - if (options == null) { - options = new Options(); - } - return options; - } - - public static class Options { - private Optimizer optimizer; - private Integer maxNumberOfPlans; - private Boolean allPlans; - - protected Optimizer getOptimizer() { - if (optimizer == null) { - optimizer = new Optimizer(); - } - return optimizer; - } - } - - public static class Optimizer { - private Collection rules; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.internal.serde.UserDataInside; + +import java.util.Collection; +import java.util.Map; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + * @see API Documentation + */ +public final class AqlQueryExplainOptions { + + private Map bindVars; + private String query; + private Options options; + + public AqlQueryExplainOptions() { + super(); + } + + @UserDataInside + public Map getBindVars() { + return bindVars; + } + + /** + * @param bindVars key/value pairs representing the bind parameters + * @return options + */ + AqlQueryExplainOptions bindVars(final Map bindVars) { + this.bindVars = bindVars; + return this; + } + + public String getQuery() { + return query; + } + + /** + * @param query the query which you want explained + * @return options + */ + AqlQueryExplainOptions query(final String query) { + this.query = query; + return this; + } + + public Integer getMaxNumberOfPlans() { + return getOptions().maxNumberOfPlans; + } + + /** + * @param maxNumberOfPlans an optional maximum number of plans that the optimizer is allowed to generate. Setting + * this attribute + * to a low value allows to put a cap on the amount of work the optimizer does. + * @return options + */ + public AqlQueryExplainOptions maxNumberOfPlans(final Integer maxNumberOfPlans) { + getOptions().maxNumberOfPlans = maxNumberOfPlans; + return this; + } + + public Boolean getAllPlans() { + return getOptions().allPlans; + } + + /** + * @param allPlans if set to true, all possible execution plans will be returned. The default is false, meaning + * only the + * optimal plan will be returned. + * @return options + */ + public AqlQueryExplainOptions allPlans(final Boolean allPlans) { + getOptions().allPlans = allPlans; + return this; + } + + public Collection getRules() { + return getOptions().getOptimizer().rules; + } + + /** + * @param rules an array of to-be-included or to-be-excluded optimizer rules can be put into this attribute, telling + * the optimizer to include or exclude specific rules. + * @return options + */ + public AqlQueryExplainOptions rules(final Collection rules) { + getOptions().getOptimizer().rules = rules; + return this; + } + + private Options getOptions() { + if (options == null) { + options = new Options(); + } + return options; + } + + public static final class Options { + private Optimizer optimizer; + private Integer maxNumberOfPlans; + private Boolean allPlans; + + public Optimizer getOptimizer() { + if (optimizer == null) { + optimizer = new Optimizer(); + } + return optimizer; + } + } + + public static final class Optimizer { + private Collection rules; + } +} diff --git a/src/main/java/com/arangodb/model/AqlQueryOptions.java b/core/src/main/java/com/arangodb/model/AqlQueryOptions.java similarity index 71% rename from src/main/java/com/arangodb/model/AqlQueryOptions.java rename to core/src/main/java/com/arangodb/model/AqlQueryOptions.java index 52e344663..27921a4f8 100644 --- a/src/main/java/com/arangodb/model/AqlQueryOptions.java +++ b/core/src/main/java/com/arangodb/model/AqlQueryOptions.java @@ -20,13 +20,11 @@ package com.arangodb.model; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.annotations.Expose; +import com.arangodb.internal.serde.UserDataInside; -import java.io.Serializable; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Map; /** * @author Mark Vollmary @@ -34,20 +32,16 @@ * @see API * Documentation */ -public class AqlQueryOptions implements Serializable { - - private static final long serialVersionUID = 1L; +public final class AqlQueryOptions { private Boolean count; private Integer ttl; private Integer batchSize; private Boolean cache; - private Boolean fillBlockCache; private Long memoryLimit; - private VPackSlice bindVars; + private Map bindVars; private String query; private Options options; - @Expose(serialize = false) private Boolean allowDirtyRead; private String streamTransactionId; @@ -91,8 +85,10 @@ public Integer getBatchSize() { } /** - * @param batchSize maximum number of result documents to be transferred from the server to the client in one roundtrip. - * If this attribute is not set, a server-controlled default value will be used. A batchSize value of 0 + * @param batchSize maximum number of result documents to be transferred from the server to the client in one + * roundtrip. + * If this attribute is not set, a server-controlled default value will be used. A batchSize + * value of 0 * is disallowed. * @return options */ @@ -106,8 +102,10 @@ public Long getMemoryLimit() { } /** - * @param memoryLimit the maximum number of memory (measured in bytes) that the query is allowed to use. If set, then the - * query will fail with error "resource limit exceeded" in case it allocates too much memory. A value of + * @param memoryLimit the maximum number of memory (measured in bytes) that the query is allowed to use. If set, + * then the + * query will fail with error "resource limit exceeded" in case it allocates too much memory. + * A value of * 0 indicates that there is no memory limit. * @return options * @since ArangoDB 3.1.0 @@ -133,7 +131,7 @@ public AqlQueryOptions cache(final Boolean cache) { } public Boolean getFillBlockCache() { - return options != null ? options.fillBlockCache : null; + return getOptions().fillBlockCache; } /** @@ -142,7 +140,8 @@ public Boolean getFillBlockCache() { * usually the desired behavior. The option can be set to false for queries that * are known to either read a lot of data that would thrash the block cache, or for queries * that read data known to be outside of the hot set. By setting the option - * to false, data read by the query will not make it into the RocksDB block cache if + * to false, data read by the query will not make it into the RocksDB block + * cache if * it is not already in there, thus leaving more room for the actual hot set. * @return options * @since ArangoDB 3.8.1 @@ -152,20 +151,21 @@ public AqlQueryOptions fillBlockCache(final Boolean fillBlockCache) { return this; } - protected VPackSlice getBindVars() { + @UserDataInside + public Map getBindVars() { return bindVars; } /** - * @param bindVars key/value pairs representing the bind parameters + * @param bindVarsBytes serialized bind parameters * @return options */ - protected AqlQueryOptions bindVars(final VPackSlice bindVars) { - this.bindVars = bindVars; + AqlQueryOptions bindVars(final Map bindVarsBytes) { + this.bindVars = bindVarsBytes; return this; } - protected String getQuery() { + public String getQuery() { return query; } @@ -173,20 +173,24 @@ protected String getQuery() { * @param query the query which you want parse * @return options */ - protected AqlQueryOptions query(final String query) { + public AqlQueryOptions query(final String query) { this.query = query; return this; } public Boolean getFailOnWarning() { - return options != null ? options.failOnWarning : null; + return getOptions().failOnWarning; } /** - * @param failOnWarning When set to true, the query will throw an exception and abort instead of producing a warning. This - * option should be used during development to catch potential issues early. When the attribute is set to - * false, warnings will not be propagated to exceptions and will be returned with the query result. There - * is also a server configuration option --query.fail-on-warning for setting the default value for + * @param failOnWarning When set to true, the query will throw an exception and abort instead of producing a + * warning. This + * option should be used during development to catch potential issues early. When the + * attribute is set to + * false, warnings will not be propagated to exceptions and will be returned with the query + * result. There + * is also a server configuration option --query.fail-on-warning for setting the default + * value for * failOnWarning so it does not need to be set on a per-query level. * @return options */ @@ -210,11 +214,12 @@ public AqlQueryOptions maxRuntime(final Double timeout) { * profile of the extra return attribute if the query result is not served from the query cache. */ public Boolean getProfile() { - return options != null ? options.profile : null; + return getOptions().profile; } /** - * @param profile If set to true, then the additional query profiling information will be returned in the sub-attribute + * @param profile If set to true, then the additional query profiling information will be returned in the + * sub-attribute * profile of the extra return attribute if the query result is not served from the query cache. * @return options */ @@ -224,7 +229,7 @@ public AqlQueryOptions profile(final Boolean profile) { } public Long getMaxTransactionSize() { - return options != null ? options.maxTransactionSize : null; + return getOptions().maxTransactionSize; } /** @@ -238,12 +243,14 @@ public AqlQueryOptions maxTransactionSize(final Long maxTransactionSize) { } public Long getMaxWarningCount() { - return options != null ? options.maxWarningCount : null; + return getOptions().maxWarningCount; } /** - * @param maxWarningCount Limits the maximum number of warnings a query will return. The number of warnings a query will return - * is limited to 10 by default, but that number can be increased or decreased by setting this attribute. + * @param maxWarningCount Limits the maximum number of warnings a query will return. The number of warnings a + * query will return + * is limited to 10 by default, but that number can be increased or decreased by setting + * this attribute. * @return options * @since ArangoDB 3.2.0 */ @@ -253,11 +260,12 @@ public AqlQueryOptions maxWarningCount(final Long maxWarningCount) { } public Long getIntermediateCommitCount() { - return options != null ? options.intermediateCommitCount : null; + return getOptions().intermediateCommitCount; } /** - * @param intermediateCommitCount Maximum number of operations after which an intermediate commit is performed automatically. Honored by + * @param intermediateCommitCount Maximum number of operations after which an intermediate commit is performed + * automatically. Honored by * the RocksDB storage engine only. * @return options * @since ArangoDB 3.2.0 @@ -268,11 +276,12 @@ public AqlQueryOptions intermediateCommitCount(final Long intermediateCommitCoun } public Long getIntermediateCommitSize() { - return options != null ? options.intermediateCommitSize : null; + return getOptions().intermediateCommitSize; } /** - * @param intermediateCommitSize Maximum total size of operations after which an intermediate commit is performed automatically. + * @param intermediateCommitSize Maximum total size of operations after which an intermediate commit is performed + * automatically. * Honored by the RocksDB storage engine only. * @return options * @since ArangoDB 3.2.0 @@ -283,12 +292,14 @@ public AqlQueryOptions intermediateCommitSize(final Long intermediateCommitSize) } public Double getSatelliteSyncWait() { - return options != null ? options.satelliteSyncWait : null; + return getOptions().satelliteSyncWait; } /** - * @param satelliteSyncWait This enterprise parameter allows to configure how long a DBServer will have time to bring the - * satellite collections involved in the query into sync. The default value is 60.0 (seconds). When the + * @param satelliteSyncWait This enterprise parameter allows to configure how long a DBServer will have time to + * bring the + * satellite collections involved in the query into sync. The default value is 60.0 + * (seconds). When the * max time has been reached the query will be stopped. * @return options * @since ArangoDB 3.2.0 @@ -299,15 +310,20 @@ public AqlQueryOptions satelliteSyncWait(final Double satelliteSyncWait) { } public Boolean getSkipInaccessibleCollections() { - return options != null ? options.skipInaccessibleCollections : null; + return getOptions().skipInaccessibleCollections; } /** - * @param skipInaccessibleCollections AQL queries (especially graph traversals) will treat collection to which a user has no access rights - * as if these collections were empty. Instead of returning a forbidden access error, your queries will - * execute normally. This is intended to help with certain use-cases: A graph contains several - * collections and different users execute AQL queries on that graph. You can now naturally limit the - * accessible results by changing the access rights of users on collections. This feature is only + * @param skipInaccessibleCollections AQL queries (especially graph traversals) will treat collection to which a + * user has no access rights + * as if these collections were empty. Instead of returning a forbidden access + * error, your queries will + * execute normally. This is intended to help with certain use-cases: A graph + * contains several + * collections and different users execute AQL queries on that graph. You can + * now naturally limit the + * accessible results by changing the access rights of users on collections. + * This feature is only * available in the Enterprise Edition. * @return options * @since ArangoDB 3.2.0 @@ -318,18 +334,26 @@ public AqlQueryOptions skipInaccessibleCollections(final Boolean skipInaccessibl } public Boolean getFullCount() { - return options != null ? options.fullCount : null; + return getOptions().fullCount; } /** - * @param fullCount if set to true and the query contains a LIMIT clause, then the result will have an extra attribute - * with the sub-attributes stats and fullCount, { ... , "extra": { "stats": { "fullCount": 123 } } }. The - * fullCount attribute will contain the number of documents in the result before the last LIMIT in the - * query was applied. It can be used to count the number of documents that match certain filter criteria, - * but only return a subset of them, in one go. It is thus similar to MySQL's SQL_CALC_FOUND_ROWS hint. - * Note that setting the option will disable a few LIMIT optimizations and may lead to more documents - * being processed, and thus make queries run longer. Note that the fullCount attribute will only be - * present in the result if the query has a LIMIT clause and the LIMIT clause is actually used in the + * @param fullCount if set to true and the query contains a LIMIT clause, then the result will have an extra + * attribute + * with the sub-attributes stats and fullCount, { ... , "extra": { "stats": { "fullCount": 123 } + * } }. The + * fullCount attribute will contain the number of documents in the result before the last LIMIT + * in the + * query was applied. It can be used to count the number of documents that match certain filter + * criteria, + * but only return a subset of them, in one go. It is thus similar to MySQL's + * SQL_CALC_FOUND_ROWS hint. + * Note that setting the option will disable a few LIMIT optimizations and may lead to more + * documents + * being processed, and thus make queries run longer. Note that the fullCount attribute will + * only be + * present in the result if the query has a LIMIT clause and the LIMIT clause is actually used + * in the * query. * @return options */ @@ -339,7 +363,7 @@ public AqlQueryOptions fullCount(final Boolean fullCount) { } public Integer getMaxPlans() { - return options != null ? options.maxPlans : null; + return getOptions().maxPlans; } /** @@ -352,12 +376,14 @@ public AqlQueryOptions maxPlans(final Integer maxPlans) { } public Collection getRules() { - return options != null ? options.optimizer != null ? options.optimizer.rules : null : null; + return getOptions().getOptimizer().rules; } /** - * @param rules A list of to-be-included or to-be-excluded optimizer rules can be put into this attribute, telling the - * optimizer to include or exclude specific rules. To disable a rule, prefix its name with a -, to enable + * @param rules A list of to-be-included or to-be-excluded optimizer rules can be put into this attribute, + * telling the + * optimizer to include or exclude specific rules. To disable a rule, prefix its name with a -, to + * enable * a rule, prefix it with a +. There is also a pseudo-rule all, which will match all optimizer rules * @return options */ @@ -367,17 +393,21 @@ public AqlQueryOptions rules(final Collection rules) { } public Boolean getStream() { - return options != null ? options.stream : null; + return getOptions().stream; } /** - * @param stream Specify true and the query will be executed in a streaming fashion. The query result is not stored on - * the server, but calculated on the fly. Beware: long-running queries will need to hold the collection - * locks for as long as the query cursor exists. When set to false a query will be executed right away in + * @param stream Specify true and the query will be executed in a streaming fashion. The query result is not + * stored on + * the server, but calculated on the fly. Beware: long-running queries will need to hold the + * collection + * locks for as long as the query cursor exists. When set to false a query will be executed right + * away in * its entirety. In that case query results are either returned right away (if the resultset is small * enough), or stored on the arangod instance and accessible via the cursor API (with respect to the * ttl). It is advisable to only use this option on short-running queries or without exclusive locks - * (write-locks on MMFiles). Please note that the query options cache, count and fullCount will not work + * (write-locks on MMFiles). Please note that the query options cache, count and fullCount will not + * work * on streaming queries. Additionally query statistics, warnings and profiling data will only be * available after the query is finished. The default value is false * @return options @@ -389,7 +419,7 @@ public AqlQueryOptions stream(final Boolean stream) { } public Collection getShardIds() { - return options != null ? options.shardIds : null; + return getOptions().shardIds; } /** @@ -399,20 +429,48 @@ public Collection getShardIds() { * @return options */ public AqlQueryOptions shardIds(final String... shardIds) { - getOptions().getShardIds().addAll(Arrays.asList(shardIds)); + getOptions().shardIds = Arrays.asList(shardIds); return this; } - private Options getOptions() { + public Options getOptions() { if (options == null) { options = new Options(); } return options; } - public static class Options implements Serializable { + /** + * @param allowDirtyRead Set to {@code true} allows reading from followers in an active-failover setup. + * @return options + * @see API + * Documentation + * @since ArangoDB 3.4.0 + */ + public AqlQueryOptions allowDirtyRead(final Boolean allowDirtyRead) { + this.allowDirtyRead = allowDirtyRead; + return this; + } + + public Boolean getAllowDirtyRead() { + return allowDirtyRead; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.0 + */ + public AqlQueryOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } - private static final long serialVersionUID = 1L; + public static final class Options { private Boolean failOnWarning; private Boolean profile; @@ -430,54 +488,77 @@ public static class Options implements Serializable { private Double maxRuntime; private Boolean fillBlockCache; - protected Optimizer getOptimizer() { + public Boolean getFailOnWarning() { + return failOnWarning; + } + + public Boolean getProfile() { + return profile; + } + + public Long getMaxTransactionSize() { + return maxTransactionSize; + } + + public Long getMaxWarningCount() { + return maxWarningCount; + } + + public Long getIntermediateCommitCount() { + return intermediateCommitCount; + } + + public Long getIntermediateCommitSize() { + return intermediateCommitSize; + } + + public Double getSatelliteSyncWait() { + return satelliteSyncWait; + } + + public Boolean getSkipInaccessibleCollections() { + return skipInaccessibleCollections; + } + + public Boolean getFullCount() { + return fullCount; + } + + public Integer getMaxPlans() { + return maxPlans; + } + + public Boolean getStream() { + return stream; + } + + public Double getMaxRuntime() { + return maxRuntime; + } + + public Boolean getFillBlockCache() { + return fillBlockCache; + } + + public Optimizer getOptimizer() { if (optimizer == null) { optimizer = new Optimizer(); } return optimizer; } - protected Collection getShardIds() { - if (shardIds == null) { - shardIds = new ArrayList<>(); - } + public Collection getShardIds() { return shardIds; } } - public static class Optimizer { + public static final class Optimizer { private Collection rules; - } - /** - * @param allowDirtyRead Set to {@code true} allows reading from followers in an active-failover setup. - * @return options - * @see API - * Documentation - * @since ArangoDB 3.4.0 - */ - public AqlQueryOptions allowDirtyRead(final Boolean allowDirtyRead) { - this.allowDirtyRead = allowDirtyRead; - return this; - } - - public Boolean getAllowDirtyRead() { - return allowDirtyRead; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.0 - */ - public AqlQueryOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; + public Collection getRules() { + return rules; + } } } diff --git a/src/main/java/com/arangodb/model/AqlQueryParseOptions.java b/core/src/main/java/com/arangodb/model/AqlQueryParseOptions.java similarity index 86% rename from src/main/java/com/arangodb/model/AqlQueryParseOptions.java rename to core/src/main/java/com/arangodb/model/AqlQueryParseOptions.java index b2194779c..064fa0685 100644 --- a/src/main/java/com/arangodb/model/AqlQueryParseOptions.java +++ b/core/src/main/java/com/arangodb/model/AqlQueryParseOptions.java @@ -1,48 +1,48 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class AqlQueryParseOptions { - - private String query; - - public AqlQueryParseOptions() { - super(); - } - - protected String getQuery() { - return query; - } - - /** - * @param query the query which you want parse - * @return options - */ - protected AqlQueryParseOptions query(final String query) { - this.query = query; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class AqlQueryParseOptions { + + private String query; + + public AqlQueryParseOptions() { + super(); + } + + public String getQuery() { + return query; + } + + /** + * @param query the query which you want parse + * @return options + */ + AqlQueryParseOptions query(final String query) { + this.query = query; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/CollectionCountOptions.java b/core/src/main/java/com/arangodb/model/CollectionCountOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/CollectionCountOptions.java rename to core/src/main/java/com/arangodb/model/CollectionCountOptions.java index 6030f1db8..edfc64eaa 100644 --- a/src/main/java/com/arangodb/model/CollectionCountOptions.java +++ b/core/src/main/java/com/arangodb/model/CollectionCountOptions.java @@ -23,7 +23,7 @@ /** * @author Michele Rastelli */ -public class CollectionCountOptions { +public final class CollectionCountOptions { private String streamTransactionId; diff --git a/core/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/core/src/main/java/com/arangodb/model/CollectionCreateOptions.java new file mode 100644 index 000000000..89ed62e93 --- /dev/null +++ b/core/src/main/java/com/arangodb/model/CollectionCreateOptions.java @@ -0,0 +1,303 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import java.util.Arrays; +import java.util.Collection; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class CollectionCreateOptions { + + private String name; + private ReplicationFactor replicationFactor; + private Integer writeConcern; + private KeyOptions keyOptions; + private Boolean waitForSync; + private final List computedValues = new ArrayList<>(); + private Collection shardKeys; + private Integer numberOfShards; + private Boolean isSystem; + private CollectionType type; + private String distributeShardsLike; + + private String shardingStrategy; // cluster option + private String smartJoinAttribute; // enterprise option + + private CollectionSchema schema; + + public CollectionCreateOptions() { + super(); + } + + public String getName() { + return name; + } + + /** + * @param name The name of the collection + * @return options + */ + CollectionCreateOptions name(final String name) { + this.name = name; + return this; + } + + public ReplicationFactor getReplicationFactor() { + return replicationFactor; + } + + /** + * @param replicationFactor (The default is 1): in a cluster, this attribute determines how many copies of each + * shard are kept on + * different DBServers. The value 1 means that only one copy (no synchronous + * replication) is kept. A + * value of k means that k-1 replicas are kept. Any two copies reside on different + * DBServers. Replication + * between them is synchronous, that is, every write operation to the "leader" copy will + * be replicated to + * all "follower" replicas, before the write operation is reported successful. If a + * server fails, this is + * detected automatically and one of the servers holding copies take over, usually + * without an error being + * reported. + * @return options + */ + public CollectionCreateOptions replicationFactor(final ReplicationFactor replicationFactor) { + this.replicationFactor = replicationFactor; + return this; + } + + public CollectionCreateOptions replicationFactor(int replicationFactor) { + this.replicationFactor = ReplicationFactor.of(replicationFactor); + return this; + } + + public Integer getWriteConcern() { + return writeConcern; + } + + /** + * @param writeConcern write concern for this collection (default: 1). + * It determines how many copies of each shard are required to be in sync on the different + * DB-Servers. If there are less then these many copies in the cluster a shard will refuse to + * write. Writes to shards with enough up-to-date copies will succeed at the same time however. + * The value of writeConcern can not be larger than replicationFactor. (cluster only) + * @return options + */ + public CollectionCreateOptions writeConcern(final Integer writeConcern) { + this.writeConcern = writeConcern; + return this; + } + + public KeyOptions getKeyOptions() { + return keyOptions; + } + + /** + * @param allowUserKeys if set to true, then it is allowed to supply own key values in the _key attribute of a + * document. If + * set to false, then the key generator will solely be responsible for generating keys and + * supplying own + * key values in the _key attribute of documents is considered an error. + * @param type specifies the type of the key generator. The currently available generators are + * traditional and + * autoincrement. + * @param increment increment value for autoincrement key generator. Not used for other key generator types. + * @param offset Initial offset value for autoincrement key generator. Not used for other key generator + * types. + * @return options + */ + public CollectionCreateOptions keyOptions( + final Boolean allowUserKeys, + final KeyType type, + final Integer increment, + final Integer offset) { + this.keyOptions = new KeyOptions(allowUserKeys, type, increment, offset); + return this; + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync If true then the data is synchronized to disk before returning from a document create, + * update, replace + * or removal operation. (default: false) + * @return options + */ + public CollectionCreateOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public Collection getShardKeys() { + return shardKeys; + } + + /** + * @param shardKeys (The default is [ "_key" ]): in a cluster, this attribute determines which document + * attributes are + * used to determine the target shard for documents. Documents are sent to shards based on the + * values of + * their shard key attributes. The values of all shard key attributes in a document are hashed, + * and the + * hash value is used to determine the target shard. Note: Values of shard key attributes cannot be + * changed once set. This option is meaningless in a single server setup. + * @return options + */ + public CollectionCreateOptions shardKeys(final String... shardKeys) { + this.shardKeys = Arrays.asList(shardKeys); + return this; + } + + /** + * @param smartJoinAttribute + * @return options + */ + public CollectionCreateOptions smartJoinAttribute(final String smartJoinAttribute) { + this.smartJoinAttribute = smartJoinAttribute; + return this; + } + + public String getSmartJoinAttribute() { + return smartJoinAttribute; + } + + /** + * @param shardingStrategy + * @return options + */ + public CollectionCreateOptions shardingStrategy(final String shardingStrategy) { + this.shardingStrategy = shardingStrategy; + return this; + } + + public String getShardingStrategy() { + return shardingStrategy; + } + + /** + * @param numberOfShards (The default is 1): in a cluster, this value determines the number of shards to create + * for the + * collection. In a single server setup, this option is meaningless. + * @return options + */ + public CollectionCreateOptions numberOfShards(final Integer numberOfShards) { + this.numberOfShards = numberOfShards; + return this; + } + + public Integer getNumberOfShards() { + return numberOfShards; + } + + public Boolean getIsSystem() { + return isSystem; + } + + /** + * @param isSystem If true, create a system collection. In this case collection-name should start with an + * underscore. End + * users should normally create non-system collections only. API implementors may be required to + * create + * system collections in very special occasions, but normally a regular collection will do. (The + * default + * is false) + * @return options + */ + public CollectionCreateOptions isSystem(final Boolean isSystem) { + this.isSystem = isSystem; + return this; + } + + public CollectionType getType() { + return type; + } + + /** + * @param type (The default is {@link CollectionType#DOCUMENT}): the type of the collection to create. + * @return options + */ + public CollectionCreateOptions type(final CollectionType type) { + this.type = type; + return this; + } + + public String getDistributeShardsLike() { + return distributeShardsLike; + } + + /** + * @param distributeShardsLike (The default is ""): in an enterprise cluster, this attribute binds the specifics + * of sharding for the + * newly created collection to follow that of a specified existing collection. Note: + * Using this parameter + * has consequences for the prototype collection. It can no longer be dropped, before + * sharding imitating + * collections are dropped. Equally, backups and restores of imitating collections + * alone will generate + * warnings, which can be overridden, about missing sharding prototype. + * @return options + */ + public CollectionCreateOptions distributeShardsLike(final String distributeShardsLike) { + this.distributeShardsLike = distributeShardsLike; + return this; + } + + public CollectionSchema getSchema() { + return schema; + } + + /** + * @param schema object that specifies the collection level schema for documents + * @return options + * @since ArangoDB 3.7 + */ + public CollectionCreateOptions schema(final CollectionSchema schema) { + this.schema = schema; + return this; + } + + /** + * @param computedValues An optional list of computed values. + * @return options + * @since ArangoDB 3.10 + */ + public CollectionCreateOptions computedValues(final ComputedValue... computedValues) { + Collections.addAll(this.computedValues, computedValues); + return this; + } + + public List getComputedValues() { + return computedValues; + } +} diff --git a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java b/core/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java similarity index 60% rename from src/main/java/com/arangodb/model/CollectionPropertiesOptions.java rename to core/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java index e7c62f71f..a3144b9f4 100644 --- a/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java +++ b/core/src/main/java/com/arangodb/model/CollectionPropertiesOptions.java @@ -1,90 +1,87 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public class CollectionPropertiesOptions { - - private Boolean waitForSync; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Long journalSize; - private CollectionSchema schema; - - public CollectionPropertiesOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync If true then creating or changing a document will wait until the data has been synchronized to disk. - * @return options - */ - public CollectionPropertiesOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public Long getJournalSize() { - return journalSize; - } - - /** - * @param journalSize The maximal size of a journal or datafile in bytes. The value must be at least 1048576 (1 MB). Note - * that when changing the journalSize value, it will only have an effect for additional journals or - * datafiles that are created. Already existing journals or datafiles will not be affected. - * @return options - * @deprecated MMFiles only - */ - @Deprecated - public CollectionPropertiesOptions journalSize(final Long journalSize) { - this.journalSize = journalSize; - return this; - } - - public CollectionSchema getSchema() { - return schema; - } - - /** - * @param schema object that specifies the collection level schema for documents - * @since ArangoDB 3.7 - * @return options - */ - public CollectionPropertiesOptions schema(final CollectionSchema schema) { - this.schema = schema; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author Mark Vollmary + * @see + * API + * Documentation + */ +public final class CollectionPropertiesOptions { + + private Boolean waitForSync; + private CollectionSchema schema; + private List computedValues; + + public CollectionPropertiesOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync If true then creating or changing a document will wait until the data has been synchronized + * to disk. + * @return options + */ + public CollectionPropertiesOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public CollectionSchema getSchema() { + return schema; + } + + /** + * @param schema object that specifies the collection level schema for documents + * @return options + * @since ArangoDB 3.7 + */ + public CollectionPropertiesOptions schema(final CollectionSchema schema) { + this.schema = schema; + return this; + } + + /** + * @param computedValues An optional list of computed values. + * @return options + * @since ArangoDB 3.10 + */ + public CollectionPropertiesOptions computedValues(final ComputedValue... computedValues) { + if(this.computedValues == null) { + this.computedValues = new ArrayList<>(); + } + Collections.addAll(this.computedValues, computedValues); + return this; + } + + public List getComputedValues() { + return computedValues; + } +} diff --git a/src/main/java/com/arangodb/model/CollectionRenameOptions.java b/core/src/main/java/com/arangodb/model/CollectionRenameOptions.java similarity index 87% rename from src/main/java/com/arangodb/model/CollectionRenameOptions.java rename to core/src/main/java/com/arangodb/model/CollectionRenameOptions.java index 1c7896c79..6748f811f 100644 --- a/src/main/java/com/arangodb/model/CollectionRenameOptions.java +++ b/core/src/main/java/com/arangodb/model/CollectionRenameOptions.java @@ -1,47 +1,47 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - */ -public class CollectionRenameOptions { - - private String name; - - public CollectionRenameOptions() { - super(); - } - - public String getName() { - return name; - } - - /** - * @param name The new name - * @return options - */ - protected CollectionRenameOptions name(final String name) { - this.name = name; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + */ +public final class CollectionRenameOptions { + + private String name; + + public CollectionRenameOptions() { + super(); + } + + public String getName() { + return name; + } + + /** + * @param name The new name + * @return options + */ + CollectionRenameOptions name(final String name) { + this.name = name; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/CollectionSchema.java b/core/src/main/java/com/arangodb/model/CollectionSchema.java similarity index 78% rename from src/main/java/com/arangodb/model/CollectionSchema.java rename to core/src/main/java/com/arangodb/model/CollectionSchema.java index 49b6fea85..60d7cbf0d 100644 --- a/src/main/java/com/arangodb/model/CollectionSchema.java +++ b/core/src/main/java/com/arangodb/model/CollectionSchema.java @@ -22,20 +22,19 @@ package com.arangodb.model; +import com.arangodb.internal.serde.InternalDeserializers; +import com.arangodb.internal.serde.InternalSerializers; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + /** * @author Michele Rastelli - * @see API Documentation + * @see + * API Documentation * @since ArangoDB 3.7 */ -public class CollectionSchema { - - /** - * Value to unset the collection schema on properties update {@link com.arangodb.ArangoCollection#changeProperties(CollectionPropertiesOptions)}. - */ - public static final CollectionSchema NULL_SCHEMA = new CollectionSchema() - .setLevel(null) - .setMessage(null) - .setRule(null); +public final class CollectionSchema { private String rule; private Level level; @@ -44,10 +43,12 @@ public class CollectionSchema { /** * @return JSON Schema description */ + @JsonSerialize(using = InternalSerializers.CollectionSchemaRuleSerializer.class) public String getRule() { return rule; } + @JsonDeserialize(using = InternalDeserializers.CollectionSchemaRuleDeserializer.class) public CollectionSchema setRule(String rule) { this.rule = rule; return this; @@ -82,11 +83,13 @@ public enum Level { /** * The rule is inactive and validation thus turned off. */ + @JsonProperty("none") NONE("none"), /** * Only newly inserted documents are validated. */ + @JsonProperty("new") NEW("new"), /** @@ -95,15 +98,21 @@ public enum Level { * but you want to stop the insertion of more invalid documents and prohibit that valid documents are changed to * invalid documents. */ + @JsonProperty("moderate") MODERATE("moderate"), /** * All new and modified document must strictly pass validation. No exceptions are made (default). */ + @JsonProperty("strict") STRICT("strict"); private final String value; + Level(String value) { + this.value = value; + } + public static Level of(String label) { for (Level e : values()) { if (e.value.equals(label)) { @@ -113,10 +122,6 @@ public static Level of(String label) { return null; } - Level(String value) { - this.value = value; - } - public String getValue() { return value; } diff --git a/src/main/java/com/arangodb/model/CollectionTruncateOptions.java b/core/src/main/java/com/arangodb/model/CollectionTruncateOptions.java similarity index 96% rename from src/main/java/com/arangodb/model/CollectionTruncateOptions.java rename to core/src/main/java/com/arangodb/model/CollectionTruncateOptions.java index dff681273..1b089533e 100644 --- a/src/main/java/com/arangodb/model/CollectionTruncateOptions.java +++ b/core/src/main/java/com/arangodb/model/CollectionTruncateOptions.java @@ -23,7 +23,7 @@ /** * @author Michele Rastelli */ -public class CollectionTruncateOptions { +public final class CollectionTruncateOptions { private String streamTransactionId; diff --git a/src/main/java/com/arangodb/model/CollectionsReadOptions.java b/core/src/main/java/com/arangodb/model/CollectionsReadOptions.java similarity index 93% rename from src/main/java/com/arangodb/model/CollectionsReadOptions.java rename to core/src/main/java/com/arangodb/model/CollectionsReadOptions.java index cea7750d0..11e563fad 100644 --- a/src/main/java/com/arangodb/model/CollectionsReadOptions.java +++ b/core/src/main/java/com/arangodb/model/CollectionsReadOptions.java @@ -1,49 +1,49 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public class CollectionsReadOptions { - - private Boolean excludeSystem; - - public CollectionsReadOptions() { - super(); - } - - public Boolean getExcludeSystem() { - return excludeSystem; - } - - /** - * @param excludeSystem Whether or not system collections should be excluded from the result. - * @return options - */ - public CollectionsReadOptions excludeSystem(final Boolean excludeSystem) { - this.excludeSystem = excludeSystem; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class CollectionsReadOptions { + + private Boolean excludeSystem; + + public CollectionsReadOptions() { + super(); + } + + public Boolean getExcludeSystem() { + return excludeSystem; + } + + /** + * @param excludeSystem Whether or not system collections should be excluded from the result. + * @return options + */ + public CollectionsReadOptions excludeSystem(final Boolean excludeSystem) { + this.excludeSystem = excludeSystem; + return this; + } + +} diff --git a/core/src/main/java/com/arangodb/model/ComputedValue.java b/core/src/main/java/com/arangodb/model/ComputedValue.java new file mode 100644 index 000000000..54d6a2b9f --- /dev/null +++ b/core/src/main/java/com/arangodb/model/ComputedValue.java @@ -0,0 +1,128 @@ +package com.arangodb.model; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +/** + * @since ArangoDB 3.10 + */ +public final class ComputedValue { + private String name; + private String expression; + private Boolean overwrite; + private Set computeOn; + private Boolean keepNull; + private Boolean failOnWarning; + + public enum ComputeOn { + insert, update, replace + } + + public ComputedValue() { + super(); + } + + /** + * @param name (required) The name of the target attribute. Can only be a top-level attribute, but you may return + * a nested object. Cannot be _key, _id, _rev, _from, _to, or a shard key attribute. + * @return this + */ + public ComputedValue name(final String name) { + this.name = name; + return this; + } + + /** + * @param expression (required) An AQL RETURN operation with an expression that computes the desired value. See + * Computed Value Expressions + * for details. + * @return this + */ + public ComputedValue expression(final String expression) { + this.expression = expression; + return this; + } + + /** + * @param overwrite (required) Whether the computed value shall take precedence over a user-provided or existing + * attribute. + * @return this + */ + public ComputedValue overwrite(final Boolean overwrite) { + this.overwrite = overwrite; + return this; + } + + /** + * @param computeOn (optional) An array of operations to define on which write operations the value shall be + * computed. The default is ["insert", "update", "replace"]. + * @return this + */ + public ComputedValue computeOn(final ComputeOn... computeOn) { + if (this.computeOn == null) { + this.computeOn = new HashSet<>(); + } + Collections.addAll(this.computeOn, computeOn); + return this; + } + + /** + * @param keepNull (optional) Whether the target attribute shall be set if the expression evaluates to null. You + * can set the option to false to not set (or unset) the target attribute if the expression + * returns null. The default is true. + * @return this + */ + public ComputedValue keepNull(final Boolean keepNull) { + this.keepNull = keepNull; + return this; + } + + /** + * @param failOnWarning (optional) Whether to let the write operation fail if the expression produces a warning. + * The default is false. + * @return this + */ + public ComputedValue failOnWarning(final Boolean failOnWarning) { + this.failOnWarning = failOnWarning; + return this; + } + + public String getName() { + return name; + } + + public String getExpression() { + return expression; + } + + public Boolean getOverwrite() { + return overwrite; + } + + public Set getComputeOn() { + return computeOn; + } + + public Boolean getKeepNull() { + return keepNull; + } + + public Boolean getFailOnWarning() { + return failOnWarning; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ComputedValue that = (ComputedValue) o; + return Objects.equals(name, that.name) && Objects.equals(expression, that.expression) && Objects.equals(overwrite, that.overwrite) && Objects.equals(computeOn, that.computeOn) && Objects.equals(keepNull, that.keepNull) && Objects.equals(failOnWarning, that.failOnWarning); + } + + @Override + public int hashCode() { + return Objects.hash(name, expression, overwrite, computeOn, keepNull, failOnWarning); + } +} diff --git a/src/main/java/com/arangodb/model/DBCreateOptions.java b/core/src/main/java/com/arangodb/model/DBCreateOptions.java similarity index 84% rename from src/main/java/com/arangodb/model/DBCreateOptions.java rename to core/src/main/java/com/arangodb/model/DBCreateOptions.java index 23708bb18..16b82beb6 100644 --- a/src/main/java/com/arangodb/model/DBCreateOptions.java +++ b/core/src/main/java/com/arangodb/model/DBCreateOptions.java @@ -1,89 +1,79 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.DbName; - -import java.util.Collection; - -/** - * @author Mark Vollmary - */ -public class DBCreateOptions { - - private Collection users; - private String name; - private DatabaseOptions options; - - public DBCreateOptions() { - super(); - } - - public Collection getUsers() { - return users; - } - - /** - * @param users array of user objects to initially create for the new database. - * User information will not be changed for users that already exist. - * If users is not specified or does not contain any users, a default user - * root will be created with an empty string password. This ensures that the - * new database will be accessible after it is created. - * @return options - */ - public DBCreateOptions users(final Collection users) { - this.users = users; - return this; - } - - public String getName() { - return name; - } - - /** - * @param name Has to contain a valid database name - * @return options - * @deprecated Use {@link #name(DbName)} instead. - */ - @Deprecated - public DBCreateOptions name(final String name) { - return name(DbName.of(name)); - } - - /** - * @param dbName database name - * @return options - */ - public DBCreateOptions name(final DbName dbName) { - name = dbName.get(); - return this; - } - - public DatabaseOptions getOptions() { - return options; - } - - public DBCreateOptions options(DatabaseOptions options) { - this.options = options; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.DbName; + +import java.util.Collection; + +/** + * @author Mark Vollmary + */ +public final class DBCreateOptions { + + private Collection users; + private String name; + private DatabaseOptions options; + + public DBCreateOptions() { + super(); + } + + public Collection getUsers() { + return users; + } + + /** + * @param users array of user objects to initially create for the new database. + * User information will not be changed for users that already exist. + * If users is not specified or does not contain any users, a default user + * root will be created with an empty string password. This ensures that the + * new database will be accessible after it is created. + * @return options + */ + public DBCreateOptions users(final Collection users) { + this.users = users; + return this; + } + + public String getName() { + return name; + } + + /** + * @param dbName database name + * @return options + */ + public DBCreateOptions name(final DbName dbName) { + name = dbName.get(); + return this; + } + + public DatabaseOptions getOptions() { + return options; + } + + public DBCreateOptions options(DatabaseOptions options) { + this.options = options; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/DatabaseOptions.java b/core/src/main/java/com/arangodb/model/DatabaseOptions.java similarity index 73% rename from src/main/java/com/arangodb/model/DatabaseOptions.java rename to core/src/main/java/com/arangodb/model/DatabaseOptions.java index 81052c6c5..62bbaa7cd 100644 --- a/src/main/java/com/arangodb/model/DatabaseOptions.java +++ b/core/src/main/java/com/arangodb/model/DatabaseOptions.java @@ -26,29 +26,24 @@ * @author Michele Rastelli * @since ArangoDB 3.6.0 */ -public class DatabaseOptions { +public final class DatabaseOptions { - private final ReplicationFactor replicationFactor; + private ReplicationFactor replicationFactor; private Integer writeConcern; private String sharding; public DatabaseOptions() { super(); - replicationFactor = new ReplicationFactor(); } - public Integer getReplicationFactor() { - return replicationFactor.getReplicationFactor(); + public ReplicationFactor getReplicationFactor() { + return replicationFactor; } public Integer getWriteConcern() { return writeConcern; } - public Boolean getSatellite() { - return this.replicationFactor.getSatellite(); - } - public String getSharding() { return sharding; } @@ -58,8 +53,13 @@ public String getSharding() { * @return options * @since ArangoDB 3.6.0 */ - public DatabaseOptions replicationFactor(final Integer replicationFactor) { - this.replicationFactor.setReplicationFactor(replicationFactor); + public DatabaseOptions replicationFactor(final ReplicationFactor replicationFactor) { + this.replicationFactor = replicationFactor; + return this; + } + + public DatabaseOptions replicationFactor(int replicationFactor) { + this.replicationFactor = ReplicationFactor.of(replicationFactor); return this; } @@ -77,17 +77,6 @@ public DatabaseOptions writeConcern(final Integer writeConcern) { return this; } - /** - * @param satellite whether the collection is a satellite collection. Only in an enterprise cluster setup (else - * returning null). - * @return options - * @since ArangoDB 3.6.0 - */ - public DatabaseOptions satellite(final Boolean satellite) { - this.replicationFactor.setSatellite(satellite); - return this; - } - /** * @param sharding The sharding method to use for new collections in this database. * Valid values are: “”, “flexible”, or “single”. The first two are equivalent. diff --git a/src/main/java/com/arangodb/model/DatabaseUsersOptions.java b/core/src/main/java/com/arangodb/model/DatabaseUsersOptions.java similarity index 98% rename from src/main/java/com/arangodb/model/DatabaseUsersOptions.java rename to core/src/main/java/com/arangodb/model/DatabaseUsersOptions.java index edc9175da..63d11e6c8 100644 --- a/src/main/java/com/arangodb/model/DatabaseUsersOptions.java +++ b/core/src/main/java/com/arangodb/model/DatabaseUsersOptions.java @@ -25,7 +25,7 @@ /** * @author Michele Rastelli */ -public class DatabaseUsersOptions { +public final class DatabaseUsersOptions { private String username; private Map extra; diff --git a/src/main/java/com/arangodb/model/DocumentCreateOptions.java b/core/src/main/java/com/arangodb/model/DocumentCreateOptions.java similarity index 77% rename from src/main/java/com/arangodb/model/DocumentCreateOptions.java rename to core/src/main/java/com/arangodb/model/DocumentCreateOptions.java index 3c8a52337..f90845950 100644 --- a/src/main/java/com/arangodb/model/DocumentCreateOptions.java +++ b/core/src/main/java/com/arangodb/model/DocumentCreateOptions.java @@ -26,17 +26,16 @@ * @see API * Documentation */ -public class DocumentCreateOptions { +public final class DocumentCreateOptions { private Boolean waitForSync; private Boolean returnNew; private Boolean returnOld; - private Boolean overwrite; private OverwriteMode overwriteMode; private Boolean silent; private String streamTransactionId; private Boolean mergeObjects; - + private Boolean keepNull; public DocumentCreateOptions() { super(); @@ -73,8 +72,7 @@ public Boolean getReturnOld() { } /** - * @param returnOld Additionally return the complete old document under the attribute old in the result. Only - * available if the {@code overwrite} option is used. + * @param returnOld Additionally return the complete old document under the attribute old in the result. * @return options * @since ArangoDB 3.4 */ @@ -83,34 +81,11 @@ public DocumentCreateOptions returnOld(final Boolean returnOld) { return this; } - public Boolean getOverwrite() { - return overwrite; - } - - /** - * @param overwrite If set to true, the insert becomes a replace-insert. If a document with the same {@code _key} - * already exists the new document is not rejected with unique constraint violated but will replace - * the old document. - * @return options - * @since ArangoDB 3.4 - * @deprecated use {@link #overwriteMode(OverwriteMode)} instead - */ - @Deprecated - public DocumentCreateOptions overwrite(final Boolean overwrite) { - this.overwrite = overwrite; - return this; - } - public OverwriteMode getOverwriteMode() { return overwriteMode; } /** - * Limitations: - * - {@code keepNull} parameter is not supported - * - the fields having {@code null} value are always removed during serialization - * Therefore in case of {@link OverwriteMode#update}, existing attributes cannot be removed. - * * @param overwriteMode This parameter can be set to replace or update. If given it sets implicitly the overwrite * flag. In case it is set to update, the replace-insert becomes an update-insert. Otherwise * this option follows the rules of the overwrite parameter. @@ -155,10 +130,12 @@ public Boolean getMergeObjects() { } /** - * Only considered if {@link this#overwriteMode} is set to {@link OverwriteMode#update} + * Only considered if {@link DocumentCreateOptions#overwriteMode(OverwriteMode)} is set to {@link OverwriteMode#update} * - * @param mergeObjects Controls whether objects (not arrays) will be merged if present in both the existing and the patch - * document. If set to false, the value in the patch document will overwrite the existing document's + * @param mergeObjects Controls whether objects (not arrays) will be merged if present in both the existing and + * the patch + * document. If set to false, the value in the patch document will overwrite the existing + * document's * value. If set to true, objects will be merged. The default is true. * @return options * @since ArangoDB 3.7 @@ -168,4 +145,22 @@ public DocumentCreateOptions mergeObjects(Boolean mergeObjects) { return this; } + public Boolean getKeepNull() { + return keepNull; + } + + /** + * @param keepNull If the intention is to delete existing attributes with the update-insert command, the URL + * query parameter keepNull can be used with a value of false. This will modify the behavior of + * the patch command to remove any attributes from the existing document that are contained in + * the patch document with an attribute value of null. This option controls the update-insert + * behavior only. + * @return options + * @since ArangoDB 3.7 + */ + public DocumentCreateOptions keepNull(Boolean keepNull) { + this.keepNull = keepNull; + return this; + } + } diff --git a/src/main/java/com/arangodb/model/DocumentDeleteOptions.java b/core/src/main/java/com/arangodb/model/DocumentDeleteOptions.java similarity index 95% rename from src/main/java/com/arangodb/model/DocumentDeleteOptions.java rename to core/src/main/java/com/arangodb/model/DocumentDeleteOptions.java index e0e566952..d2de3aa43 100644 --- a/src/main/java/com/arangodb/model/DocumentDeleteOptions.java +++ b/core/src/main/java/com/arangodb/model/DocumentDeleteOptions.java @@ -26,7 +26,7 @@ * @see API * Documentation */ -public class DocumentDeleteOptions { +public final class DocumentDeleteOptions { private Boolean waitForSync; private String ifMatch; @@ -69,7 +69,8 @@ public Boolean getReturnOld() { } /** - * @param returnOld Return additionally the complete previous revision of the changed document under the attribute old in + * @param returnOld Return additionally the complete previous revision of the changed document under the + * attribute old in * the result. * @return options */ diff --git a/src/main/java/com/arangodb/model/DocumentExistsOptions.java b/core/src/main/java/com/arangodb/model/DocumentExistsOptions.java similarity index 75% rename from src/main/java/com/arangodb/model/DocumentExistsOptions.java rename to core/src/main/java/com/arangodb/model/DocumentExistsOptions.java index a790bf201..3af420a78 100644 --- a/src/main/java/com/arangodb/model/DocumentExistsOptions.java +++ b/core/src/main/java/com/arangodb/model/DocumentExistsOptions.java @@ -1,94 +1,80 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - * @see API - * Documentation - */ -public class DocumentExistsOptions { - - private String ifNoneMatch; - private String ifMatch; - private boolean catchException; - private String streamTransactionId; - - public DocumentExistsOptions() { - super(); - catchException = true; - } - - public String getIfNoneMatch() { - return ifNoneMatch; - } - - /** - * @param ifNoneMatch document revision must not contain If-None-Match - * @return options - */ - public DocumentExistsOptions ifNoneMatch(final String ifNoneMatch) { - this.ifNoneMatch = ifNoneMatch; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch document revision must contain If-Match - * @return options - */ - public DocumentExistsOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public boolean isCatchException() { - return catchException; - } - - /** - * @param catchException whether or not catch possible thrown exceptions - * @return options - */ - public DocumentExistsOptions catchException(final boolean catchException) { - this.catchException = catchException; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.0 - */ - public DocumentExistsOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + * @see + * API + * Documentation + */ +public final class DocumentExistsOptions { + + private String ifNoneMatch; + private String ifMatch; + private String streamTransactionId; + + public DocumentExistsOptions() { + super(); + } + + public String getIfNoneMatch() { + return ifNoneMatch; + } + + /** + * @param ifNoneMatch document revision must not contain If-None-Match + * @return options + */ + public DocumentExistsOptions ifNoneMatch(final String ifNoneMatch) { + this.ifNoneMatch = ifNoneMatch; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch document revision must contain If-Match + * @return options + */ + public DocumentExistsOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.0 + */ + public DocumentExistsOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/DocumentImportOptions.java b/core/src/main/java/com/arangodb/model/DocumentImportOptions.java similarity index 84% rename from src/main/java/com/arangodb/model/DocumentImportOptions.java rename to core/src/main/java/com/arangodb/model/DocumentImportOptions.java index b8a55e3ed..42612a8e8 100644 --- a/src/main/java/com/arangodb/model/DocumentImportOptions.java +++ b/core/src/main/java/com/arangodb/model/DocumentImportOptions.java @@ -1,153 +1,162 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - */ -public class DocumentImportOptions { - - public enum OnDuplicate { - error, update, replace, ignore - } - - private String fromPrefix; - private String toPrefix; - private Boolean overwrite; - private Boolean waitForSync; - private OnDuplicate onDuplicate; - private Boolean complete; - private Boolean details; - - public DocumentImportOptions() { - super(); - } - - public String getFromPrefix() { - return fromPrefix; - } - - /** - * @param fromPrefix An optional prefix for the values in _from attributes. If specified, the value is automatically - * prepended to each _from input value. This allows specifying just the keys for _from. - * @return options - */ - public DocumentImportOptions fromPrefix(final String fromPrefix) { - this.fromPrefix = fromPrefix; - return this; - } - - public String getToPrefix() { - return toPrefix; - } - - /** - * @param toPrefix An optional prefix for the values in _to attributes. If specified, the value is automatically - * prepended to each _to input value. This allows specifying just the keys for _to. - * @return options - */ - public DocumentImportOptions toPrefix(final String toPrefix) { - this.toPrefix = toPrefix; - return this; - } - - public Boolean getOverwrite() { - return overwrite; - } - - /** - * @param overwrite If this parameter has a value of true, then all data in the collection will be removed prior to the - * import. Note that any existing index definitions will be preserved. - * @return options - */ - public DocumentImportOptions overwrite(final Boolean overwrite) { - this.overwrite = overwrite; - return this; - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until documents have been synced to disk before returning. - * @return options - */ - public DocumentImportOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public OnDuplicate getOnDuplicate() { - return onDuplicate; - } - - /** - * @param onDuplicate Controls what action is carried out in case of a unique key constraint violation. Possible values are: - *
      - *
    • error: this will not import the current document because of the unique key constraint violation. - * This is the default setting.
    • - *
    • update: this will update an existing document in the database with the data specified in the - * request. Attributes of the existing document that are not present in the request will be - * preserved.
    • - *
    • replace: this will replace an existing document in the database with the data specified in the - * request.
    • - *
    • ignore: this will not update an existing document and simply ignore the error caused by the unique - * key constraint violation. Note that update, replace and ignore will only work when the import document - * in the request contains the _key attribute. update and replace may also fail because of secondary - * unique key constraint violations.
    • - *
    - * @return options - */ - public DocumentImportOptions onDuplicate(final OnDuplicate onDuplicate) { - this.onDuplicate = onDuplicate; - return this; - } - - public Boolean getComplete() { - return complete; - } - - /** - * @param complete If set to true, it will make the whole import fail if any error occurs. Otherwise the import will - * continue even if some documents cannot be imported. - * @return options - */ - public DocumentImportOptions complete(final Boolean complete) { - this.complete = complete; - return this; - } - - public Boolean getDetails() { - return details; - } - - /** - * @param details If set to true, the result will include an attribute details with details about documents that could - * not be imported. - * @return options - */ - public DocumentImportOptions details(final Boolean details) { - this.details = details; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + */ +public final class DocumentImportOptions { + + private String fromPrefix; + private String toPrefix; + private Boolean overwrite; + private Boolean waitForSync; + private OnDuplicate onDuplicate; + private Boolean complete; + private Boolean details; + + public DocumentImportOptions() { + super(); + } + + public String getFromPrefix() { + return fromPrefix; + } + + /** + * @param fromPrefix An optional prefix for the values in _from attributes. If specified, the value is automatically + * prepended to each _from input value. This allows specifying just the keys for _from. + * @return options + */ + public DocumentImportOptions fromPrefix(final String fromPrefix) { + this.fromPrefix = fromPrefix; + return this; + } + + public String getToPrefix() { + return toPrefix; + } + + /** + * @param toPrefix An optional prefix for the values in _to attributes. If specified, the value is automatically + * prepended to each _to input value. This allows specifying just the keys for _to. + * @return options + */ + public DocumentImportOptions toPrefix(final String toPrefix) { + this.toPrefix = toPrefix; + return this; + } + + public Boolean getOverwrite() { + return overwrite; + } + + /** + * @param overwrite If this parameter has a value of true, then all data in the collection will be removed prior + * to the + * import. Note that any existing index definitions will be preserved. + * @return options + */ + public DocumentImportOptions overwrite(final Boolean overwrite) { + this.overwrite = overwrite; + return this; + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until documents have been synced to disk before returning. + * @return options + */ + public DocumentImportOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public OnDuplicate getOnDuplicate() { + return onDuplicate; + } + + /** + * @param onDuplicate Controls what action is carried out in case of a unique key constraint violation. Possible + * values are: + *
      + *
    • error: this will not import the current document because of the unique key constraint + * violation. + * This is the default setting.
    • + *
    • update: this will update an existing document in the database with the data specified + * in the + * request. Attributes of the existing document that are not present in the request will be + * preserved.
    • + *
    • replace: this will replace an existing document in the database with the data specified + * in the + * request.
    • + *
    • ignore: this will not update an existing document and simply ignore the error caused by + * the unique + * key constraint violation. Note that update, replace and ignore will only work when the + * import document + * in the request contains the _key attribute. update and replace may also fail because of + * secondary + * unique key constraint violations.
    • + *
    + * @return options + */ + public DocumentImportOptions onDuplicate(final OnDuplicate onDuplicate) { + this.onDuplicate = onDuplicate; + return this; + } + + public Boolean getComplete() { + return complete; + } + + /** + * @param complete If set to true, it will make the whole import fail if any error occurs. Otherwise the import will + * continue even if some documents cannot be imported. + * @return options + */ + public DocumentImportOptions complete(final Boolean complete) { + this.complete = complete; + return this; + } + + public Boolean getDetails() { + return details; + } + + /** + * @param details If set to true, the result will include an attribute details with details about documents that + * could + * not be imported. + * @return options + */ + public DocumentImportOptions details(final Boolean details) { + this.details = details; + return this; + } + + public enum OnDuplicate { + error, update, replace, ignore + } + +} diff --git a/src/main/java/com/arangodb/model/DocumentReadOptions.java b/core/src/main/java/com/arangodb/model/DocumentReadOptions.java similarity index 80% rename from src/main/java/com/arangodb/model/DocumentReadOptions.java rename to core/src/main/java/com/arangodb/model/DocumentReadOptions.java index b808f6ed4..f19aa3e43 100644 --- a/src/main/java/com/arangodb/model/DocumentReadOptions.java +++ b/core/src/main/java/com/arangodb/model/DocumentReadOptions.java @@ -1,114 +1,96 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.velocypack.annotations.Expose; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - * @see API - * Documentation - */ -public class DocumentReadOptions { - - private String ifNoneMatch; - private String ifMatch; - private boolean catchException; - @Expose(serialize = false) - private Boolean allowDirtyRead; - private String streamTransactionId; - - public DocumentReadOptions() { - super(); - catchException = true; - } - - public String getIfNoneMatch() { - return ifNoneMatch; - } - - /** - * @param ifNoneMatch document revision must not contain If-None-Match - * @return options - */ - public DocumentReadOptions ifNoneMatch(final String ifNoneMatch) { - this.ifNoneMatch = ifNoneMatch; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch document revision must contain If-Match - * @return options - */ - public DocumentReadOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public boolean isCatchException() { - return catchException; - } - - /** - * @param catchException whether or not catch possible thrown exceptions - * @return options - */ - public DocumentReadOptions catchException(final boolean catchException) { - this.catchException = catchException; - return this; - } - - /** - * @param allowDirtyRead Set to {@code true} allows reading from followers in an active-failover setup. - * @return options - * @see API - * Documentation - * @since ArangoDB 3.4.0 - */ - public DocumentReadOptions allowDirtyRead(final Boolean allowDirtyRead) { - this.allowDirtyRead = allowDirtyRead; - return this; - } - - public Boolean getAllowDirtyRead() { - return allowDirtyRead; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.0 - */ - public DocumentReadOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + * @see API + * Documentation + */ +public final class DocumentReadOptions { + + private String ifNoneMatch; + private String ifMatch; + private Boolean allowDirtyRead; + private String streamTransactionId; + + public DocumentReadOptions() { + super(); + } + + public String getIfNoneMatch() { + return ifNoneMatch; + } + + /** + * @param ifNoneMatch document revision must not contain If-None-Match + * @return options + */ + public DocumentReadOptions ifNoneMatch(final String ifNoneMatch) { + this.ifNoneMatch = ifNoneMatch; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch document revision must contain If-Match + * @return options + */ + public DocumentReadOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + /** + * @param allowDirtyRead Set to {@code true} allows reading from followers in an active-failover setup. + * @return options + * @see API + * Documentation + * @since ArangoDB 3.4.0 + */ + public DocumentReadOptions allowDirtyRead(final Boolean allowDirtyRead) { + this.allowDirtyRead = allowDirtyRead; + return this; + } + + public Boolean getAllowDirtyRead() { + return allowDirtyRead; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.0 + */ + public DocumentReadOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/DocumentReplaceOptions.java b/core/src/main/java/com/arangodb/model/DocumentReplaceOptions.java similarity index 92% rename from src/main/java/com/arangodb/model/DocumentReplaceOptions.java rename to core/src/main/java/com/arangodb/model/DocumentReplaceOptions.java index 2646f847d..8dae60508 100644 --- a/src/main/java/com/arangodb/model/DocumentReplaceOptions.java +++ b/core/src/main/java/com/arangodb/model/DocumentReplaceOptions.java @@ -26,7 +26,7 @@ * @see API * Documentation */ -public class DocumentReplaceOptions { +public final class DocumentReplaceOptions { private Boolean waitForSync; private Boolean ignoreRevs; @@ -58,8 +58,10 @@ public Boolean getIgnoreRevs() { } /** - * @param ignoreRevs By default, or if this is set to true, the _rev attributes in the given document is ignored. If this - * is set to false, then the _rev attribute given in the body document is taken as a precondition. The + * @param ignoreRevs By default, or if this is set to true, the _rev attributes in the given document is ignored. + * If this + * is set to false, then the _rev attribute given in the body document is taken as a + * precondition. The * document is only replaced if the current revision is the one specified. * @return options */ @@ -99,7 +101,8 @@ public Boolean getReturnOld() { } /** - * @param returnOld Return additionally the complete previous revision of the changed document under the attribute old in + * @param returnOld Return additionally the complete previous revision of the changed document under the + * attribute old in * the result. * @return options */ diff --git a/src/main/java/com/arangodb/model/DocumentUpdateOptions.java b/core/src/main/java/com/arangodb/model/DocumentUpdateOptions.java similarity index 84% rename from src/main/java/com/arangodb/model/DocumentUpdateOptions.java rename to core/src/main/java/com/arangodb/model/DocumentUpdateOptions.java index 20d7b8cca..e405582c1 100644 --- a/src/main/java/com/arangodb/model/DocumentUpdateOptions.java +++ b/core/src/main/java/com/arangodb/model/DocumentUpdateOptions.java @@ -26,7 +26,7 @@ * @see API * Documentation */ -public class DocumentUpdateOptions { +public final class DocumentUpdateOptions { private Boolean keepNull; private Boolean mergeObjects; @@ -35,7 +35,6 @@ public class DocumentUpdateOptions { private String ifMatch; private Boolean returnNew; private Boolean returnOld; - private Boolean serializeNull; private Boolean silent; private String streamTransactionId; @@ -64,8 +63,10 @@ public Boolean getMergeObjects() { } /** - * @param mergeObjects Controls whether objects (not arrays) will be merged if present in both the existing and the patch - * document. If set to false, the value in the patch document will overwrite the existing document's + * @param mergeObjects Controls whether objects (not arrays) will be merged if present in both the existing and + * the patch + * document. If set to false, the value in the patch document will overwrite the existing + * document's * value. If set to true, objects will be merged. The default is true. * @return options */ @@ -92,8 +93,10 @@ public Boolean getIgnoreRevs() { } /** - * @param ignoreRevs By default, or if this is set to true, the _rev attributes in the given document is ignored. If this - * is set to false, then the _rev attribute given in the body document is taken as a precondition. The + * @param ignoreRevs By default, or if this is set to true, the _rev attributes in the given document is ignored. + * If this + * is set to false, then the _rev attribute given in the body document is taken as a + * precondition. The * document is only updated if the current revision is the one specified. * @return options */ @@ -133,7 +136,8 @@ public Boolean getReturnOld() { } /** - * @param returnOld Return additionally the complete previous revision of the changed document under the attribute old in + * @param returnOld Return additionally the complete previous revision of the changed document under the + * attribute old in * the result. * @return options */ @@ -142,21 +146,6 @@ public DocumentUpdateOptions returnOld(final Boolean returnOld) { return this; } - public Boolean getSerializeNull() { - return serializeNull; - } - - /** - * @param serializeNull By default, or if this is set to true, all fields of the document which have null values are - * serialized to VelocyPack otherwise they are excluded from serialization. Use this to update single - * fields from a stored document. - * @return options - */ - public DocumentUpdateOptions serializeNull(final Boolean serializeNull) { - this.serializeNull = serializeNull; - return this; - } - public Boolean getSilent() { return silent; } diff --git a/src/main/java/com/arangodb/model/EdgeCreateOptions.java b/core/src/main/java/com/arangodb/model/EdgeCreateOptions.java similarity index 94% rename from src/main/java/com/arangodb/model/EdgeCreateOptions.java rename to core/src/main/java/com/arangodb/model/EdgeCreateOptions.java index 3f335cfb1..2429d9405 100644 --- a/src/main/java/com/arangodb/model/EdgeCreateOptions.java +++ b/core/src/main/java/com/arangodb/model/EdgeCreateOptions.java @@ -1,63 +1,63 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class EdgeCreateOptions { - - private Boolean waitForSync; - private String streamTransactionId; - - public EdgeCreateOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until document has been synced to disk. - * @return options - */ - public EdgeCreateOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public EdgeCreateOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class EdgeCreateOptions { + + private Boolean waitForSync; + private String streamTransactionId; + + public EdgeCreateOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until document has been synced to disk. + * @return options + */ + public EdgeCreateOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public EdgeCreateOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/EdgeDeleteOptions.java b/core/src/main/java/com/arangodb/model/EdgeDeleteOptions.java similarity index 94% rename from src/main/java/com/arangodb/model/EdgeDeleteOptions.java rename to core/src/main/java/com/arangodb/model/EdgeDeleteOptions.java index 30d13c117..6d14fbcf7 100644 --- a/src/main/java/com/arangodb/model/EdgeDeleteOptions.java +++ b/core/src/main/java/com/arangodb/model/EdgeDeleteOptions.java @@ -1,77 +1,77 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class EdgeDeleteOptions { - - private Boolean waitForSync; - private String ifMatch; - private String streamTransactionId; - - public EdgeDeleteOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until deletion operation has been synced to disk. - * @return options - */ - public EdgeDeleteOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch remove a document based on a target revision - * @return options - */ - public EdgeDeleteOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public EdgeDeleteOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class EdgeDeleteOptions { + + private Boolean waitForSync; + private String ifMatch; + private String streamTransactionId; + + public EdgeDeleteOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until deletion operation has been synced to disk. + * @return options + */ + public EdgeDeleteOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch remove a document based on a target revision + * @return options + */ + public EdgeDeleteOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public EdgeDeleteOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/EdgeReplaceOptions.java b/core/src/main/java/com/arangodb/model/EdgeReplaceOptions.java similarity index 94% rename from src/main/java/com/arangodb/model/EdgeReplaceOptions.java rename to core/src/main/java/com/arangodb/model/EdgeReplaceOptions.java index 81f021ea0..ebf54eafd 100644 --- a/src/main/java/com/arangodb/model/EdgeReplaceOptions.java +++ b/core/src/main/java/com/arangodb/model/EdgeReplaceOptions.java @@ -1,77 +1,77 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class EdgeReplaceOptions { - - private Boolean waitForSync; - private String ifMatch; - private String streamTransactionId; - - public EdgeReplaceOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until document has been synced to disk. - * @return options - */ - public EdgeReplaceOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch replace a document based on target revision - * @return options - */ - public EdgeReplaceOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public EdgeReplaceOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class EdgeReplaceOptions { + + private Boolean waitForSync; + private String ifMatch; + private String streamTransactionId; + + public EdgeReplaceOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until document has been synced to disk. + * @return options + */ + public EdgeReplaceOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch replace a document based on target revision + * @return options + */ + public EdgeReplaceOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public EdgeReplaceOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/EdgeUpdateOptions.java b/core/src/main/java/com/arangodb/model/EdgeUpdateOptions.java similarity index 95% rename from src/main/java/com/arangodb/model/EdgeUpdateOptions.java rename to core/src/main/java/com/arangodb/model/EdgeUpdateOptions.java index cb95ddd85..356f6609b 100644 --- a/src/main/java/com/arangodb/model/EdgeUpdateOptions.java +++ b/core/src/main/java/com/arangodb/model/EdgeUpdateOptions.java @@ -1,94 +1,94 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class EdgeUpdateOptions { - - private Boolean keepNull; - private Boolean waitForSync; - private String ifMatch; - private String streamTransactionId; - - public EdgeUpdateOptions() { - super(); - } - - public Boolean getKeepNull() { - return keepNull; - } - - /** - * @param keepNull If the intention is to delete existing attributes with the patch command, the URL query parameter - * keepNull can be used with a value of false. This will modify the behavior of the patch command to - * remove any attributes from the existing document that are contained in the patch document with an - * attribute value of null. - * @return options - */ - public EdgeUpdateOptions keepNull(final Boolean keepNull) { - this.keepNull = keepNull; - return this; - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until document has been synced to disk. - * @return options - */ - public EdgeUpdateOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch replace a document based on target revision - * @return options - */ - public EdgeUpdateOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public EdgeUpdateOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class EdgeUpdateOptions { + + private Boolean keepNull; + private Boolean waitForSync; + private String ifMatch; + private String streamTransactionId; + + public EdgeUpdateOptions() { + super(); + } + + public Boolean getKeepNull() { + return keepNull; + } + + /** + * @param keepNull If the intention is to delete existing attributes with the patch command, the URL query parameter + * keepNull can be used with a value of false. This will modify the behavior of the patch command to + * remove any attributes from the existing document that are contained in the patch document with an + * attribute value of null. + * @return options + */ + public EdgeUpdateOptions keepNull(final Boolean keepNull) { + this.keepNull = keepNull; + return this; + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until document has been synced to disk. + * @return options + */ + public EdgeUpdateOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch replace a document based on target revision + * @return options + */ + public EdgeUpdateOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public EdgeUpdateOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/FulltextIndexOptions.java b/core/src/main/java/com/arangodb/model/FulltextIndexOptions.java similarity index 79% rename from src/main/java/com/arangodb/model/FulltextIndexOptions.java rename to core/src/main/java/com/arangodb/model/FulltextIndexOptions.java index 9bf8f82a5..d476c8bba 100644 --- a/src/main/java/com/arangodb/model/FulltextIndexOptions.java +++ b/core/src/main/java/com/arangodb/model/FulltextIndexOptions.java @@ -1,76 +1,79 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.IndexType; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public class FulltextIndexOptions extends IndexOptions { - - private Iterable fields; - private final IndexType type = IndexType.fulltext; - private Integer minLength; - - public FulltextIndexOptions() { - super(); - } - - @Override - protected FulltextIndexOptions getThis() { - return this; - } - - protected Iterable getFields() { - return fields; - } - - /** - * @param fields A list of attribute paths - * @return options - */ - protected FulltextIndexOptions fields(final Iterable fields) { - this.fields = fields; - return this; - } - - protected IndexType getType() { - return type; - } - - public Integer getMinLength() { - return minLength; - } - - /** - * @param minLength Minimum character length of words to index. Will default to a server-defined value if unspecified. It - * is thus recommended to set this value explicitly when creating the index. - * @return options - */ - public FulltextIndexOptions minLength(final Integer minLength) { - this.minLength = minLength; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + +/** + * @author Mark Vollmary + * @see API + * Documentation + * @deprecated since ArangoDB 3.10, use ArangoSearch or Inverted indexes instead. + */ +@Deprecated +public final class FulltextIndexOptions extends IndexOptions { + + private final IndexType type = IndexType.fulltext; + private Iterable fields; + private Integer minLength; + + public FulltextIndexOptions() { + super(); + } + + @Override + FulltextIndexOptions getThis() { + return this; + } + + public Iterable getFields() { + return fields; + } + + /** + * @param fields A list of attribute paths + * @return options + */ + FulltextIndexOptions fields(final Iterable fields) { + this.fields = fields; + return this; + } + + public IndexType getType() { + return type; + } + + public Integer getMinLength() { + return minLength; + } + + /** + * @param minLength Minimum character length of words to index. Will default to a server-defined value if + * unspecified. It + * is thus recommended to set this value explicitly when creating the index. + * @return options + */ + public FulltextIndexOptions minLength(final Integer minLength) { + this.minLength = minLength; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/GeoIndexOptions.java b/core/src/main/java/com/arangodb/model/GeoIndexOptions.java similarity index 56% rename from src/main/java/com/arangodb/model/GeoIndexOptions.java rename to core/src/main/java/com/arangodb/model/GeoIndexOptions.java index 691ed0ec2..4a95e2274 100644 --- a/src/main/java/com/arangodb/model/GeoIndexOptions.java +++ b/core/src/main/java/com/arangodb/model/GeoIndexOptions.java @@ -1,75 +1,94 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.IndexType; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class GeoIndexOptions extends IndexOptions { - - private Iterable fields; - private final IndexType type = IndexType.geo; - private Boolean geoJson; - - public GeoIndexOptions() { - super(); - } - - @Override - protected GeoIndexOptions getThis() { - return this; - } - - protected Iterable getFields() { - return fields; - } - - /** - * @param fields A list of attribute paths - * @return options - */ - protected GeoIndexOptions fields(final Iterable fields) { - this.fields = fields; - return this; - } - - protected IndexType getType() { - return type; - } - - public Boolean getGeoJson() { - return geoJson; - } - - /** - * @param geoJson If a geo-spatial index on a location is constructed and geoJson is true, then the order within the - * array is longitude followed by latitude. This corresponds to the format described in - * @return options - */ - public GeoIndexOptions geoJson(final Boolean geoJson) { - this.geoJson = geoJson; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + +/** + * @author Mark Vollmary + * @see + * API Documentation + */ +public final class GeoIndexOptions extends IndexOptions { + + private final IndexType type = IndexType.geo; + private Iterable fields; + private Boolean geoJson; + private Boolean legacyPolygons; + + public GeoIndexOptions() { + super(); + } + + @Override + GeoIndexOptions getThis() { + return this; + } + + public Iterable getFields() { + return fields; + } + + /** + * @param fields A list of attribute paths + * @return options + */ + GeoIndexOptions fields(final Iterable fields) { + this.fields = fields; + return this; + } + + public IndexType getType() { + return type; + } + + public Boolean getGeoJson() { + return geoJson; + } + + /** + * @param geoJson If a geo-spatial index on a location is constructed and geoJson is true, then the order within the + * array is longitude followed by latitude. This corresponds to the format described in + * @return options + */ + public GeoIndexOptions geoJson(final Boolean geoJson) { + this.geoJson = geoJson; + return this; + } + + public Boolean getLegacyPolygons() { + return legacyPolygons; + } + + /** + * @param legacyPolygons If `true` will use the old rules (pre-3.10) for the parsing GeoJSON polygons. This + * allows you to let old indexes produce the same, potentially wrong results as before an + * upgrade. A geo index with `legacyPolygons` set to `false` will use the new, correct and + * consistent method for parsing of GeoJSON polygons. + * See Legacy Polygons. + * @return options + * @since ArangoDB 3.10 + */ + public GeoIndexOptions legacyPolygons(final Boolean legacyPolygons) { + this.legacyPolygons = legacyPolygons; + return this; + } +} diff --git a/src/main/java/com/arangodb/model/GraphCreateOptions.java b/core/src/main/java/com/arangodb/model/GraphCreateOptions.java similarity index 61% rename from src/main/java/com/arangodb/model/GraphCreateOptions.java rename to core/src/main/java/com/arangodb/model/GraphCreateOptions.java index cf06b3e4b..a0db68f4c 100644 --- a/src/main/java/com/arangodb/model/GraphCreateOptions.java +++ b/core/src/main/java/com/arangodb/model/GraphCreateOptions.java @@ -1,326 +1,272 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.EdgeDefinition; -import com.arangodb.entity.ReplicationFactor; - -import java.util.Arrays; -import java.util.Collection; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class GraphCreateOptions { - - private String name; - private Collection edgeDefinitions; - private Collection orphanCollections; - private Boolean isSmart; - private SmartOptions options; - - public GraphCreateOptions() { - super(); - } - - protected String getName() { - return name; - } - - /** - * @param name Name of the graph - * @return options - */ - protected GraphCreateOptions name(final String name) { - this.name = name; - return this; - } - - public Collection getEdgeDefinitions() { - return edgeDefinitions; - } - - /** - * @param edgeDefinitions An array of definitions for the edge - * @return options - */ - protected GraphCreateOptions edgeDefinitions(final Collection edgeDefinitions) { - this.edgeDefinitions = edgeDefinitions; - return this; - } - - public Collection getOrphanCollections() { - return orphanCollections; - } - - /** - * @param orphanCollections Additional vertex collections - * @return options - */ - public GraphCreateOptions orphanCollections(final String... orphanCollections) { - this.orphanCollections = Arrays.asList(orphanCollections); - return this; - } - - public Boolean getIsSmart() { - return isSmart; - } - - /** - * @param isSmart Define if the created graph should be smart. This only has effect in Enterprise version. - * @return options - */ - public GraphCreateOptions isSmart(final Boolean isSmart) { - this.isSmart = isSmart; - return this; - } - - public Boolean getIsDisjoint() { - return getOptions().getIsDisjoint(); - } - - /** - * @param isDisjoint If set to true, a Disjoint SmartGraph will be created. This flag is not editable after - * creation. Default: false. - * @return options - * @since ArangoDB 3.7 - */ - public GraphCreateOptions isDisjoint(final Boolean isDisjoint) { - getOptions().setIsDisjoint(isDisjoint); - return this; - } - - public Integer getReplicationFactor() { - return getOptions().replicationFactor.getReplicationFactor(); - } - - /** - * @param replicationFactor (The default is 1): in a cluster, this attribute determines how many copies of each shard are kept on - * different DBServers. The value 1 means that only one copy (no synchronous replication) is kept. A - * value of k means that k-1 replicas are kept. Any two copies reside on different DBServers. Replication - * between them is synchronous, that is, every write operation to the "leader" copy will be replicated to - * all "follower" replicas, before the write operation is reported successful. If a server fails, this is - * detected automatically and one of the servers holding copies take over, usually without an error being - * reported. - * @return options - */ - public GraphCreateOptions replicationFactor(final Integer replicationFactor) { - getOptions().replicationFactor.setReplicationFactor(replicationFactor); - return this; - } - - public Boolean getSatellite() { - return getOptions().replicationFactor.getSatellite(); - } - - /** - * @param satellite If the true the graph is created as a satellite graph. In this case - * {@link #replicationFactor(Integer)} is ignored. - * @return options - * @since ArangoDB 3.7 - */ - public GraphCreateOptions satellite(final Boolean satellite) { - getOptions().replicationFactor.setSatellite(satellite); - return this; - } - - /** - * @deprecated use {@link #getWriteConcern()} instead - */ - @Deprecated - public Integer getMinReplicationFactor() { - return getOptions().getMinReplicationFactor(); - } - - /** - * @param minReplicationFactor (optional, default is 1): in a cluster, this attribute determines how many desired copies of each - * shard are kept on different DBServers. The value 1 means that only one copy (no synchronous - * replication) is kept. A value of k means that desired k-1 replicas are kept. If in a failover scenario - * a shard of a collection has less than minReplicationFactor many insync followers it will go into - * "read-only" mode and will reject writes until enough followers are insync again. In more detail: - * Having `minReplicationFactor == 1` means as soon as a "master-copy" is available of the data writes - * are allowed. Having `minReplicationFactor > 1` requires additional insync copies on follower servers - * to allow writes. - * @return options - * @deprecated use {@link #writeConcern(Integer)} instead - */ - @Deprecated - public GraphCreateOptions minReplicationFactor(final Integer minReplicationFactor) { - getOptions().setMinReplicationFactor(minReplicationFactor); - return this; - } - - public Integer getWriteConcern() { - return getOptions().getWriteConcern(); - } - - /** - * @param writeConcern Write concern for new collections in the graph. - * It determines how many copies of each shard are required to be in sync on the different - * DB-Servers. If there are less then these many copies in the cluster a shard will refuse to - * write. Writes to shards with enough up-to-date copies will succeed at the same time however. - * The value of writeConcern can not be larger than replicationFactor. (cluster only) - * @return options - */ - public GraphCreateOptions writeConcern(final Integer writeConcern) { - getOptions().setWriteConcern(writeConcern); - return this; - } - - public Integer getNumberOfShards() { - return getOptions().getNumberOfShards(); - } - - /** - * @param numberOfShards The number of shards that is used for every collection within this graph. Cannot be modified later. - * @return options - */ - public GraphCreateOptions numberOfShards(final Integer numberOfShards) { - getOptions().setNumberOfShards(numberOfShards); - return this; - } - - public String getSmartGraphAttribute() { - return getOptions().getSmartGraphAttribute(); - } - - /** - * @param smartGraphAttribute The attribute name that is used to smartly shard the vertices of a graph. Every vertex in this Graph - * has to have this attribute. Cannot be modified later. - * @return options - */ - public GraphCreateOptions smartGraphAttribute(final String smartGraphAttribute) { - getOptions().setSmartGraphAttribute(smartGraphAttribute); - return this; - } - - public Collection getSatellites() { - return getOptions().getSatellites(); - } - - /** - * @param satellites collection names that will be used to create SatelliteCollections - * for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only). Each array element - * must be a valid collection name. The collection type cannot be modified later. - * @return options - * @since ArangoDB 3.9.0 - */ - public GraphCreateOptions satellites(final String... satellites) { - getOptions().setSatellites(satellites); - return this; - } - - private SmartOptions getOptions() { - if (options == null) { - options = new SmartOptions(); - } - return options; - } - - public static class SmartOptions { - private ReplicationFactor replicationFactor; - private Integer minReplicationFactor; - private Integer writeConcern; - private Integer numberOfShards; - private String smartGraphAttribute; - private Boolean isDisjoint; - private Collection satellites; - - public SmartOptions() { - super(); - replicationFactor = new ReplicationFactor(); - } - - public Integer getReplicationFactor() { - return replicationFactor.getReplicationFactor(); - } - - public void setReplicationFactor(final Integer replicationFactor) { - this.replicationFactor.setReplicationFactor(replicationFactor); - } - - public Boolean getSatellite() { - return replicationFactor.getSatellite(); - } - - public void setSatellite(final Boolean satellite) { - replicationFactor.setSatellite(satellite); - } - - /** - * @deprecated use {{@link #getWriteConcern()}} instead - */ - @Deprecated - public Integer getMinReplicationFactor() { - return minReplicationFactor; - } - - /** - * @deprecated use {{@link #setWriteConcern(Integer)}} instead - */ - @Deprecated - public void setMinReplicationFactor(final Integer minReplicationFactor) { - this.minReplicationFactor = minReplicationFactor; - } - - public Integer getWriteConcern() { - return writeConcern; - } - - public void setWriteConcern(final Integer writeConcern) { - this.writeConcern = writeConcern; - } - - public Integer getNumberOfShards() { - return numberOfShards; - } - - public void setNumberOfShards(final Integer numberOfShards) { - this.numberOfShards = numberOfShards; - } - - public String getSmartGraphAttribute() { - return smartGraphAttribute; - } - - public void setSmartGraphAttribute(final String smartGraphAttribute) { - this.smartGraphAttribute = smartGraphAttribute; - } - - public Boolean getIsDisjoint() { - return isDisjoint; - } - - public void setIsDisjoint(final Boolean isDisjoint) { - this.isDisjoint = isDisjoint; - } - - public Collection getSatellites() { - return satellites; - } - - public void setSatellites(final String... satellites) { - this.satellites = Arrays.asList(satellites); - } - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.EdgeDefinition; +import com.arangodb.entity.ReplicationFactor; + +import java.util.Arrays; +import java.util.Collection; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class GraphCreateOptions { + + private String name; + private Collection edgeDefinitions; + private Collection orphanCollections; + private Boolean isSmart; + private SmartOptions options; + + public GraphCreateOptions() { + super(); + } + + public String getName() { + return name; + } + + /** + * @param name Name of the graph + * @return options + */ + GraphCreateOptions name(final String name) { + this.name = name; + return this; + } + + public Collection getEdgeDefinitions() { + return edgeDefinitions; + } + + /** + * @param edgeDefinitions An array of definitions for the edge + * @return options + */ + GraphCreateOptions edgeDefinitions(final Collection edgeDefinitions) { + this.edgeDefinitions = edgeDefinitions; + return this; + } + + public Collection getOrphanCollections() { + return orphanCollections; + } + + /** + * @param orphanCollections Additional vertex collections + * @return options + */ + public GraphCreateOptions orphanCollections(final String... orphanCollections) { + this.orphanCollections = Arrays.asList(orphanCollections); + return this; + } + + public Boolean getIsSmart() { + return isSmart; + } + + /** + * @param isSmart Define if the created graph should be smart. This only has effect in Enterprise version. + * @return options + */ + public GraphCreateOptions isSmart(final Boolean isSmart) { + this.isSmart = isSmart; + return this; + } + + public Boolean getIsDisjoint() { + return getOptions().getIsDisjoint(); + } + + /** + * @param isDisjoint If set to true, a Disjoint SmartGraph will be created. This flag is not editable after + * creation. Default: false. + * @return options + * @since ArangoDB 3.7 + */ + public GraphCreateOptions isDisjoint(final Boolean isDisjoint) { + getOptions().setIsDisjoint(isDisjoint); + return this; + } + + public ReplicationFactor getReplicationFactor() { + return getOptions().replicationFactor; + } + + /** + * @param replicationFactor (The default is 1): in a cluster, this attribute determines how many copies of each + * shard are kept on + * different DBServers. The value 1 means that only one copy (no synchronous + * replication) is kept. A + * value of k means that k-1 replicas are kept. Any two copies reside on different + * DBServers. Replication + * between them is synchronous, that is, every write operation to the "leader" copy will + * be replicated to + * all "follower" replicas, before the write operation is reported successful. If a + * server fails, this is + * detected automatically and one of the servers holding copies take over, usually + * without an error being + * reported. + * @return options + */ + public GraphCreateOptions replicationFactor(final ReplicationFactor replicationFactor) { + getOptions().setReplicationFactor(replicationFactor); + return this; + } + + public GraphCreateOptions replicationFactor(int replicationFactor) { + getOptions().setReplicationFactor(ReplicationFactor.of(replicationFactor)); + return this; + } + + public Integer getWriteConcern() { + return getOptions().getWriteConcern(); + } + + /** + * @param writeConcern Write concern for new collections in the graph. + * It determines how many copies of each shard are required to be in sync on the different + * DB-Servers. If there are less then these many copies in the cluster a shard will refuse to + * write. Writes to shards with enough up-to-date copies will succeed at the same time however. + * The value of writeConcern can not be larger than replicationFactor. (cluster only) + * @return options + */ + public GraphCreateOptions writeConcern(final Integer writeConcern) { + getOptions().setWriteConcern(writeConcern); + return this; + } + + public Integer getNumberOfShards() { + return getOptions().getNumberOfShards(); + } + + /** + * @param numberOfShards The number of shards that is used for every collection within this graph. Cannot be + * modified later. + * @return options + */ + public GraphCreateOptions numberOfShards(final Integer numberOfShards) { + getOptions().setNumberOfShards(numberOfShards); + return this; + } + + public String getSmartGraphAttribute() { + return getOptions().getSmartGraphAttribute(); + } + + /** + * @param smartGraphAttribute The attribute name that is used to smartly shard the vertices of a graph. Every + * vertex in this Graph + * has to have this attribute. Cannot be modified later. + * @return options + */ + public GraphCreateOptions smartGraphAttribute(final String smartGraphAttribute) { + getOptions().setSmartGraphAttribute(smartGraphAttribute); + return this; + } + + public Collection getSatellites() { + return getOptions().getSatellites(); + } + + /** + * @param satellites collection names that will be used to create SatelliteCollections + * for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only). Each array element + * must be a valid collection name. The collection type cannot be modified later. + * @return options + * @since ArangoDB 3.9.0 + */ + public GraphCreateOptions satellites(final String... satellites) { + getOptions().setSatellites(satellites); + return this; + } + + public SmartOptions getOptions() { + if (options == null) { + options = new SmartOptions(); + } + return options; + } + + public static final class SmartOptions { + private ReplicationFactor replicationFactor; + private Integer writeConcern; + private Integer numberOfShards; + private String smartGraphAttribute; + private Boolean isDisjoint; + private Collection satellites; + + public SmartOptions() { + super(); + } + + public ReplicationFactor getReplicationFactor() { + return replicationFactor; + } + + public void setReplicationFactor(final ReplicationFactor replicationFactor) { + this.replicationFactor = replicationFactor; + } + + public Integer getWriteConcern() { + return writeConcern; + } + + public void setWriteConcern(final Integer writeConcern) { + this.writeConcern = writeConcern; + } + + public Integer getNumberOfShards() { + return numberOfShards; + } + + public void setNumberOfShards(final Integer numberOfShards) { + this.numberOfShards = numberOfShards; + } + + public String getSmartGraphAttribute() { + return smartGraphAttribute; + } + + public void setSmartGraphAttribute(final String smartGraphAttribute) { + this.smartGraphAttribute = smartGraphAttribute; + } + + public Boolean getIsDisjoint() { + return isDisjoint; + } + + public void setIsDisjoint(final Boolean isDisjoint) { + this.isDisjoint = isDisjoint; + } + + public Collection getSatellites() { + return satellites; + } + + public void setSatellites(final String... satellites) { + this.satellites = Arrays.asList(satellites); + } + } + +} diff --git a/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java b/core/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java similarity index 82% rename from src/main/java/com/arangodb/model/GraphDocumentReadOptions.java rename to core/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java index 1e661f64d..6e3e803a0 100644 --- a/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java +++ b/core/src/main/java/com/arangodb/model/GraphDocumentReadOptions.java @@ -20,23 +20,18 @@ package com.arangodb.model; -import com.arangodb.velocypack.annotations.Expose; - /** * @author Mark Vollmary */ -public class GraphDocumentReadOptions { +public final class GraphDocumentReadOptions { private String ifNoneMatch; private String ifMatch; - private boolean catchException; - @Expose(serialize = false) private Boolean allowDirtyRead; private String streamTransactionId; public GraphDocumentReadOptions() { super(); - catchException = true; } public String getIfNoneMatch() { @@ -65,19 +60,6 @@ public GraphDocumentReadOptions ifMatch(final String ifMatch) { return this; } - public boolean isCatchException() { - return catchException; - } - - /** - * @param catchException whether or not catch possible thrown exceptions - * @return options - */ - public GraphDocumentReadOptions catchException(final boolean catchException) { - this.catchException = catchException; - return this; - } - /** * @param allowDirtyRead Set to {@code true} allows reading from followers in an active-failover setup. * @return options diff --git a/src/main/java/com/arangodb/model/HashIndexOptions.java b/core/src/main/java/com/arangodb/model/HashIndexOptions.java similarity index 79% rename from src/main/java/com/arangodb/model/HashIndexOptions.java rename to core/src/main/java/com/arangodb/model/HashIndexOptions.java index 3af784ebb..1924debe7 100644 --- a/src/main/java/com/arangodb/model/HashIndexOptions.java +++ b/core/src/main/java/com/arangodb/model/HashIndexOptions.java @@ -1,122 +1,121 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.IndexType; - -/** - * @author Mark Vollmary - * @see API Documentation - * @deprecated use {@link PersistentIndexOptions} instead. Since ArangoDB 3.7 a hash index is an alias for a persistent - * index. - */ -@Deprecated -public class HashIndexOptions extends IndexOptions { - - private Iterable fields; - private final IndexType type = IndexType.hash; - private Boolean unique; - private Boolean sparse; - private Boolean deduplicate; - private Boolean estimates; - - public HashIndexOptions() { - super(); - } - - @Override - protected HashIndexOptions getThis() { - return this; - } - - protected Iterable getFields() { - return fields; - } - - /** - * @param fields A list of attribute paths - * @return options - */ - protected HashIndexOptions fields(final Iterable fields) { - this.fields = fields; - return this; - } - - protected IndexType getType() { - return type; - } - - public Boolean getUnique() { - return unique; - } - - /** - * @param unique if true, then create a unique index - * @return options - */ - public HashIndexOptions unique(final Boolean unique) { - this.unique = unique; - return this; - } - - public Boolean getSparse() { - return sparse; - } - - /** - * @param sparse if true, then create a sparse index - * @return options - */ - public HashIndexOptions sparse(final Boolean sparse) { - this.sparse = sparse; - return this; - } - - public Boolean getDeduplicate() { - return deduplicate; - } - - /** - * @param deduplicate - * if false, the deduplication of array values is turned off. - * @return options - */ - public HashIndexOptions deduplicate(final Boolean deduplicate) { - this.deduplicate = deduplicate; - return this; - } - - /** - * @param estimates - * This attribute controls whether index selectivity estimates are maintained for the index. Default: {@code - * true} - * @since ArangoDB 3.8 - */ - public HashIndexOptions estimates(final Boolean estimates) { - this.estimates = estimates; - return this; - } - - public Boolean getEstimates() { - return estimates; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + +/** + * @author Mark Vollmary + * @see API Documentation + * @deprecated use {@link PersistentIndexOptions} instead. Since ArangoDB 3.7 a hash index is an alias for a persistent + * index. + */ +@Deprecated +public final class HashIndexOptions extends IndexOptions { + + private final IndexType type = IndexType.hash; + private Iterable fields; + private Boolean unique; + private Boolean sparse; + private Boolean deduplicate; + private Boolean estimates; + + public HashIndexOptions() { + super(); + } + + @Override + HashIndexOptions getThis() { + return this; + } + + public Iterable getFields() { + return fields; + } + + /** + * @param fields A list of attribute paths + * @return options + */ + HashIndexOptions fields(final Iterable fields) { + this.fields = fields; + return this; + } + + public IndexType getType() { + return type; + } + + public Boolean getUnique() { + return unique; + } + + /** + * @param unique if true, then create a unique index + * @return options + */ + public HashIndexOptions unique(final Boolean unique) { + this.unique = unique; + return this; + } + + public Boolean getSparse() { + return sparse; + } + + /** + * @param sparse if true, then create a sparse index + * @return options + */ + public HashIndexOptions sparse(final Boolean sparse) { + this.sparse = sparse; + return this; + } + + public Boolean getDeduplicate() { + return deduplicate; + } + + /** + * @param deduplicate if false, the deduplication of array values is turned off. + * @return options + */ + public HashIndexOptions deduplicate(final Boolean deduplicate) { + this.deduplicate = deduplicate; + return this; + } + + /** + * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. + * Default: {@code + * true} + * @since ArangoDB 3.8 + */ + public HashIndexOptions estimates(final Boolean estimates) { + this.estimates = estimates; + return this; + } + + public Boolean getEstimates() { + return estimates; + } + +} diff --git a/src/main/java/com/arangodb/model/ImportType.java b/core/src/main/java/com/arangodb/model/ImportType.java similarity index 96% rename from src/main/java/com/arangodb/model/ImportType.java rename to core/src/main/java/com/arangodb/model/ImportType.java index 17e4d5573..3cbd123e0 100644 --- a/src/main/java/com/arangodb/model/ImportType.java +++ b/core/src/main/java/com/arangodb/model/ImportType.java @@ -1,28 +1,28 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - */ -public enum ImportType { - documents, list, auto -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + */ +public enum ImportType { + documents, list, auto +} diff --git a/src/main/java/com/arangodb/model/IndexOptions.java b/core/src/main/java/com/arangodb/model/IndexOptions.java similarity index 82% rename from src/main/java/com/arangodb/model/IndexOptions.java rename to core/src/main/java/com/arangodb/model/IndexOptions.java index 1132e1c8e..31a62c04e 100644 --- a/src/main/java/com/arangodb/model/IndexOptions.java +++ b/core/src/main/java/com/arangodb/model/IndexOptions.java @@ -1,65 +1,64 @@ -/* - * DISCLAIMER - * - * Copyright 2019 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Heiko Kernbach - *

    - * This class is used for all index similarities - */ -public abstract class IndexOptions { - - private Boolean inBackground; - private String name; - - public IndexOptions() { - super(); - } - - protected abstract T getThis(); - - /** - * @param inBackground create the the index in the background - * this is a RocksDB only flag. - * @return options - */ - public T inBackground(final Boolean inBackground) { - this.inBackground = inBackground; - return getThis(); - } - - public Boolean getInBackground() { - return inBackground; - } - - /** - * @param name the name of the index - * @return options - */ - public T name(final String name) { - this.name = name; - return getThis(); - } - - protected String getName() { - return name; - } -} +/* + * DISCLAIMER + * + * Copyright 2019 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Heiko Kernbach + *

    + * This final class is used for all index similarities + */ +public abstract class IndexOptions> { + + private Boolean inBackground; + private String name; + + protected IndexOptions() { + } + + abstract T getThis(); + + /** + * @param inBackground create the the index in the background + * this is a RocksDB only flag. + * @return options + */ + public T inBackground(final Boolean inBackground) { + this.inBackground = inBackground; + return getThis(); + } + + public Boolean getInBackground() { + return inBackground; + } + + /** + * @param name the name of the index + * @return options + */ + public T name(final String name) { + this.name = name; + return getThis(); + } + + public String getName() { + return name; + } +} diff --git a/core/src/main/java/com/arangodb/model/InvertedIndexOptions.java b/core/src/main/java/com/arangodb/model/InvertedIndexOptions.java new file mode 100644 index 000000000..d03422bf7 --- /dev/null +++ b/core/src/main/java/com/arangodb/model/InvertedIndexOptions.java @@ -0,0 +1,362 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; +import com.arangodb.entity.InvertedIndexField; +import com.arangodb.entity.InvertedIndexPrimarySort; +import com.arangodb.entity.arangosearch.*; + +import java.util.*; + +/** + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.10 + */ +public final class InvertedIndexOptions extends IndexOptions { + + private final IndexType type = IndexType.inverted; + private Integer parallelism; + private InvertedIndexPrimarySort primarySort; + private final Collection storedValues = new ArrayList<>(); + private String analyzer; + private final Set features = new HashSet<>(); + private Boolean includeAllFields; + private Boolean trackListPositions; + private Boolean searchField; + private final Collection fields = new ArrayList<>(); + private Long consolidationIntervalMsec; + private Long commitIntervalMsec; + private Long cleanupIntervalStep; + private ConsolidationPolicy consolidationPolicy; + private Long writebufferIdle; + private Long writebufferActive; + private Long writebufferSizeMax; + + public InvertedIndexOptions() { + super(); + } + + @Override + InvertedIndexOptions getThis() { + return this; + } + + public IndexType getType() { + return type; + } + + public Integer getParallelism() { + return parallelism; + } + + /** + * @param parallelism The number of threads to use for indexing the fields. Default: 2 + * @return this + */ + public InvertedIndexOptions parallelism(Integer parallelism) { + this.parallelism = parallelism; + return this; + } + + public InvertedIndexPrimarySort getPrimarySort() { + return primarySort; + } + + /** + * @param primarySort You can define a primary sort order to enable an AQL optimization. If a query iterates over + * all documents of a collection, wants to sort them by attribute values, and the (left-most) + * fields to sort by, as well as their sorting direction, match with the primarySort definition, + * then the SORT operation is optimized away. + * @return this + */ + public InvertedIndexOptions primarySort(InvertedIndexPrimarySort primarySort) { + this.primarySort = primarySort; + return this; + } + + public Collection getStoredValues() { + return storedValues; + } + + /** + * @param storedValues The optional storedValues attribute can contain an array of paths to additional attributes to + * store in the index. These additional attributes cannot be used for index lookups or for + * sorting, but they can be used for projections. This allows an index to fully cover more + * queries and avoid extra document lookups. + * @return this + */ + public InvertedIndexOptions storedValues(StoredValue... storedValues) { + Collections.addAll(this.storedValues, storedValues); + return this; + } + + public String getAnalyzer() { + return analyzer; + } + + /** + * @param analyzer The name of an Analyzer to use by default. This Analyzer is applied to the values of the indexed + * fields for which you don’t define Analyzers explicitly. + * @return this + */ + public InvertedIndexOptions analyzer(String analyzer) { + this.analyzer = analyzer; + return this; + } + + public Set getFeatures() { + return features; + } + + /** + * @param features A list of Analyzer features to use by default. They define what features are enabled for the + * default analyzer. + * @return this + */ + public InvertedIndexOptions features(AnalyzerFeature... features) { + Collections.addAll(this.features, features); + return this; + } + + public Boolean getIncludeAllFields() { + return includeAllFields; + } + + /** + * @param includeAllFields This option only applies if you use the inverted index in a search-alias Views. If set to + * true, then all sub-attributes of this field are indexed, excluding any sub-attributes + * that are configured separately by other elements in the fields array (and their + * sub-attributes). The analyzer and features properties apply to the sub-attributes. If set + * to false, then sub-attributes are ignored. The default value is defined by the top-level + * includeAllFields option, or false if not set. + * @return this + */ + public InvertedIndexOptions includeAllFields(Boolean includeAllFields) { + this.includeAllFields = includeAllFields; + return this; + } + + public Boolean getTrackListPositions() { + return trackListPositions; + } + + /** + * @param trackListPositions This option only applies if you use the inverted index in a search-alias Views. If set + * to true, then track the value position in arrays for array values. For example, when + * querying a document like { attr: [ "valueX", "valueY", "valueZ" ] }, you need to + * specify the array element, e.g. doc.attr[1] == "valueY". If set to false, all values in + * an array are treated as equal alternatives. You don’t specify an array element in + * queries, e.g. doc.attr == "valueY", and all elements are searched for a match. Default: + * the value defined by the top-level trackListPositions option, or false if not set. + * @return this + */ + public InvertedIndexOptions trackListPositions(Boolean trackListPositions) { + this.trackListPositions = trackListPositions; + return this; + } + + public Boolean getSearchField() { + return searchField; + } + + /** + * @param searchField This option only applies if you use the inverted index in a search-alias Views. You can set + * the option to true to get the same behavior as with arangosearch Views regarding the indexing + * of array values as the default. If enabled, both, array and primitive values (strings, + * numbers, etc.) are accepted. Every element of an array is indexed according to the + * trackListPositions option. If set to false, it depends on the attribute path. If it explicitly + * expand an array ([*]), then the elements are indexed separately. Otherwise, the array is + * indexed as a whole, but only geopoint and aql Analyzers accept array inputs. You cannot use an + * array expansion if searchField is enabled. + * @return this + */ + public InvertedIndexOptions searchField(Boolean searchField) { + this.searchField = searchField; + return this; + } + + public Collection getFields() { + return fields; + } + + /** + * @param fields An array of attribute paths as strings to index the fields with the default options, or objects to + * specify options for the fields. + * @return this + */ + public InvertedIndexOptions fields(InvertedIndexField... fields) { + Collections.addAll(this.fields, fields); + return this; + } + + public Long getConsolidationIntervalMsec() { + return consolidationIntervalMsec; + } + + /** + * @param consolidationIntervalMsec Wait at least this many milliseconds between applying ‘consolidationPolicy’ to + * consolidate View data store and possibly release space on the filesystem + * (default: 1000, to disable use: 0). For the case where there are a lot of data + * modification operations, a higher value could potentially have the data store + * consume more space and file handles. For the case where there are a few data + * modification operations, a lower value will impact performance due to no segment + * candidates available for consolidation. Background: For data modification + * ArangoSearch Views follow the concept of a “versioned data store”. Thus old + * versions of data may be removed once there are no longer any users of the old + * data. The frequency of the cleanup and compaction operations are governed by + * ‘consolidationIntervalMsec’ and the candidates for compaction are selected via + * ‘consolidationPolicy’. + * @return this + */ + public InvertedIndexOptions consolidationIntervalMsec(Long consolidationIntervalMsec) { + this.consolidationIntervalMsec = consolidationIntervalMsec; + return this; + } + + public Long getCommitIntervalMsec() { + return commitIntervalMsec; + } + + /** + * @param commitIntervalMsec Wait at least this many milliseconds between committing View data store changes and + * making documents visible to queries (default: 1000, to disable use: 0). For the case + * where there are a lot of inserts/updates, a lower value, until commit, will cause the + * index not to account for them and memory usage would continue to grow. For the case + * where there are a few inserts/updates, a higher value will impact performance and waste + * disk space for each commit call without any added benefits. Background: For data + * retrieval ArangoSearch Views follow the concept of “eventually-consistent”, i.e. + * eventually all the data in ArangoDB will be matched by corresponding query expressions. + * The concept of ArangoSearch View “commit” operation is introduced to control the + * upper-bound on the time until document addition/removals are actually reflected by + * corresponding query expressions. Once a “commit” operation is complete all documents + * added/removed prior to the start of the “commit” operation will be reflected by queries + * invoked in subsequent ArangoDB transactions, in-progress ArangoDB transactions will + * still continue to return a repeatable-read state. + * @return this + */ + public InvertedIndexOptions commitIntervalMsec(Long commitIntervalMsec) { + this.commitIntervalMsec = commitIntervalMsec; + return this; + } + + public Long getCleanupIntervalStep() { + return cleanupIntervalStep; + } + + /** + * @param cleanupIntervalStep Wait at least this many commits between removing unused files in the ArangoSearch data + * directory (default: 2, to disable use: 0). For the case where the consolidation + * policies merge segments often (i.e. a lot of commit+consolidate), a lower value will + * cause a lot of disk space to be wasted. For the case where the consolidation policies + * rarely merge segments (i.e. few inserts/deletes), a higher value will impact + * performance without any added benefits. Background: With every “commit” or + * “consolidate” operation a new state of the View internal data-structures is created on + * disk. Old states/snapshots are released once there are no longer any users remaining. + * However, the files for the released states/snapshots are left on disk, and only + * removed by “cleanup” operation. + * @return this + */ + public InvertedIndexOptions cleanupIntervalStep(Long cleanupIntervalStep) { + this.cleanupIntervalStep = cleanupIntervalStep; + return this; + } + + public ConsolidationPolicy getConsolidationPolicy() { + return consolidationPolicy; + } + + /** + * @param consolidationPolicy The consolidation policy to apply for selecting which segments should be merged + * (default: {}). Background: With each ArangoDB transaction that inserts documents one + * or more ArangoSearch internal segments gets created. Similarly for removed documents + * the segments that contain such documents will have these documents marked as + * ‘deleted’. Over time this approach causes a lot of small and sparse segments to be + * created. A “consolidation” operation selects one or more segments and copies all of + * their valid documents into a single new segment, thereby allowing the search algorithm + * to perform more optimally and for extra file handles to be released once old segments + * are no longer used. + * @return this + */ + public InvertedIndexOptions consolidationPolicy(ConsolidationPolicy consolidationPolicy) { + this.consolidationPolicy = consolidationPolicy; + return this; + } + + public Long getWritebufferIdle() { + return writebufferIdle; + } + + /** + * @param writebufferIdle Maximum number of writers (segments) cached in the pool (default: 64, use 0 to disable) + * @return this + */ + public InvertedIndexOptions writebufferIdle(Long writebufferIdle) { + this.writebufferIdle = writebufferIdle; + return this; + } + + public Long getWritebufferActive() { + return writebufferActive; + } + + /** + * @param writebufferActive Maximum number of concurrent active writers (segments) that perform a transaction. Other + * writers (segments) wait till current active writers (segments) finish (default: 0, use 0 + * to disable) + * @return this + */ + public InvertedIndexOptions writebufferActive(Long writebufferActive) { + this.writebufferActive = writebufferActive; + return this; + } + + public Long getWritebufferSizeMax() { + return writebufferSizeMax; + } + + /** + * @param writebufferSizeMax Maximum memory byte size per writer (segment) before a writer (segment) flush is + * triggered. 0 value turns off this limit for any writer (buffer) and data will be + * flushed periodically based on the value defined for the flush thread (ArangoDB server + * startup option). 0 value should be used carefully due to high potential memory + * consumption (default: 33554432, use 0 to disable) + * @return this + */ + public InvertedIndexOptions writebufferSizeMax(Long writebufferSizeMax) { + this.writebufferSizeMax = writebufferSizeMax; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + InvertedIndexOptions that = (InvertedIndexOptions) o; + return type == that.type && Objects.equals(parallelism, that.parallelism) && Objects.equals(primarySort, that.primarySort) && Objects.equals(storedValues, that.storedValues) && Objects.equals(analyzer, that.analyzer) && Objects.equals(features, that.features) && Objects.equals(includeAllFields, that.includeAllFields) && Objects.equals(trackListPositions, that.trackListPositions) && Objects.equals(searchField, that.searchField) && Objects.equals(fields, that.fields) && Objects.equals(consolidationIntervalMsec, that.consolidationIntervalMsec) && Objects.equals(commitIntervalMsec, that.commitIntervalMsec) && Objects.equals(cleanupIntervalStep, that.cleanupIntervalStep) && Objects.equals(consolidationPolicy, that.consolidationPolicy) && Objects.equals(writebufferIdle, that.writebufferIdle) && Objects.equals(writebufferActive, that.writebufferActive) && Objects.equals(writebufferSizeMax, that.writebufferSizeMax); + } + + @Override + public int hashCode() { + return Objects.hash(type, parallelism, primarySort, storedValues, analyzer, features, includeAllFields, trackListPositions, searchField, fields, consolidationIntervalMsec, commitIntervalMsec, cleanupIntervalStep, consolidationPolicy, writebufferIdle, writebufferActive, writebufferSizeMax); + } +} diff --git a/src/main/java/com/arangodb/model/LogOptions.java b/core/src/main/java/com/arangodb/model/LogOptions.java similarity index 92% rename from src/main/java/com/arangodb/model/LogOptions.java rename to core/src/main/java/com/arangodb/model/LogOptions.java index 9a37cdf08..a8d29071d 100644 --- a/src/main/java/com/arangodb/model/LogOptions.java +++ b/core/src/main/java/com/arangodb/model/LogOptions.java @@ -1,151 +1,152 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.LogLevel; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public class LogOptions { - - public static final String PROPERTY_UPTO = "upto"; - public static final String PROPERTY_LEVEL = "level"; - public static final String PROPERTY_START = "start"; - public static final String PROPERTY_SIZE = "size"; - public static final String PROPERTY_OFFSET = "offset"; - public static final String PROPERTY_SEARCH = "search"; - public static final String PROPERTY_SORT = "sort"; - - public enum SortOrder { - asc, desc - } - - private LogLevel upto; - private LogLevel level; - private Long start; - private Integer size; - private Integer offset; - private String search; - private SortOrder sort; - - public LogOptions() { - super(); - } - - public LogLevel getUpto() { - return upto; - } - - /** - * @param upto Returns all log entries up to log level upto - * @return options - */ - public LogOptions upto(final LogLevel upto) { - this.upto = upto; - return this; - } - - public LogLevel getLevel() { - return level; - } - - /** - * @param level Returns all log entries of log level level. Note that the query parameters upto and level are mutually - * exclusive - * @return options - */ - public LogOptions level(final LogLevel level) { - this.level = level; - return this; - } - - public Long getStart() { - return start; - } - - /** - * @param start Returns all log entries such that their log entry identifier (lid value) is greater or equal to start - * @return options - */ - public LogOptions start(final Long start) { - this.start = start; - return this; - } - - public Integer getSize() { - return size; - } - - /** - * @param size Restricts the result to at most size log entries - * @return options - */ - public LogOptions size(final Integer size) { - this.size = size; - return this; - } - - public Integer getOffset() { - return offset; - } - - /** - * @param offset Starts to return log entries skipping the first offset log entries. offset and size can be used for - * pagination - * @return options - */ - public LogOptions offset(final Integer offset) { - this.offset = offset; - return this; - } - - public String getSearch() { - return search; - } - - /** - * @param search Only return the log entries containing the text specified in search - * @return options - */ - public LogOptions search(final String search) { - this.search = search; - return this; - } - - public SortOrder getSort() { - return sort; - } - - /** - * @param sort Sort the log entries either ascending (if sort is asc) or descending (if sort is desc) according to - * their lid values. Note that the lid imposes a chronological order. The default value is asc - * @return options - */ - public LogOptions sort(final SortOrder sort) { - this.sort = sort; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.LogLevel; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class LogOptions { + + public static final String PROPERTY_UPTO = "upto"; + public static final String PROPERTY_LEVEL = "level"; + public static final String PROPERTY_START = "start"; + public static final String PROPERTY_SIZE = "size"; + public static final String PROPERTY_OFFSET = "offset"; + public static final String PROPERTY_SEARCH = "search"; + public static final String PROPERTY_SORT = "sort"; + private LogLevel upto; + private LogLevel level; + private Long start; + private Integer size; + private Integer offset; + private String search; + private SortOrder sort; + + public LogOptions() { + super(); + } + + public LogLevel getUpto() { + return upto; + } + + /** + * @param upto Returns all log entries up to log level upto + * @return options + */ + public LogOptions upto(final LogLevel upto) { + this.upto = upto; + return this; + } + + public LogLevel getLevel() { + return level; + } + + /** + * @param level Returns all log entries of log level level. Note that the query parameters upto and level are + * mutually + * exclusive + * @return options + */ + public LogOptions level(final LogLevel level) { + this.level = level; + return this; + } + + public Long getStart() { + return start; + } + + /** + * @param start Returns all log entries such that their log entry identifier (lid value) is greater or equal to + * start + * @return options + */ + public LogOptions start(final Long start) { + this.start = start; + return this; + } + + public Integer getSize() { + return size; + } + + /** + * @param size Restricts the result to at most size log entries + * @return options + */ + public LogOptions size(final Integer size) { + this.size = size; + return this; + } + + public Integer getOffset() { + return offset; + } + + /** + * @param offset Starts to return log entries skipping the first offset log entries. offset and size can be used for + * pagination + * @return options + */ + public LogOptions offset(final Integer offset) { + this.offset = offset; + return this; + } + + public String getSearch() { + return search; + } + + /** + * @param search Only return the log entries containing the text specified in search + * @return options + */ + public LogOptions search(final String search) { + this.search = search; + return this; + } + + public SortOrder getSort() { + return sort; + } + + /** + * @param sort Sort the log entries either ascending (if sort is asc) or descending (if sort is desc) according to + * their lid values. Note that the lid imposes a chronological order. The default value is asc + * @return options + */ + public LogOptions sort(final SortOrder sort) { + this.sort = sort; + return this; + } + + public enum SortOrder { + asc, desc + } + +} diff --git a/src/main/java/com/arangodb/model/OptionsBuilder.java b/core/src/main/java/com/arangodb/model/OptionsBuilder.java similarity index 95% rename from src/main/java/com/arangodb/model/OptionsBuilder.java rename to core/src/main/java/com/arangodb/model/OptionsBuilder.java index ab99ad37f..3b4f6c86d 100644 --- a/src/main/java/com/arangodb/model/OptionsBuilder.java +++ b/core/src/main/java/com/arangodb/model/OptionsBuilder.java @@ -23,15 +23,15 @@ import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.Permissions; import com.arangodb.entity.ViewType; -import com.arangodb.velocypack.VPackSlice; import java.util.Collection; +import java.util.Map; /** * @author Mark Vollmary * @author Michele Rastelli */ -public class OptionsBuilder { +public final class OptionsBuilder { private OptionsBuilder() { super(); @@ -67,6 +67,7 @@ public static GeoIndexOptions build(final GeoIndexOptions options, final Iterabl return options.fields(fields); } + @Deprecated public static FulltextIndexOptions build(final FulltextIndexOptions options, final Iterable fields) { return options.fields(fields); } @@ -83,14 +84,15 @@ public static CollectionCreateOptions build(final CollectionCreateOptions option return options.name(name); } - public static AqlQueryOptions build(final AqlQueryOptions options, final String query, final VPackSlice bindVars) { + public static AqlQueryOptions build(final AqlQueryOptions options, final String query, + final Map bindVars) { return options.query(query).bindVars(bindVars); } public static AqlQueryExplainOptions build( final AqlQueryExplainOptions options, final String query, - final VPackSlice bindVars) { + final Map bindVars) { return options.query(query).bindVars(bindVars); } diff --git a/src/main/java/com/arangodb/model/OverwriteMode.java b/core/src/main/java/com/arangodb/model/OverwriteMode.java similarity index 100% rename from src/main/java/com/arangodb/model/OverwriteMode.java rename to core/src/main/java/com/arangodb/model/OverwriteMode.java diff --git a/src/main/java/com/arangodb/model/PersistentIndexOptions.java b/core/src/main/java/com/arangodb/model/PersistentIndexOptions.java similarity index 54% rename from src/main/java/com/arangodb/model/PersistentIndexOptions.java rename to core/src/main/java/com/arangodb/model/PersistentIndexOptions.java index c9ba08c34..583a2e107 100644 --- a/src/main/java/com/arangodb/model/PersistentIndexOptions.java +++ b/core/src/main/java/com/arangodb/model/PersistentIndexOptions.java @@ -1,121 +1,158 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.IndexType; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public class PersistentIndexOptions extends IndexOptions { - - private Iterable fields; - protected final IndexType type = IndexType.persistent; - private Boolean unique; - private Boolean sparse; - private Boolean deduplicate; - private Boolean estimates; - - public PersistentIndexOptions() { - super(); - } - - @Override - protected PersistentIndexOptions getThis() { - return this; - } - - protected Iterable getFields() { - return fields; - } - - /** - * @param fields A list of attribute paths - * @return options - */ - protected PersistentIndexOptions fields(final Iterable fields) { - this.fields = fields; - return this; - } - - protected IndexType getType() { - return type; - } - - public Boolean getUnique() { - return unique; - } - - /** - * @param unique if true, then create a unique index - * @return options - */ - public PersistentIndexOptions unique(final Boolean unique) { - this.unique = unique; - return this; - } - - public Boolean getSparse() { - return sparse; - } - - /** - * @param sparse - * if true, then create a sparse index - * @return options - */ - public PersistentIndexOptions sparse(final Boolean sparse) { - this.sparse = sparse; - return this; - } - - public Boolean getDeduplicate() { - return deduplicate; - } - - /** - * @param deduplicate - * if false, the deduplication of array values is turned off. Default: {@code true} - * @return options - */ - public PersistentIndexOptions deduplicate(final Boolean deduplicate) { - this.deduplicate = deduplicate; - return this; - } - - /** - * @param estimates - * This attribute controls whether index selectivity estimates are maintained for the index. Default: {@code - * true} - * @since ArangoDB 3.8 - */ - public PersistentIndexOptions estimates(final Boolean estimates) { - this.estimates = estimates; - return this; - } - - public Boolean getEstimates() { - return estimates; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; + +/** + * @author Mark Vollmary + * @see API + * Documentation + */ +public final class PersistentIndexOptions extends IndexOptions { + + private final IndexType type = IndexType.persistent; + private Iterable fields; + private Boolean unique; + private Boolean sparse; + private Boolean deduplicate; + private Boolean estimates; + private Boolean cacheEnabled; + private Collection storedValues; + + public PersistentIndexOptions() { + super(); + } + + @Override + PersistentIndexOptions getThis() { + return this; + } + + public Iterable getFields() { + return fields; + } + + /** + * @param fields A list of attribute paths + * @return options + */ + PersistentIndexOptions fields(final Iterable fields) { + this.fields = fields; + return this; + } + + public IndexType getType() { + return type; + } + + public Boolean getUnique() { + return unique; + } + + /** + * @param unique if true, then create a unique index + * @return options + */ + public PersistentIndexOptions unique(final Boolean unique) { + this.unique = unique; + return this; + } + + public Boolean getSparse() { + return sparse; + } + + /** + * @param sparse if true, then create a sparse index + * @return options + */ + public PersistentIndexOptions sparse(final Boolean sparse) { + this.sparse = sparse; + return this; + } + + public Boolean getDeduplicate() { + return deduplicate; + } + + /** + * @param deduplicate if false, the deduplication of array values is turned off. Default: {@code true} + * @return options + */ + public PersistentIndexOptions deduplicate(final Boolean deduplicate) { + this.deduplicate = deduplicate; + return this; + } + + /** + * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. + * Default: {@code + * true} + * @since ArangoDB 3.8 + */ + public PersistentIndexOptions estimates(final Boolean estimates) { + this.estimates = estimates; + return this; + } + + public Boolean getEstimates() { + return estimates; + } + + /** + * @param cacheEnabled enables in-memory caching of index entries + * @return options + * @since ArangoDB 3.10 + */ + public PersistentIndexOptions cacheEnabled(final Boolean cacheEnabled) { + this.cacheEnabled = cacheEnabled; + return this; + } + + public Boolean getCacheEnabled() { + return cacheEnabled; + } + + public Collection getStoredValues() { + return storedValues; + } + + /** + * @param storedValues (optional) array of paths to additional attributes to store in the index. These additional + * attributes cannot be used for index lookups or for sorting, but they can be used for + * projections. This allows an index to fully cover more queries and avoid extra document + * lookups. The maximum number of attributes in `storedValues` is 32. + * @return options + */ + public PersistentIndexOptions storedValues(final String... storedValues) { + if (this.storedValues == null) { + this.storedValues = new HashSet<>(); + } + Collections.addAll(this.storedValues, storedValues); + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/QueueTimeSample.java b/core/src/main/java/com/arangodb/model/QueueTimeSample.java similarity index 96% rename from src/main/java/com/arangodb/model/QueueTimeSample.java rename to core/src/main/java/com/arangodb/model/QueueTimeSample.java index 841221761..bfc1f2496 100644 --- a/src/main/java/com/arangodb/model/QueueTimeSample.java +++ b/core/src/main/java/com/arangodb/model/QueueTimeSample.java @@ -10,7 +10,7 @@ * @author Michele Rastelli * @see API Documentation */ -public class QueueTimeSample { +public final class QueueTimeSample { /** * Unix-timestamp in milliseconds, recorded at client side. */ diff --git a/src/main/java/com/arangodb/model/SkiplistIndexOptions.java b/core/src/main/java/com/arangodb/model/SkiplistIndexOptions.java similarity index 79% rename from src/main/java/com/arangodb/model/SkiplistIndexOptions.java rename to core/src/main/java/com/arangodb/model/SkiplistIndexOptions.java index 15f3dcdfe..bb1cc87d4 100644 --- a/src/main/java/com/arangodb/model/SkiplistIndexOptions.java +++ b/core/src/main/java/com/arangodb/model/SkiplistIndexOptions.java @@ -1,122 +1,121 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.IndexType; - -/** - * @author Mark Vollmary - * @see API Documentation - * @deprecated use {@link PersistentIndexOptions} instead. Since ArangoDB 3.7 a skiplist index is an alias for a - * persistent index. - */ -@Deprecated -public class SkiplistIndexOptions extends IndexOptions { - - private Iterable fields; - private final IndexType type = IndexType.skiplist; - private Boolean unique; - private Boolean sparse; - private Boolean deduplicate; - private Boolean estimates; - - public SkiplistIndexOptions() { - super(); - } - - @Override - protected SkiplistIndexOptions getThis() { - return this; - } - - protected Iterable getFields() { - return fields; - } - - /** - * @param fields A list of attribute paths - * @return options - */ - protected SkiplistIndexOptions fields(final Iterable fields) { - this.fields = fields; - return this; - } - - protected IndexType getType() { - return type; - } - - public Boolean getUnique() { - return unique; - } - - /** - * @param unique if true, then create a unique index - * @return options - */ - public SkiplistIndexOptions unique(final Boolean unique) { - this.unique = unique; - return this; - } - - public Boolean getSparse() { - return sparse; - } - - /** - * @param sparse if true, then create a sparse index - * @return options - */ - public SkiplistIndexOptions sparse(final Boolean sparse) { - this.sparse = sparse; - return this; - } - - public Boolean getDeduplicate() { - return deduplicate; - } - - /** - * @param deduplicate - * if false, the deduplication of array values is turned off. - * @return options - */ - public SkiplistIndexOptions deduplicate(final Boolean deduplicate) { - this.deduplicate = deduplicate; - return this; - } - - /** - * @param estimates - * This attribute controls whether index selectivity estimates are maintained for the index. Default: {@code - * true} - * @since ArangoDB 3.8 - */ - public SkiplistIndexOptions estimates(final Boolean estimates) { - this.estimates = estimates; - return this; - } - - public Boolean getEstimates() { - return estimates; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + +/** + * @author Mark Vollmary + * @see API Documentation + * @deprecated use {@link PersistentIndexOptions} instead. Since ArangoDB 3.7 a skiplist index is an alias for a + * persistent index. + */ +@Deprecated +public final class SkiplistIndexOptions extends IndexOptions { + + private final IndexType type = IndexType.skiplist; + private Iterable fields; + private Boolean unique; + private Boolean sparse; + private Boolean deduplicate; + private Boolean estimates; + + public SkiplistIndexOptions() { + super(); + } + + @Override + SkiplistIndexOptions getThis() { + return this; + } + + public Iterable getFields() { + return fields; + } + + /** + * @param fields A list of attribute paths + * @return options + */ + SkiplistIndexOptions fields(final Iterable fields) { + this.fields = fields; + return this; + } + + public IndexType getType() { + return type; + } + + public Boolean getUnique() { + return unique; + } + + /** + * @param unique if true, then create a unique index + * @return options + */ + public SkiplistIndexOptions unique(final Boolean unique) { + this.unique = unique; + return this; + } + + public Boolean getSparse() { + return sparse; + } + + /** + * @param sparse if true, then create a sparse index + * @return options + */ + public SkiplistIndexOptions sparse(final Boolean sparse) { + this.sparse = sparse; + return this; + } + + public Boolean getDeduplicate() { + return deduplicate; + } + + /** + * @param deduplicate if false, the deduplication of array values is turned off. + * @return options + */ + public SkiplistIndexOptions deduplicate(final Boolean deduplicate) { + this.deduplicate = deduplicate; + return this; + } + + /** + * @param estimates This attribute controls whether index selectivity estimates are maintained for the index. + * Default: {@code + * true} + * @since ArangoDB 3.8 + */ + public SkiplistIndexOptions estimates(final Boolean estimates) { + this.estimates = estimates; + return this; + } + + public Boolean getEstimates() { + return estimates; + } + +} diff --git a/src/main/java/com/arangodb/model/StreamTransactionOptions.java b/core/src/main/java/com/arangodb/model/StreamTransactionOptions.java similarity index 79% rename from src/main/java/com/arangodb/model/StreamTransactionOptions.java rename to core/src/main/java/com/arangodb/model/StreamTransactionOptions.java index 98f8b451d..a723f4034 100644 --- a/src/main/java/com/arangodb/model/StreamTransactionOptions.java +++ b/core/src/main/java/com/arangodb/model/StreamTransactionOptions.java @@ -20,25 +20,33 @@ package com.arangodb.model; +import com.fasterxml.jackson.annotation.JsonIgnore; + /** * @author Mark Vollmary * @author Michele Rastelli * @see API Documentation * @since ArangoDB 3.5.0 */ -public class StreamTransactionOptions { +public final class StreamTransactionOptions { private final TransactionCollectionOptions collections; private Integer lockTimeout; private Boolean waitForSync; private Long maxTransactionSize; private Boolean allowImplicit; + @JsonIgnore + private Boolean allowDirtyRead; public StreamTransactionOptions() { super(); collections = new TransactionCollectionOptions(); } + public TransactionCollectionOptions getCollections() { + return collections; + } + public Integer getLockTimeout() { return lockTimeout; } @@ -61,7 +69,8 @@ public Boolean getWaitForSync() { } /** - * @param waitForSync an optional boolean flag that, if set, will force the transaction to write all data to disk before + * @param waitForSync an optional boolean flag that, if set, will force the transaction to write all data to disk + * before * returning * @return options */ @@ -89,7 +98,8 @@ public StreamTransactionOptions writeCollections(final String... write) { } /** - * @param exclusive contains the array of collection-names to be used in the transaction (mandatory) for exclusive write + * @param exclusive contains the array of collection-names to be used in the transaction (mandatory) for + * exclusive write * @return options */ public StreamTransactionOptions exclusiveCollections(final String... exclusive) { @@ -123,4 +133,20 @@ public StreamTransactionOptions maxTransactionSize(final Long maxTransactionSize return this; } + public Boolean getAllowDirtyRead() { + return allowDirtyRead; + } + + /** + * @param allowDirtyRead Set to {@code true} allows reading from followers in an active-failover setup. + * @return options + * @see API + * Documentation + * @since ArangoDB 3.4.0 + */ + public StreamTransactionOptions allowDirtyRead(final Boolean allowDirtyRead) { + this.allowDirtyRead = allowDirtyRead; + return this; + } + } diff --git a/src/main/java/com/arangodb/model/TransactionCollectionOptions.java b/core/src/main/java/com/arangodb/model/TransactionCollectionOptions.java similarity index 97% rename from src/main/java/com/arangodb/model/TransactionCollectionOptions.java rename to core/src/main/java/com/arangodb/model/TransactionCollectionOptions.java index d11d14220..ce1d4e466 100644 --- a/src/main/java/com/arangodb/model/TransactionCollectionOptions.java +++ b/core/src/main/java/com/arangodb/model/TransactionCollectionOptions.java @@ -27,7 +27,7 @@ * @author Mark Vollmary * @author Michele Rastelli */ -public class TransactionCollectionOptions { +public final class TransactionCollectionOptions { private Collection read; private Collection write; diff --git a/src/main/java/com/arangodb/model/TransactionOptions.java b/core/src/main/java/com/arangodb/model/TransactionOptions.java similarity index 84% rename from src/main/java/com/arangodb/model/TransactionOptions.java rename to core/src/main/java/com/arangodb/model/TransactionOptions.java index e1226a1bd..28d314d18 100644 --- a/src/main/java/com/arangodb/model/TransactionOptions.java +++ b/core/src/main/java/com/arangodb/model/TransactionOptions.java @@ -20,17 +20,19 @@ package com.arangodb.model; +import com.arangodb.internal.serde.UserData; + /** * @author Mark Vollmary * @author Michele Rastelli * @see API * Documentation */ -public class TransactionOptions { +public final class TransactionOptions { + private final TransactionCollectionOptions collections; private String action; private Object params; - private final TransactionCollectionOptions collections; private Integer lockTimeout; private Boolean waitForSync; private Long maxTransactionSize; @@ -40,7 +42,11 @@ public TransactionOptions() { collections = new TransactionCollectionOptions(); } - protected String getAction() { + public TransactionCollectionOptions getCollections() { + return collections; + } + + public String getAction() { return action; } @@ -48,11 +54,12 @@ protected String getAction() { * @param action the actual transaction operations to be executed, in the form of stringified JavaScript code * @return options */ - protected TransactionOptions action(final String action) { + TransactionOptions action(final String action) { this.action = action; return this; } + @UserData public Object getParams() { return params; } @@ -88,7 +95,8 @@ public Boolean getWaitForSync() { } /** - * @param waitForSync an optional boolean flag that, if set, will force the transaction to write all data to disk before + * @param waitForSync an optional boolean flag that, if set, will force the transaction to write all data to disk + * before * returning * @return options */ @@ -116,7 +124,8 @@ public TransactionOptions writeCollections(final String... write) { } /** - * @param exclusive contains the array of collection-names to be used in the transaction (mandatory) for exclusive write + * @param exclusive contains the array of collection-names to be used in the transaction (mandatory) for + * exclusive write * @return options * @since ArangoDB 3.4.0 */ @@ -126,10 +135,14 @@ public TransactionOptions exclusiveCollections(final String... exclusive) { } /** - * @param allowImplicit Collections that will be written to in the transaction must be declared with the write attribute or it - * will fail, whereas non-declared collections from which is solely read will be added lazily. The - * optional attribute allowImplicit can be set to false to let transactions fail in case of undeclared - * collections for reading. Collections for reading should be fully declared if possible, to avoid + * @param allowImplicit Collections that will be written to in the transaction must be declared with the write + * attribute or it + * will fail, whereas non-declared collections from which is solely read will be added + * lazily. The + * optional attribute allowImplicit can be set to false to let transactions fail in case of + * undeclared + * collections for reading. Collections for reading should be fully declared if possible, to + * avoid * deadlocks. * @return options */ diff --git a/src/main/java/com/arangodb/model/TtlIndexOptions.java b/core/src/main/java/com/arangodb/model/TtlIndexOptions.java similarity index 78% rename from src/main/java/com/arangodb/model/TtlIndexOptions.java rename to core/src/main/java/com/arangodb/model/TtlIndexOptions.java index 59ee57e82..65aa5af58 100644 --- a/src/main/java/com/arangodb/model/TtlIndexOptions.java +++ b/core/src/main/java/com/arangodb/model/TtlIndexOptions.java @@ -1,74 +1,75 @@ -/* - * DISCLAIMER - * - * Copyright 2019 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.IndexType; - -/** - * @author Heiko Kernbach - * @see API Documentation - */ -public class TtlIndexOptions extends IndexOptions { - - private Iterable fields; - private final IndexType type = IndexType.ttl; - private Integer expireAfter; - - public TtlIndexOptions() { - super(); - } - - @Override - protected TtlIndexOptions getThis() { - return this; - } - - protected Iterable getFields() { - return fields; - } - - /** - * @param fields A list of attribute paths - * @return options - */ - protected TtlIndexOptions fields(final Iterable fields) { - this.fields = fields; - return this; - } - - protected IndexType getType() { - return type; - } - - /** - * @param expireAfter The time (in seconds) after a document’s creation after which the documents count as “expired”. - * @return options - */ - public TtlIndexOptions expireAfter(final Integer expireAfter) { - this.expireAfter = expireAfter; - return this; - } - - protected Integer getExpireAfter() { - return expireAfter; - } - -} +/* + * DISCLAIMER + * + * Copyright 2019 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + +/** + * @author Heiko Kernbach + * @see API Documentation + */ +public final class TtlIndexOptions extends IndexOptions { + + private final IndexType type = IndexType.ttl; + private Iterable fields; + private Integer expireAfter; + + public TtlIndexOptions() { + super(); + } + + @Override + TtlIndexOptions getThis() { + return this; + } + + public Iterable getFields() { + return fields; + } + + /** + * @param fields A list of attribute paths + * @return options + */ + TtlIndexOptions fields(final Iterable fields) { + this.fields = fields; + return this; + } + + public IndexType getType() { + return type; + } + + /** + * @param expireAfter The time (in seconds) after a document’s creation after which the documents count as + * “expired”. + * @return options + */ + public TtlIndexOptions expireAfter(final Integer expireAfter) { + this.expireAfter = expireAfter; + return this; + } + + public Integer getExpireAfter() { + return expireAfter; + } + +} diff --git a/src/main/java/com/arangodb/model/UserAccessOptions.java b/core/src/main/java/com/arangodb/model/UserAccessOptions.java similarity index 84% rename from src/main/java/com/arangodb/model/UserAccessOptions.java rename to core/src/main/java/com/arangodb/model/UserAccessOptions.java index 85f86bc66..9ac9ebfb3 100644 --- a/src/main/java/com/arangodb/model/UserAccessOptions.java +++ b/core/src/main/java/com/arangodb/model/UserAccessOptions.java @@ -1,45 +1,45 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.Permissions; - -/** - * @author Mark Vollmary - */ -public class UserAccessOptions { - - private Permissions grant; - - public UserAccessOptions() { - super(); - } - - protected Permissions getGrant() { - return grant; - } - - protected UserAccessOptions grant(final Permissions grant) { - this.grant = grant; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.Permissions; + +/** + * @author Mark Vollmary + */ +public final class UserAccessOptions { + + private Permissions grant; + + public UserAccessOptions() { + super(); + } + + public Permissions getGrant() { + return grant; + } + + UserAccessOptions grant(final Permissions grant) { + this.grant = grant; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/UserCreateOptions.java b/core/src/main/java/com/arangodb/model/UserCreateOptions.java similarity index 86% rename from src/main/java/com/arangodb/model/UserCreateOptions.java rename to core/src/main/java/com/arangodb/model/UserCreateOptions.java index 2ac216259..cc210b004 100644 --- a/src/main/java/com/arangodb/model/UserCreateOptions.java +++ b/core/src/main/java/com/arangodb/model/UserCreateOptions.java @@ -1,93 +1,93 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import java.util.Map; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class UserCreateOptions { - - private String user; - private String passwd; - private Boolean active; - private Map extra; - - public UserCreateOptions() { - super(); - } - - protected String getUser() { - return user; - } - - /** - * @param user The name of the user - * @return options - */ - protected UserCreateOptions user(final String user) { - this.user = user; - return this; - } - - protected String getPasswd() { - return passwd; - } - - /** - * @param passwd The user password - * @return options - */ - protected UserCreateOptions passwd(final String passwd) { - this.passwd = passwd; - return this; - } - - public Boolean getActive() { - return active; - } - - /** - * @param active An optional flag that specifies whether the user is active. If not specified, this will default to - * true - * @return options - */ - public UserCreateOptions active(final Boolean active) { - this.active = active; - return this; - } - - public Map getExtra() { - return extra; - } - - /** - * @param extra Optional data about the user - * @return options - */ - public UserCreateOptions extra(final Map extra) { - this.extra = extra; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import java.util.Map; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class UserCreateOptions { + + private String user; + private String passwd; + private Boolean active; + private Map extra; + + public UserCreateOptions() { + super(); + } + + public String getUser() { + return user; + } + + /** + * @param user The name of the user + * @return options + */ + UserCreateOptions user(final String user) { + this.user = user; + return this; + } + + public String getPasswd() { + return passwd; + } + + /** + * @param passwd The user password + * @return options + */ + UserCreateOptions passwd(final String passwd) { + this.passwd = passwd; + return this; + } + + public Boolean getActive() { + return active; + } + + /** + * @param active An optional flag that specifies whether the user is active. If not specified, this will default to + * true + * @return options + */ + public UserCreateOptions active(final Boolean active) { + this.active = active; + return this; + } + + public Map getExtra() { + return extra; + } + + /** + * @param extra Optional data about the user + * @return options + */ + public UserCreateOptions extra(final Map extra) { + this.extra = extra; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/UserUpdateOptions.java b/core/src/main/java/com/arangodb/model/UserUpdateOptions.java similarity index 94% rename from src/main/java/com/arangodb/model/UserUpdateOptions.java rename to core/src/main/java/com/arangodb/model/UserUpdateOptions.java index eec7fa2f4..4f9077791 100644 --- a/src/main/java/com/arangodb/model/UserUpdateOptions.java +++ b/core/src/main/java/com/arangodb/model/UserUpdateOptions.java @@ -1,79 +1,79 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import java.util.Map; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class UserUpdateOptions { - - private String passwd; - private Boolean active; - private Map extra; - - public UserUpdateOptions() { - super(); - } - - public String getPasswd() { - return passwd; - } - - /** - * @param passwd The user password - * @return options - */ - public UserUpdateOptions passwd(final String passwd) { - this.passwd = passwd; - return this; - } - - public Boolean getActive() { - return active; - } - - /** - * @param active An optional flag that specifies whether the user is active. If not specified, this will default to - * true - * @return options - */ - public UserUpdateOptions active(final Boolean active) { - this.active = active; - return this; - } - - public Map getExtra() { - return extra; - } - - /** - * @param extra Optional data about the user - * @return options - */ - public UserUpdateOptions extra(final Map extra) { - this.extra = extra; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import java.util.Map; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class UserUpdateOptions { + + private String passwd; + private Boolean active; + private Map extra; + + public UserUpdateOptions() { + super(); + } + + public String getPasswd() { + return passwd; + } + + /** + * @param passwd The user password + * @return options + */ + public UserUpdateOptions passwd(final String passwd) { + this.passwd = passwd; + return this; + } + + public Boolean getActive() { + return active; + } + + /** + * @param active An optional flag that specifies whether the user is active. If not specified, this will default to + * true + * @return options + */ + public UserUpdateOptions active(final Boolean active) { + this.active = active; + return this; + } + + public Map getExtra() { + return extra; + } + + /** + * @param extra Optional data about the user + * @return options + */ + public UserUpdateOptions extra(final Map extra) { + this.extra = extra; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java b/core/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java similarity index 81% rename from src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java rename to core/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java index b79b8ed41..d7ab02a70 100644 --- a/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java +++ b/core/src/main/java/com/arangodb/model/VertexCollectionCreateOptions.java @@ -1,72 +1,79 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import java.util.Arrays; -import java.util.Collection; - -/** - * @author Mark Vollmary - */ -public class VertexCollectionCreateOptions { - - private String collection; - private Options options; - - public VertexCollectionCreateOptions() { - super(); - } - - protected String getCollection() { - return collection; - } - - /** - * @param collection The name of the collection - * @return options - */ - protected VertexCollectionCreateOptions collection(final String collection) { - this.collection = collection; - return this; - } - - public Collection getSatellites() { - return options.satellites; - } - - /** - * @param satellites collection names that will be used to create SatelliteCollections - * for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only). Each array element - * must be a valid collection name. The collection type cannot be modified later. - * @return options - * @since ArangoDB 3.9.0 - */ - public VertexCollectionCreateOptions satellites(final String... satellites) { - options = new Options(); - options.satellites = Arrays.asList(satellites); - return this; - } - - public static class Options { - private Collection satellites; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import java.util.Arrays; +import java.util.Collection; + +/** + * @author Mark Vollmary + */ +public final class VertexCollectionCreateOptions { + + private final Options options = new Options(); + private String collection; + + public VertexCollectionCreateOptions() { + super(); + } + + public String getCollection() { + return collection; + } + + /** + * @param collection The name of the collection + * @return options + */ + VertexCollectionCreateOptions collection(final String collection) { + this.collection = collection; + return this; + } + + public Options getOptions() { + return options; + } + + public Collection getSatellites() { + return options.satellites; + } + + /** + * @param satellites collection names that will be used to create SatelliteCollections + * for a Hybrid (Disjoint) SmartGraph (Enterprise Edition only). Each array element + * must be a valid collection name. The collection type cannot be modified later. + * @return options + * @since ArangoDB 3.9.0 + */ + public VertexCollectionCreateOptions satellites(final String... satellites) { + options.satellites = Arrays.asList(satellites); + return this; + } + + public static final class Options { + private Collection satellites; + + public Collection getSatellites() { + return satellites; + } + } + +} diff --git a/src/main/java/com/arangodb/model/VertexCreateOptions.java b/core/src/main/java/com/arangodb/model/VertexCreateOptions.java similarity index 94% rename from src/main/java/com/arangodb/model/VertexCreateOptions.java rename to core/src/main/java/com/arangodb/model/VertexCreateOptions.java index d998aa590..62397a68d 100644 --- a/src/main/java/com/arangodb/model/VertexCreateOptions.java +++ b/core/src/main/java/com/arangodb/model/VertexCreateOptions.java @@ -1,63 +1,63 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class VertexCreateOptions { - - private Boolean waitForSync; - private String streamTransactionId; - - public VertexCreateOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until document has been synced to disk. - * @return options - */ - public VertexCreateOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public VertexCreateOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class VertexCreateOptions { + + private Boolean waitForSync; + private String streamTransactionId; + + public VertexCreateOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until document has been synced to disk. + * @return options + */ + public VertexCreateOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public VertexCreateOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/VertexDeleteOptions.java b/core/src/main/java/com/arangodb/model/VertexDeleteOptions.java similarity index 94% rename from src/main/java/com/arangodb/model/VertexDeleteOptions.java rename to core/src/main/java/com/arangodb/model/VertexDeleteOptions.java index d52f58347..98af70ace 100644 --- a/src/main/java/com/arangodb/model/VertexDeleteOptions.java +++ b/core/src/main/java/com/arangodb/model/VertexDeleteOptions.java @@ -1,77 +1,77 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class VertexDeleteOptions { - - private Boolean waitForSync; - private String ifMatch; - private String streamTransactionId; - - public VertexDeleteOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until deletion operation has been synced to disk. - * @return options - */ - public VertexDeleteOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch remove a document based on a target revision - * @return options - */ - public VertexDeleteOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public VertexDeleteOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class VertexDeleteOptions { + + private Boolean waitForSync; + private String ifMatch; + private String streamTransactionId; + + public VertexDeleteOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until deletion operation has been synced to disk. + * @return options + */ + public VertexDeleteOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch remove a document based on a target revision + * @return options + */ + public VertexDeleteOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public VertexDeleteOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/VertexReplaceOptions.java b/core/src/main/java/com/arangodb/model/VertexReplaceOptions.java similarity index 94% rename from src/main/java/com/arangodb/model/VertexReplaceOptions.java rename to core/src/main/java/com/arangodb/model/VertexReplaceOptions.java index 5957b7235..0efe64298 100644 --- a/src/main/java/com/arangodb/model/VertexReplaceOptions.java +++ b/core/src/main/java/com/arangodb/model/VertexReplaceOptions.java @@ -1,77 +1,77 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class VertexReplaceOptions { - - private Boolean waitForSync; - private String ifMatch; - private String streamTransactionId; - - public VertexReplaceOptions() { - super(); - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until document has been synced to disk. - * @return options - */ - public VertexReplaceOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch replace a document based on target revision - * @return options - */ - public VertexReplaceOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public VertexReplaceOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class VertexReplaceOptions { + + private Boolean waitForSync; + private String ifMatch; + private String streamTransactionId; + + public VertexReplaceOptions() { + super(); + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until document has been synced to disk. + * @return options + */ + public VertexReplaceOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch replace a document based on target revision + * @return options + */ + public VertexReplaceOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public VertexReplaceOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } + +} diff --git a/src/main/java/com/arangodb/model/VertexUpdateOptions.java b/core/src/main/java/com/arangodb/model/VertexUpdateOptions.java similarity index 95% rename from src/main/java/com/arangodb/model/VertexUpdateOptions.java rename to core/src/main/java/com/arangodb/model/VertexUpdateOptions.java index 1e0478692..62554a193 100644 --- a/src/main/java/com/arangodb/model/VertexUpdateOptions.java +++ b/core/src/main/java/com/arangodb/model/VertexUpdateOptions.java @@ -1,93 +1,93 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -public class VertexUpdateOptions { - - private Boolean keepNull; - private Boolean waitForSync; - private String ifMatch; - private String streamTransactionId; - - public VertexUpdateOptions() { - super(); - } - - public Boolean getKeepNull() { - return keepNull; - } - - /** - * @param keepNull If the intention is to delete existing attributes with the patch command, the URL query parameter - * keepNull can be used with a value of false. This will modify the behavior of the patch command to - * remove any attributes from the existing document that are contained in the patch document with an - * attribute value of null. - * @return options - */ - public VertexUpdateOptions keepNull(final Boolean keepNull) { - this.keepNull = keepNull; - return this; - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync Wait until document has been synced to disk. - * @return options - */ - public VertexUpdateOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - public String getIfMatch() { - return ifMatch; - } - - /** - * @param ifMatch replace a document based on target revision - * @return options - */ - public VertexUpdateOptions ifMatch(final String ifMatch) { - this.ifMatch = ifMatch; - return this; - } - - public String getStreamTransactionId() { - return streamTransactionId; - } - - /** - * @param streamTransactionId If set, the operation will be executed within the transaction. - * @return options - * @since ArangoDB 3.5.1 - */ - public VertexUpdateOptions streamTransactionId(final String streamTransactionId) { - this.streamTransactionId = streamTransactionId; - return this; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +/** + * @author Mark Vollmary + * @see API Documentation + */ +public final class VertexUpdateOptions { + + private Boolean keepNull; + private Boolean waitForSync; + private String ifMatch; + private String streamTransactionId; + + public VertexUpdateOptions() { + super(); + } + + public Boolean getKeepNull() { + return keepNull; + } + + /** + * @param keepNull If the intention is to delete existing attributes with the patch command, the URL query parameter + * keepNull can be used with a value of false. This will modify the behavior of the patch command to + * remove any attributes from the existing document that are contained in the patch document with an + * attribute value of null. + * @return options + */ + public VertexUpdateOptions keepNull(final Boolean keepNull) { + this.keepNull = keepNull; + return this; + } + + public Boolean getWaitForSync() { + return waitForSync; + } + + /** + * @param waitForSync Wait until document has been synced to disk. + * @return options + */ + public VertexUpdateOptions waitForSync(final Boolean waitForSync) { + this.waitForSync = waitForSync; + return this; + } + + public String getIfMatch() { + return ifMatch; + } + + /** + * @param ifMatch replace a document based on target revision + * @return options + */ + public VertexUpdateOptions ifMatch(final String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + public String getStreamTransactionId() { + return streamTransactionId; + } + + /** + * @param streamTransactionId If set, the operation will be executed within the transaction. + * @return options + * @since ArangoDB 3.5.1 + */ + public VertexUpdateOptions streamTransactionId(final String streamTransactionId) { + this.streamTransactionId = streamTransactionId; + return this; + } +} diff --git a/src/main/java/com/arangodb/model/ViewCreateOptions.java b/core/src/main/java/com/arangodb/model/ViewCreateOptions.java similarity index 79% rename from src/main/java/com/arangodb/model/ViewCreateOptions.java rename to core/src/main/java/com/arangodb/model/ViewCreateOptions.java index b2287a6de..e0a58273d 100644 --- a/src/main/java/com/arangodb/model/ViewCreateOptions.java +++ b/core/src/main/java/com/arangodb/model/ViewCreateOptions.java @@ -25,25 +25,31 @@ /** * @author Mark Vollmary */ -public class ViewCreateOptions { +public final class ViewCreateOptions { - @SuppressWarnings("unused") private String name; - @SuppressWarnings("unused") private ViewType type; public ViewCreateOptions() { super(); } - protected ViewCreateOptions name(final String name) { + ViewCreateOptions name(final String name) { this.name = name; return this; } - protected ViewCreateOptions type(final ViewType type) { + ViewCreateOptions type(final ViewType type) { this.type = type; return this; } + public String getName() { + return name; + } + + public ViewType getType() { + return type; + } + } diff --git a/src/main/java/com/arangodb/model/ViewRenameOptions.java b/core/src/main/java/com/arangodb/model/ViewRenameOptions.java similarity index 91% rename from src/main/java/com/arangodb/model/ViewRenameOptions.java rename to core/src/main/java/com/arangodb/model/ViewRenameOptions.java index d67c5bf54..2f0ed5faf 100644 --- a/src/main/java/com/arangodb/model/ViewRenameOptions.java +++ b/core/src/main/java/com/arangodb/model/ViewRenameOptions.java @@ -23,7 +23,7 @@ /** * @author Mark Vollmary */ -public class ViewRenameOptions { +public final class ViewRenameOptions { private String name; @@ -39,7 +39,7 @@ public String getName() { * @param name The new name * @return options */ - protected ViewRenameOptions name(final String name) { + ViewRenameOptions name(final String name) { this.name = name; return this; } diff --git a/src/main/java/com/arangodb/model/ZKDIndexOptions.java b/core/src/main/java/com/arangodb/model/ZKDIndexOptions.java similarity index 84% rename from src/main/java/com/arangodb/model/ZKDIndexOptions.java rename to core/src/main/java/com/arangodb/model/ZKDIndexOptions.java index 4e570a9ad..e4742e8ed 100644 --- a/src/main/java/com/arangodb/model/ZKDIndexOptions.java +++ b/core/src/main/java/com/arangodb/model/ZKDIndexOptions.java @@ -21,16 +21,17 @@ package com.arangodb.model; import com.arangodb.entity.IndexType; +import com.fasterxml.jackson.annotation.JsonProperty; /** * @author Michele Rastelli * @see API Documentation * @since ArangoDB 3.9 */ -public class ZKDIndexOptions extends IndexOptions { +public final class ZKDIndexOptions extends IndexOptions { + final IndexType type = IndexType.zkd; private Iterable fields; - protected final IndexType type = IndexType.zkd; private Boolean unique; private FieldValueTypes fieldValueTypes; @@ -39,11 +40,11 @@ public ZKDIndexOptions() { } @Override - protected ZKDIndexOptions getThis() { + ZKDIndexOptions getThis() { return this; } - protected Iterable getFields() { + public Iterable getFields() { return fields; } @@ -51,12 +52,12 @@ protected Iterable getFields() { * @param fields A list of attribute paths * @return options */ - protected ZKDIndexOptions fields(final Iterable fields) { + ZKDIndexOptions fields(final Iterable fields) { this.fields = fields; return this; } - protected IndexType getType() { + public IndexType getType() { return type; } @@ -87,6 +88,7 @@ public ZKDIndexOptions fieldValueTypes(final FieldValueTypes fieldValueTypes) { } public enum FieldValueTypes { + @JsonProperty("double") DOUBLE } diff --git a/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java b/core/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java similarity index 92% rename from src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java rename to core/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java index 62be6902c..f4115efec 100644 --- a/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java +++ b/core/src/main/java/com/arangodb/model/arangosearch/AnalyzerDeleteOptions.java @@ -23,13 +23,10 @@ /** * @author Michele Rastelli */ -public class AnalyzerDeleteOptions { +public final class AnalyzerDeleteOptions { private Boolean force; - public AnalyzerDeleteOptions() { - } - public Boolean getForce() { return force; } diff --git a/core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java b/core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java new file mode 100644 index 000000000..7b9ba4238 --- /dev/null +++ b/core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java @@ -0,0 +1,206 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model.arangosearch; + +import com.arangodb.entity.ViewType; +import com.arangodb.entity.arangosearch.*; +import com.arangodb.internal.serde.InternalSerializers; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.util.Arrays; +import java.util.Collection; + +/** + * @author Mark Vollmary + */ +public final class ArangoSearchCreateOptions { + + private final ViewType type; + private String name; + private Long consolidationIntervalMsec; + private Long commitIntervalMsec; + private Long cleanupIntervalStep; + private ConsolidationPolicy consolidationPolicy; + private Collection links; + private Collection primarySorts; + private ArangoSearchCompression primarySortCompression; + private Collection storedValues; + + public ArangoSearchCreateOptions() { + super(); + type = ViewType.ARANGO_SEARCH; + } + + ArangoSearchCreateOptions name(final String name) { + this.name = name; + return this; + } + + /** + * @param consolidationIntervalMsec Wait at least this many milliseconds between committing index data changes + * and making them visible to + * queries (default: 60000, to disable use: 0). For the case where there are a + * lot of inserts/updates, a + * lower value, until commit, will cause the index not to account for them and + * memory usage would + * continue to grow. For the case where there are a few inserts/updates, a + * higher value will impact + * performance and waste disk space for each commit call without any added + * benefits. + * @return options + */ + public ArangoSearchCreateOptions consolidationIntervalMsec(final Long consolidationIntervalMsec) { + this.consolidationIntervalMsec = consolidationIntervalMsec; + return this; + } + + /** + * @param commitIntervalMsec Wait at least this many milliseconds between committing view data store changes and + * making documents visible to + * queries (default: 1000, to disable use: 0). For the case where there are a lot of + * inserts/updates, a lower value, + * until commit, will cause the index not to account for them and memory usage would + * continue to grow. For the case + * where there are a few inserts/updates, a higher value will impact performance and + * waste disk space for each + * commit call without any added benefits. Background: For data retrieval ArangoSearch + * views follow the concept of + * “eventually-consistent”, i.e. eventually all the data in ArangoDB will be matched by + * corresponding query + * expressions. The concept of ArangoSearch view “commit” operation is introduced to + * control the upper-bound on the + * time until document addition/removals are actually reflected by corresponding query + * expressions. Once a “commit” + * operation is complete all documents added/removed prior to the start of the “commit” + * operation will be reflected + * by queries invoked in subsequent ArangoDB transactions, in-progress ArangoDB + * transactions will still continue to + * return a repeatable-read state. + * @return options + */ + public ArangoSearchCreateOptions commitIntervalMsec(final Long commitIntervalMsec) { + this.commitIntervalMsec = commitIntervalMsec; + return this; + } + + /** + * @param cleanupIntervalStep Wait at least this many commits between removing unused files in data directory + * (default: 10, to + * disable use: 0). For the case where the consolidation policies merge segments often + * (i.e. a lot of + * commit+consolidate), a lower value will cause a lot of disk space to be wasted. For + * the case where the + * consolidation policies rarely merge segments (i.e. few inserts/deletes), a higher + * value will impact + * performance without any added benefits. + * @return options + */ + public ArangoSearchCreateOptions cleanupIntervalStep(final Long cleanupIntervalStep) { + this.cleanupIntervalStep = cleanupIntervalStep; + return this; + } + + /** + * @param consolidationPolicy + * @return options + */ + public ArangoSearchCreateOptions consolidationPolicy(final ConsolidationPolicy consolidationPolicy) { + this.consolidationPolicy = consolidationPolicy; + return this; + } + + /** + * @param links A list of linked collections + * @return options + */ + public ArangoSearchCreateOptions link(final CollectionLink... links) { + this.links = Arrays.asList(links); + return this; + } + + /** + * @param primarySorts A list of linked collections + * @return options + */ + public ArangoSearchCreateOptions primarySort(final PrimarySort... primarySorts) { + this.primarySorts = Arrays.asList(primarySorts); + return this; + } + + /** + * @param primarySortCompression Defines how to compress the primary sort data + * @return options + */ + public ArangoSearchCreateOptions primarySortCompression(final ArangoSearchCompression primarySortCompression) { + this.primarySortCompression = primarySortCompression; + return this; + } + + /** + * @return options + */ + public ArangoSearchCreateOptions storedValues(final StoredValue... storedValues) { + this.storedValues = Arrays.asList(storedValues); + return this; + } + + public String getName() { + return name; + } + + public ViewType getType() { + return type; + } + + public Long getConsolidationIntervalMsec() { + return consolidationIntervalMsec; + } + + public Long getCommitIntervalMsec() { + return commitIntervalMsec; + } + + public Long getCleanupIntervalStep() { + return cleanupIntervalStep; + } + + public ConsolidationPolicy getConsolidationPolicy() { + return consolidationPolicy; + } + + @JsonSerialize(using = InternalSerializers.CollectionLinksSerializer.class) + public Collection getLinks() { + return links; + } + + public Collection getPrimarySorts() { + return primarySorts; + } + + public ArangoSearchCompression getPrimarySortCompression() { + return primarySortCompression; + } + + public Collection getStoredValues() { + return storedValues; + } + +} diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java b/core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java similarity index 100% rename from src/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java rename to core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchOptionsBuilder.java diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java b/core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java similarity index 53% rename from src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java rename to core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java index a874e6d30..912540c7f 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java +++ b/core/src/main/java/com/arangodb/model/arangosearch/ArangoSearchPropertiesOptions.java @@ -20,50 +20,58 @@ package com.arangodb.model.arangosearch; -import com.arangodb.entity.arangosearch.ArangoSearchProperties; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.ConsolidationPolicy; import com.arangodb.entity.arangosearch.PrimarySort; +import com.arangodb.internal.serde.InternalSerializers; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.util.Arrays; +import java.util.Collection; /** * @author Mark Vollmary */ -public class ArangoSearchPropertiesOptions { - - private final ArangoSearchProperties properties; +public final class ArangoSearchPropertiesOptions { - public ArangoSearchPropertiesOptions() { - super(); - properties = new ArangoSearchProperties(); - } - - public ArangoSearchProperties getProperties() { - return properties; - } + private Long consolidationIntervalMsec; + private Long cleanupIntervalStep; + private ConsolidationPolicy consolidationPolicy; + private Collection links; + private Collection primarySorts; /** - * @param consolidationIntervalMsec Wait at least this many milliseconds between committing index data changes and making them visible to - * queries (default: 60000, to disable use: 0). For the case where there are a lot of inserts/updates, a - * lower value, until commit, will cause the index not to account for them and memory usage would - * continue to grow. For the case where there are a few inserts/updates, a higher value will impact - * performance and waste disk space for each commit call without any added benefits. + * @param consolidationIntervalMsec Wait at least this many milliseconds between committing index data changes + * and making them visible to + * queries (default: 60000, to disable use: 0). For the case where there are a + * lot of inserts/updates, a + * lower value, until commit, will cause the index not to account for them and + * memory usage would + * continue to grow. For the case where there are a few inserts/updates, a + * higher value will impact + * performance and waste disk space for each commit call without any added + * benefits. * @return options */ public ArangoSearchPropertiesOptions consolidationIntervalMsec(final Long consolidationIntervalMsec) { - properties.setConsolidationIntervalMsec(consolidationIntervalMsec); + this.consolidationIntervalMsec = consolidationIntervalMsec; return this; } /** - * @param cleanupIntervalStep Wait at least this many commits between removing unused files in data directory (default: 10, to - * disable use: 0). For the case where the consolidation policies merge segments often (i.e. a lot of - * commit+consolidate), a lower value will cause a lot of disk space to be wasted. For the case where the - * consolidation policies rarely merge segments (i.e. few inserts/deletes), a higher value will impact + * @param cleanupIntervalStep Wait at least this many commits between removing unused files in data directory + * (default: 10, to + * disable use: 0). For the case where the consolidation policies merge segments often + * (i.e. a lot of + * commit+consolidate), a lower value will cause a lot of disk space to be wasted. For + * the case where the + * consolidation policies rarely merge segments (i.e. few inserts/deletes), a higher + * value will impact * performance without any added benefits. * @return options */ public ArangoSearchPropertiesOptions cleanupIntervalStep(final Long cleanupIntervalStep) { - properties.setCleanupIntervalStep(cleanupIntervalStep); + this.cleanupIntervalStep = cleanupIntervalStep; return this; } @@ -72,7 +80,7 @@ public ArangoSearchPropertiesOptions cleanupIntervalStep(final Long cleanupInter * @return options */ public ArangoSearchPropertiesOptions consolidationPolicy(final ConsolidationPolicy consolidationPolicy) { - properties.setConsolidationPolicy(consolidationPolicy); + this.consolidationPolicy = consolidationPolicy; return this; } @@ -81,7 +89,7 @@ public ArangoSearchPropertiesOptions consolidationPolicy(final ConsolidationPoli * @return options */ public ArangoSearchPropertiesOptions link(final CollectionLink... links) { - properties.addLink(links); + this.links = Arrays.asList(links); return this; } @@ -90,8 +98,28 @@ public ArangoSearchPropertiesOptions link(final CollectionLink... links) { * @return options */ public ArangoSearchPropertiesOptions primarySort(final PrimarySort... primarySorts) { - properties.addPrimarySort(primarySorts); + this.primarySorts = Arrays.asList(primarySorts); return this; } + public Long getConsolidationIntervalMsec() { + return consolidationIntervalMsec; + } + + public Long getCleanupIntervalStep() { + return cleanupIntervalStep; + } + + public ConsolidationPolicy getConsolidationPolicy() { + return consolidationPolicy; + } + + @JsonSerialize(using = InternalSerializers.CollectionLinksSerializer.class) + public Collection getLinks() { + return links; + } + + public Collection getPrimarySorts() { + return primarySorts; + } } diff --git a/core/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java b/core/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java new file mode 100644 index 000000000..6456fe6ee --- /dev/null +++ b/core/src/main/java/com/arangodb/model/arangosearch/SearchAliasCreateOptions.java @@ -0,0 +1,71 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model.arangosearch; + +import com.arangodb.entity.ViewType; +import com.arangodb.entity.arangosearch.*; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +/** + * @author Michele Rastelli + * @since ArangoDB 3.10 + */ +public final class SearchAliasCreateOptions { + + private String name; + private final ViewType type; + + private final Collection indexes = new ArrayList<>(); + + public SearchAliasCreateOptions() { + super(); + type = ViewType.SEARCH_ALIAS; + } + + SearchAliasCreateOptions name(final String name) { + this.name = name; + return this; + } + + /** + * @param indexes A list of inverted indexes to add to the View. + * @return options + */ + public SearchAliasCreateOptions indexes(final SearchAliasIndex... indexes) { + Collections.addAll(this.indexes, indexes); + return this; + } + + public String getName() { + return name; + } + + public ViewType getType() { + return type; + } + + public Collection getIndexes() { + return indexes; + } +} diff --git a/core/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java b/core/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java new file mode 100644 index 000000000..155e916be --- /dev/null +++ b/core/src/main/java/com/arangodb/model/arangosearch/SearchAliasOptionsBuilder.java @@ -0,0 +1,35 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model.arangosearch; + +/** + * @author Michele Rastelli + */ +public abstract class SearchAliasOptionsBuilder { + + private SearchAliasOptionsBuilder() { + super(); + } + + public static SearchAliasCreateOptions build(final SearchAliasCreateOptions options, final String name) { + return options.name(name); + } +} diff --git a/src/main/java/com/arangodb/internal/ArangoContext.java b/core/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java similarity index 52% rename from src/main/java/com/arangodb/internal/ArangoContext.java rename to core/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java index 67c80c238..7530b2cb3 100644 --- a/src/main/java/com/arangodb/internal/ArangoContext.java +++ b/core/src/main/java/com/arangodb/model/arangosearch/SearchAliasPropertiesOptions.java @@ -18,32 +18,32 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal; +package com.arangodb.model.arangosearch; -import java.util.HashMap; -import java.util.Map; +import com.arangodb.entity.arangosearch.*; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; /** - * @author Mark Vollmary + * @author Michele Rastelli + * @since ArangoDB 3.10 */ -public class ArangoContext { - - private final Map headerParam; - - public ArangoContext() { - super(); - headerParam = new HashMap<>(); - } +public final class SearchAliasPropertiesOptions { - public Map getHeaderParam() { - return headerParam; - } + private final Collection indexes = new ArrayList<>(); - public ArangoContext putHeaderParam(final String key, final Object value) { - if (value != null) { - headerParam.put(key, value.toString()); - } + /** + * @param indexes A list of inverted indexes to add to the View. + * @return options + */ + public SearchAliasPropertiesOptions indexes(SearchAliasIndex... indexes) { + Collections.addAll(this.indexes, indexes); return this; } + public Collection getIndexes() { + return indexes; + } } diff --git a/core/src/main/java/com/arangodb/serde/ArangoSerde.java b/core/src/main/java/com/arangodb/serde/ArangoSerde.java new file mode 100644 index 000000000..9e15ce097 --- /dev/null +++ b/core/src/main/java/com/arangodb/serde/ArangoSerde.java @@ -0,0 +1,35 @@ +package com.arangodb.serde; + +import com.arangodb.ContentType; + +/** + * Contract for serialization/deserialization of user data. + * Implementations of this interface could be used for customizing serialization/deserialization of user related data + * using serialization/deserialization libraries like: + * - serialization libraries for specific JVM languages (e.g. Scala, Kotlin, ...) + * - serialization libraries already in use in frameworks (e.g. JSON-B, Micronaut Serialization, ...) + * - high performance serialization libraries (e.g. supporting compile-time data binding code generation) + * - low-level libraries without support to data binding + */ +public interface ArangoSerde { + + /** + * Serializes the object into the target data type. For data type {@link ContentType#JSON}, the serialized JSON string + * must be encoded into a byte array using the UTF-8 charset. + * + * @param value object to serialize + * @return serialized byte array + */ + byte[] serialize(Object value); + + /** + * Deserializes the content and binds it to the target data type. + * For data type {@link ContentType#JSON}, the byte array is the JSON string encoded using the UTF-8 charset. + * + * @param content byte array to deserialize + * @param clazz class of target data type + * @return deserialized object + */ + T deserialize(byte[] content, Class clazz); + +} diff --git a/core/src/main/java/com/arangodb/serde/ArangoSerdeProvider.java b/core/src/main/java/com/arangodb/serde/ArangoSerdeProvider.java new file mode 100644 index 000000000..460e1f2fd --- /dev/null +++ b/core/src/main/java/com/arangodb/serde/ArangoSerdeProvider.java @@ -0,0 +1,15 @@ +package com.arangodb.serde; + +import com.arangodb.ContentType; + +public interface ArangoSerdeProvider { + + /** + * Returns a serde instance for the given content type + * + * @param contentType content type + * @return serde instance + */ + ArangoSerde of(final ContentType contentType); + +} diff --git a/core/src/main/java/com/arangodb/serde/InternalFrom.java b/core/src/main/java/com/arangodb/serde/InternalFrom.java new file mode 100644 index 000000000..1963a5fa9 --- /dev/null +++ b/core/src/main/java/com/arangodb/serde/InternalFrom.java @@ -0,0 +1,22 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + * Annotation for `_from` field used by the InternalSerde. It works with shaded driver and relocated Jackson. + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonProperty("_from") +@JsonInclude(JsonInclude.Include.NON_NULL) +public @interface InternalFrom { +} diff --git a/core/src/main/java/com/arangodb/serde/InternalId.java b/core/src/main/java/com/arangodb/serde/InternalId.java new file mode 100644 index 000000000..7ac590fbf --- /dev/null +++ b/core/src/main/java/com/arangodb/serde/InternalId.java @@ -0,0 +1,22 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + * Annotation for `_id` field used by the InternalSerde. It works with shaded driver and relocated Jackson. + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonProperty("_id") +@JsonInclude(JsonInclude.Include.NON_NULL) +public @interface InternalId { +} diff --git a/core/src/main/java/com/arangodb/serde/InternalKey.java b/core/src/main/java/com/arangodb/serde/InternalKey.java new file mode 100644 index 000000000..932ecc942 --- /dev/null +++ b/core/src/main/java/com/arangodb/serde/InternalKey.java @@ -0,0 +1,22 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + * Annotation for `_key` field used by the InternalSerde. It works with shaded driver and relocated Jackson. + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonProperty("_key") +@JsonInclude(JsonInclude.Include.NON_NULL) +public @interface InternalKey { +} diff --git a/core/src/main/java/com/arangodb/serde/InternalRev.java b/core/src/main/java/com/arangodb/serde/InternalRev.java new file mode 100644 index 000000000..c528d18e1 --- /dev/null +++ b/core/src/main/java/com/arangodb/serde/InternalRev.java @@ -0,0 +1,22 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + * Annotation for `_rev` field used by the InternalSerde. It works with shaded driver and relocated Jackson. + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonProperty("_rev") +@JsonInclude(JsonInclude.Include.NON_NULL) +public @interface InternalRev { +} diff --git a/core/src/main/java/com/arangodb/serde/InternalTo.java b/core/src/main/java/com/arangodb/serde/InternalTo.java new file mode 100644 index 000000000..7505a337b --- /dev/null +++ b/core/src/main/java/com/arangodb/serde/InternalTo.java @@ -0,0 +1,22 @@ +package com.arangodb.serde; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + * Annotation for `_to` field used by the InternalSerde. It works with shaded driver and relocated Jackson. + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonProperty("_to") +@JsonInclude(JsonInclude.Include.NON_NULL) +public @interface InternalTo { +} diff --git a/core/src/main/java/com/arangodb/util/RawBytes.java b/core/src/main/java/com/arangodb/util/RawBytes.java new file mode 100644 index 000000000..4fa2b21dd --- /dev/null +++ b/core/src/main/java/com/arangodb/util/RawBytes.java @@ -0,0 +1,49 @@ +package com.arangodb.util; + +import com.arangodb.internal.serde.InternalSerde; + +import java.util.Arrays; + +/** + * Helper class used to encapsulate raw value serialized as byte array. + * It can be used: + * - in serialization to append an already serialized raw value as is + * - in deserialization as target wrapper type for the raw value + *

    + * No validation is performed, the user is responsible for providing a valid byte array for the used content type. + *

    + * The raw value byte array can represent either: + * - a valid VPack + * - a valid JSON UTF-8 encoded string + *

    + * The driver's {@link InternalSerde} supports serializing and deserializing to and from + * {@code RawBytes}. + */ +public final class RawBytes implements RawData { + private final byte[] value; + + private RawBytes(final byte[] value) { + this.value = value; + } + + public static RawBytes of(final byte[] value) { + return new RawBytes(value); + } + + public byte[] getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RawBytes rawBytes = (RawBytes) o; + return Arrays.equals(getValue(), rawBytes.getValue()); + } + + @Override + public int hashCode() { + return Arrays.hashCode(getValue()); + } +} diff --git a/core/src/main/java/com/arangodb/util/RawData.java b/core/src/main/java/com/arangodb/util/RawData.java new file mode 100644 index 000000000..610ec7827 --- /dev/null +++ b/core/src/main/java/com/arangodb/util/RawData.java @@ -0,0 +1,17 @@ +package com.arangodb.util; + +/** + * Wrapper for raw data, current implementations are: + * - {@link RawBytes} + * - {@link RawJson} + */ +public interface RawData { + static RawJson of(final String value) { + return RawJson.of(value); + } + + static RawBytes of(final byte[] value) { + return RawBytes.of(value); + } + +} diff --git a/core/src/main/java/com/arangodb/util/RawJson.java b/core/src/main/java/com/arangodb/util/RawJson.java new file mode 100644 index 000000000..a221a0017 --- /dev/null +++ b/core/src/main/java/com/arangodb/util/RawJson.java @@ -0,0 +1,43 @@ +package com.arangodb.util; + +import com.arangodb.internal.serde.InternalSerde; + +import java.util.Objects; + +/** + * Helper class used to encapsulate raw JSON string. + * It can be used: + * - in serialization to append a raw JSON node + * - in deserialization as target wrapper type for the raw JSON string + *

    + * The driver's {@link InternalSerde} supports serializing and deserializing to and from + * {@code RawJson}. + */ +public final class RawJson implements RawData { + private final String value; + + private RawJson(final String value) { + this.value = value; + } + + public static RawJson of(final String value) { + return new RawJson(value); + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RawJson rawJson = (RawJson) o; + return Objects.equals(getValue(), rawJson.getValue()); + } + + @Override + public int hashCode() { + return Objects.hash(getValue()); + } +} diff --git a/src/main/java/com/arangodb/util/UnicodeUtils.java b/core/src/main/java/com/arangodb/util/UnicodeUtils.java similarity index 100% rename from src/main/java/com/arangodb/util/UnicodeUtils.java rename to core/src/main/java/com/arangodb/util/UnicodeUtils.java diff --git a/dev-README.md b/dev-README.md deleted file mode 100644 index fb6f0c109..000000000 --- a/dev-README.md +++ /dev/null @@ -1,18 +0,0 @@ -# dev-README - -## native image reflection configuration - -To generate reflection configuration run `helper.NativeImageHelper` and copy the generated json to `src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json`. - - -## test native - -```shell -mvn -Pnative test -``` - -## test ssl - -```shell -mvn test -Dtest=com.arangodb.ArangoSslTest -DSslTest=true -``` diff --git a/docker/foo.bin b/docker/foo.bin new file mode 100644 index 000000000..97c4296cd Binary files /dev/null and b/docker/foo.bin differ diff --git a/docker/start_db.sh b/docker/start_db.sh index a322aa97c..ee231d427 100755 --- a/docker/start_db.sh +++ b/docker/start_db.sh @@ -70,7 +70,7 @@ docker run -d \ --auth.jwt-secret=/jwtSecret \ --starter.address="${GW}" \ --docker.image="${DOCKER_IMAGE}" \ - --starter.local --starter.mode=${STARTER_MODE} --all.log.level=debug --all.log.output=+ --log.verbose + --starter.local --starter.mode=${STARTER_MODE} --all.log.level=debug --all.log.output=+ --log.verbose --all.server.descriptors-minimum=1024 wait_server() { @@ -101,6 +101,13 @@ for a in ${COORDINATORS[*]} ; do curl -u root:test --insecure --fail "$SCHEME://$a/_api/version" done +echo "" +echo "" +echo "Copying test ML models into containers..." +for c in $(docker ps -a -f name=adb-.* -q) ; do + docker cp "$LOCATION"/foo.bin "$c":/tmp +done + echo "" echo "" echo "Done, your deployment is reachable at: " diff --git a/docs/v7_detailed_changes.md b/docs/v7_detailed_changes.md new file mode 100644 index 000000000..ff893e95d --- /dev/null +++ b/docs/v7_detailed_changes.md @@ -0,0 +1,272 @@ +# Version 7.0: detailed changes + +## Maven Setup + +In your `pom.xml` include the dependency: + +``` + + + com.arangodb + arangodb-java-driver + 7.0.0-ALPHA.2 + + +``` + +## HTTP client + +The HTTP client has been changed to Vert.x WebClient. + +`HTTP/2` is now supported. `HTTP/2` supports multiplexing and uses `1` connection per host by default. + + +## Configuration changes + +The default communication protocol is now `HTTP2_JSON` (`HTTP/2` with `JSON` content type). + +The default host configuration to `127.0.0.1:8529` has been removed. + +Configuration properties are not read automatically from properties files anymore. +A new API for loading properties has been introduced: `ArangoDB.Builder.loadProperties(ArangoConfigProperties)`. +Implementations could supply configuration properties coming from different sources, eg. system properties, remote +stores, frameworks facilities, etc. +An implementation for loading properties from local files is provided by `ArangoConfigProperties.fromFile()` and its +overloaded variants. + +Here is an example to read config properties from `arangodb.properties` file (as in version `6`): + +```java +ArangoDB adb = new ArangoDB.Builder() + .loadProperties(ArangoConfigProperties.fromFile()) + // ... + .build(); +``` + +Here is an example to read config properties from `arangodb-with-prefix.properties` file, where the config properties +are prefixed with `adb`: + +```java +// arangodb-with-prefix.properties content: +// +// adb.hosts=172.28.0.1:8529 +// adb.acquireHostList=true +// ... + +ArangoDB adb = new ArangoDB.Builder() + .loadProperties(new FileConfigPropertiesProvider("arangodb-with-prefix.properties", "adb")) + .build(); +``` + +An example showing how to provide configuration using Eclipse MicroProfile Config can be found +[here](../driver/src/test/java/com/arangodb/config). + + +## Modules + +Support for different serializers and communication protocols is offered by separate modules. +Defaults modules are transitively included, but they could be excluded if not needed. + +The driver artifact `com.arangodb:arangodb-java-driver` has transitive dependencies on default modules: +- `com.arangodb:http-protocol`: `HTTP` communication protocol +- `com.arangodb:jackson-serde-json`: `JSON` user serde module based on Jackson Databind +Alternative modules are respectively: +- `com.arangodb:vst-protocol`: `VST` communication protocol +- `com.arangodb:jackson-serde-vpack`: `VPACK` user serde module based on Jackson Databind + +In case a non-default communication protocol or user serde are used, the related module(s) must be explicitly included +and the corresponding default module(s) can be excluded. + +For example, to use the driver with `VPACK` over `VST`, we must include: +- `com.arangodb:vst-protocol` and +- `com.arangodb:jackson-serde-vpack` +and could exclude: +- `com.arangodb:http-protocol` and +- `com.arangodb:jackson-serde-json` + +```xml + + + com.arangodb + arangodb-java-driver + + + com.arangodb + http-protocol + + + com.arangodb + jackson-serde-json + + + + + com.arangodb + vst-protocol + + + com.arangodb + jackson-serde-vpack + + +``` + + +## Transitive dependencies + +`com.arangodb:arangodb-java-driver` has transitive dependencies on `jackson-core`, `jackson-databind` +and `jackson-annotations`, using by default version `2.14`. + +The versions of such libraries can be overridden, the driver is compatible with Jackson 2 (at least `2.10` or greater). + +To do this, you might need to include [jackson-bom](https://github.com/FasterXML/jackson-bom) +to ensure dependency convergence across the entire project, for example in case +there are in your project other libraries depending on different versions of Jackson. + +```xml + + + + com.fasterxml.jackson + jackson-bom + ... + import + pom + + + +``` + +The module `http-protocol` has transitive dependency on `io.vertx:vertx-web-client:4.3.5`. + +If these dependency requirements cannot be satisfied, you might need to use the +[shaded version](#arangodb-java-driver-shaded) of this driver, which bundles together all modules with relocated +external dependencies. + +The dependency on `com.arangodb:velocypack` has been removed from core module and is now only used +by `com.arangodb:vst-protocol` and `com.arangodb:jackson-serde-vpack`. + + +## User Data Types + +Before version `7.0` the driver always parsed raw strings as JSON, but unfortunately this does not allow distinguishing +the case when the intent is to use the raw string as such, without parsing it. Since version `7.0`, strings are not +interpreted as JSON anymore. To represent user data as raw JSON, the wrapper class `RawJson` has been added: + +```java +RawJson rawJsonIn = RawJson.of(""" + {"foo":"bar"} + """); +ArangoCursor res = adb.db().query("RETURN @v", Map.of("v", rawJsonIn), RawJson.class); +RawJson rawJsonOut = res.next(); +String json = rawJsonOut.getValue(); // {"foo":"bar"} +``` + +To represent user data already encoded as byte array, the wrapper class `RawBytes` has been added. +The byte array can either represent a `JSON` string (UTF-8 encoded) or a `VPACK` value, but the format must be the +same used for the driver protocol configuration (`JSON` for `HTTP_JSON` and `HTTP2_JSON`, `VPACK` otherwise). + +The following changes have been applied to `BaseDocument` and `BaseEdgeDocument`: +- `final` classes +- not serializable anymore (Java serialization) +- new method `removeAttribute(String)` +- `getProperties()` returns an unmodifiable map + +Before version `7.0` when performing write operations, the metadata of the input data objects was updated in place with +the metadata received in the response. +Since version `7.0`, the input data objects passed as arguments to API methods are treated as immutable and the related +metadata fields are not updated anymore. The updated metadata can be found in the returned object. + + +## Serialization + +Up to version 6, the (de)serialization was always performed to/from `VPACK`. In case the JSON format was +required, the raw `VPACK` was then converted to `JSON`. Since version 7, the serialization module is a dataformat +agnostic API, by default using `JSON` format. + +Support of data type `VPackSlice` has been removed (in favor of Jackson types: `JsonNode`, `ArrayNode`, `ObjectNode`, +...), for example: + +```java +JsonNode jsonNodeIn = JsonNodeFactory.instance.objectNode() + .put("foo", "bar"); + +ArangoCursor res = adb.db().query("RETURN @v", Map.of("v", jsonNodeIn), JsonNode.class); +JsonNode jsonNodeOut = res.next(); +String foo = jsonNodeOut.get("foo").textValue(); // bar +``` + +The dependency on `com.arangodb:velocypack` has been removed. + +The user data custom serializer implementation `ArangoJack` has been removed in favor of `JacksonSerde`. + +Updated reference documentation can be found [here](v7_java-reference-serialization.md). + + +## ArangoDB Java Driver Shaded + +Since version `7`, a shaded variant of the driver is also published with maven coordinates: +`com.arangodb:arangodb-java-driver-shaded`. + +It bundles and relocates the following packages from transitive dependencies: +- `com.fasterxml.jackson` +- `com.arangodb.jackson.dataformat.velocypack` +- `io.vertx` +- `io.netty` + + +## Removed APIs + +The following client APIs have been removed: + +- client APIs already deprecated in Java Driver version `6` +- client API to interact with deprecated server APIs: + - `MMFiles` related APIs + - `ArangoDatabase.executeTraversal()` + - `ArangoDB.getLogs()` + - `minReplicationFactor` in collections and graphs + - `overwrite` flag in `DocumentCreateOptions` + +The user data custom serializer implementation `ArangoJack` has been removed in favor of `JacksonSerde`. + +Support for interpreting raw strings as JSON has been removed (in favor of `RawJson`). + +Support of data type `VPackSlice` has been removed (in favor of Jackson types: `JsonNode`, `ArrayNode`, `ObjectNode`, +...). + +Support for custom initialization of +cursors (`ArangoDB._setCursorInitializer(ArangoCursorInitializer cursorInitializer)`) has been removed. + + +## API methods changes + +Before version `7.0` some CRUD API methods inferred the return type from the type of the data object passed as input. +Now the return type can be explicitly set for each CRUD API method. + +CRUD operations operating with multiple documents have now an overloaded variant which accepts raw data (`RawBytes` +and `RawJson`) containing multiple documents. + +`ArangoCursor#getStats()` returns now an untyped map. + +`Request` and `Response` classes have been refactored to support generic body type. +`ArangoDB.execute(Request, Class): Response` accepts now the target deserialization type for the response body. + +`ArangoDBException` has been enhanced with the id of the request causing it. + + +## API entities + +All entities and options classes (in packages `com.arangodb.model` and `com.arangodb.entity`) are now `final`. + +The replication factor is now modeled with a new interface (`ReplicationFactor`) with +implementations: `NumericReplicationFactor` and `SatelliteReplicationFactor`. + + +## Migration + +To migrate your existing project to Java Driver version `7.0`, it is recommended updating to the latest version of +branch `6` and make sure that your code does not use any deprecated API. +This can be done by checking the presence of deprecation warnings in the Java compiler output. + +The deprecation notes in the related javadoc contain information about the reason of the deprecation and suggest +migration alternatives to use. diff --git a/docs/v7_java-reference-serialization.md b/docs/v7_java-reference-serialization.md new file mode 100644 index 000000000..c59329210 --- /dev/null +++ b/docs/v7_java-reference-serialization.md @@ -0,0 +1,200 @@ +# Serialization + +The driver functionalities related to serialization and deserialization (serde) are provided by 2 different components: +- internal serde +- user-data serde + +The **internal serde** is based on [Jackson](https://github.com/FasterXML/jackson) API and is responsible for serializing/deserializing data definition classes (in +packages `com.arangodb.model` and `com.arangodb.entity`). +This includes all the information that is not domain user data, such as configuration properties, definitions metadata +for databases, collections, graphs, ... + +Furthermore, it is used to serialize and deserialize user data of the following types: +- `JsonNode` and its children (`ArrayNode`, `ObjectNode`, ...) +- `RawJson` +- `RawBytes` +- `BaseDocument` +- `BaseEdgeDocument` + + +The **user-data serde** is used to serialize and deserialize the user data, namely the data payloads related to: +- documents +- vertexes +- edges +- AQL bind variables +- transactions parameters +- custom requests and responses (`Request` and `Response` payloads) + +User-data serde implementations must implement the `ArangoSerde` interface, which is an abstract API with no +dependencies on specific libraries. +Custom implementations can be registered via `ArangoDB.Builder#serde(ArangoSerde)`. +For example, you can find [here](../jsonb-serde/src/main/java/com/arangodb/serde/jsonb) an implementation of +`ArangoSerde` based on `JSON-B` (supporting `JSON` format only). + + +## JacksonSerde (default user-data serde) + +The default user-data serde is `JacksonSerde`, which is provided by the module `com.arangodb:jackson-serde-json`. +This is used by default from the driver, if no custom serde is registered explicitly. +It is implemented delegating [Jackson](https://github.com/FasterXML/jackson) `ObjectMapper`, therefore it is compatible +with Jackson Streaming, Data Binding and Tree Model API. +It supports both `JSON` and `VPACK` data formats. To use `VPACK`, the additional dependency on +`com.arangodb:jackson-serde-vpack` is required. + + +### Configure + +Create an instance of `JacksonSerde`, configure the underlying `ObjectMapper` and pass it to the driver: + +```java +JacksonSerde serde = new JacksonSerdeProvider().of(ContentType.JSON); +serde.configure((ObjectMapper mapper) -> { + // ... +}); + +ArangoDB adb = new ArangoDB.Builder() + .serde(serde) + // ... + .build(); +``` + +See also [Jackson Databind](https://github.com/FasterXML/jackson-databind/wiki/JacksonFeatures) configurable features. + + +### Mapping API + +The library is fully compatible with [Jackson Databind](https://github.com/FasterXML/jackson-databind) +API. To customize the serialization and deserialization behavior using the +Jackson Data Binding API, entities can be annotated with +[Jackson Annotations](https://github.com/FasterXML/jackson-annotations). +For more advanced customizations refer to [Custom serializer](#custom-serializer) section. + + +### Renaming Properties + +To use a different serialized name for a field, use the annotation `@JsonProperty`. + +```java +public class MyObject { + @JsonProperty("title") + private String name; +} +``` + +### Ignoring properties + +To ignore fields use the annotation `@JsonIgnore`. + +```java +public class Value { + @JsonIgnore + public int internalValue; +} +``` + +### Custom serializers + +The serialization and deserialization can be customized using the lower level +Streaming API or the Tree Model API, creating and registering respectively +`JsonSerializer` and `JsonDeserializer`, as specified by the Jackson API +for [CustomSerializers](https://github.com/FasterXML/jackson-docs/wiki/JacksonHowToCustomSerializers). + +```java +static class PersonSerializer extends JsonSerializer { + @Override + public void serialize(Person value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + // example using the Streaming API + gen.writeStartObject(); + gen.writeFieldName("name"); + gen.writeString(value.name); + gen.writeEndObject(); + } +} + +static class PersonDeserializer extends JsonDeserializer { + @Override + public Person deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException { + // example using the Tree Model API + Person person = new Person(); + JsonNode rootNode = parser.getCodec().readTree(parser); + JsonNode nameNode = rootNode.get("name"); + if (nameNode != null && nameNode.isTextual()) { + person.name = nameNode.asText(); + } + return person; + } +} + +// registering using annotation +@JsonSerialize(using = PersonSerializer.class) +public static class Person { + public String name; +} + +// registering programmatically +JacksonSerde serde = new JacksonSerdeProvider().of(ContentType.JSON); +serde.configure(mapper -> { + SimpleModule module = new SimpleModule("PersonModule"); + module.addDeserializer(Person.class, new PersonDeserializer()); + mapper.registerModule(module); +}); + +ArangoDB adb = new ArangoDB.Builder() + .serde(serde) + // ... + .build(); +``` + +### Jackson datatype and language modules + +By default, Jackson modules in the classpath are discovered via SPI and registered to the `JacksonSerde`. +For example, this will automatically +register [Jackson datatype modules](https://github.com/FasterXML/jackson#third-party-datatype-modules) +as well as [Jackson JVM Language modules](https://github.com/FasterXML/jackson#jvm-language-modules) +like Kotlin or Scala module (see sections below). + +To avoid automatic Jackson modules discovery and registration, an instance of `JacksonSerde` can be manually created +using `JacksonSerdeProvider.create(ObjectMapper)` and registered using `ArangoDBBuilder.serde(ArangoSerde)`, e.g.: + +```java +ArangoDB adb = new ArangoDB.Builder() + .serde(new JacksonSerdeProvider().create(new ObjectMapper())) + .build(); +``` + +### Kotlin + +[Kotlin language module](https://github.com/FasterXML/jackson-module-kotlin) +enables support for Kotlin classes and types. +It can be used including `com.fasterxml.jackson.module:jackson-module-kotlin`. + +### Scala + +[Scala language module](https://github.com/FasterXML/jackson-module-scala) +enables support for Scala classes and types. +It can be used including `com.fasterxml.jackson.module:jackson-module-scala_`. + +### Java 8 types + +Support for Java 8 features is offered by +[jackson-modules-java8](https://github.com/FasterXML/jackson-modules-java8). + +### Joda types + +Support for Joda data types, such as DateTime, is offered by +[jackson-datatype-joda](https://github.com/FasterXML/jackson-datatype-joda). + +### Metadata fields + +Metadata fields `_id`, `_key`, `_rev`, `_from`, `_to` can be mapped using respectively the annotations: +`@Id`, `@Key`, `@Rev`, `@From`, `@To`. + +```java +public class MyObject { + + @Key + private String key; + + // ... +} +``` diff --git a/driver/dev-README.md b/driver/dev-README.md new file mode 100644 index 000000000..b8405a6a0 --- /dev/null +++ b/driver/dev-README.md @@ -0,0 +1,38 @@ +# dev-README + +## GH Actions +Check results [here](https://github.com/arangodb/arangodb-java-driver/actions). + +## SonarCloud +Check results [here](https://sonarcloud.io/project/overview?id=arangodb_arangodb-java-driver). + +## check dependencies updates +```shell +mvn versions:display-dependency-updates +mvn versions:display-plugin-updates +``` + +## JaCoCo +```shell +mvn verify +``` +Report: +- [integration-tests](target/site/jacoco/index.html) + + +## native image reflection configuration + +To generate reflection configuration run `helper.NativeImageHelper` and copy the generated json to `src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json`. + + +## test native + +```shell +mvn -Pnative test +``` + +## test ssl + +```shell +mvn test -Dtest=com.arangodb.ArangoSslTest -DSslTest=true +``` diff --git a/driver/pom.xml b/driver/pom.xml new file mode 100644 index 000000000..3481759bd --- /dev/null +++ b/driver/pom.xml @@ -0,0 +1,168 @@ + + + 4.0.0 + + + arangodb-java-driver-parent + com.arangodb + 7.0.0-ALPHA.2 + + + arangodb-java-driver + arangodb-java-driver + ArangoDB Java Driver + + + false + false + src/test/**/* + com.arangodb.driver + + + + + no-graalvm + + 1.8 + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + graalvm/UnicodeUtilsTest.java + + + + + + + + static-code-analysis + + + + org.jacoco + jacoco-maven-plugin + 0.8.8 + + + + prepare-agent + + + + report + prepare-package + + report + + + + + + com.github.spotbugs + spotbugs-maven-plugin + 4.7.3.0 + + spotbugs/spotbugs-exclude.xml + + + + compile + + check + + + + + + com.github.spotbugs + spotbugs + 4.7.3 + + + + + + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.1.0 + + + enforce + + enforce + + + + + + 3.6 + + + + + + + + org.codehaus.mojo + flatten-maven-plugin + + + + + + + com.arangodb + core + + + com.arangodb + http-protocol + + + com.arangodb + jackson-serde-json + + + com.arangodb + jackson-serde-vpack + test + + + com.arangodb + vst-protocol + test + + + org.reflections + reflections + 0.10.2 + test + + + org.graalvm.sdk + graal-sdk + 22.3.0 + test + + + io.smallrye.config + smallrye-config-core + 2.13.1 + test + + + + diff --git a/driver/spotbugs/spotbugs-exclude.xml b/driver/spotbugs/spotbugs-exclude.xml new file mode 100644 index 000000000..3062bfbe9 --- /dev/null +++ b/driver/spotbugs/spotbugs-exclude.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties new file mode 100644 index 000000000..60c5b90d2 --- /dev/null +++ b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties @@ -0,0 +1,9 @@ +Args=\ +-H:ResourceConfigurationResources=${.}/resource-config.json \ +-H:ReflectionConfigurationResources=${.}/reflect-config.json \ +-H:SerializationConfigurationResources=${.}/serialization-config.json \ +--initialize-at-run-time=\ + io.netty.handler.ssl.BouncyCastleAlpnSslUtils,\ + io.netty.handler.codec.compression.ZstdOptions \ +-Dio.netty.noUnsafe=true \ +-Dio.netty.leakDetection.level=DISABLED diff --git a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json new file mode 100644 index 000000000..f4b9641c1 --- /dev/null +++ b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json @@ -0,0 +1,1502 @@ +[ + { + "name": "com.arangodb.internal.serde.InternalSerializers$FieldLinksSerializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalSerializers$CollectionLinksSerializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalSerializers$CollectionSchemaRuleSerializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalDeserializers$CollectionLinksDeserializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalDeserializers$CollectionSchemaRuleDeserializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalDeserializers$FieldLinksDeserializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ViewEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AbstractBaseDocument", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerRole", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor$SatelliteReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties$BreakMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerFeature", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBEngine$StorageEngineName", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasIndex$OperationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.StreamTransactionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryExecutionState", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryCachePropertiesEntity$CacheMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevelEntity$LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.StoreValuesType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LoadBalancingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort$Field$Direction", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.IndexType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ArangoSearchCompression", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.License", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzerCase", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties$ReturnType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StreamType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.KeyType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ViewType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties$GeoJSONAnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ShardingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ConsolidationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.Permissions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionRevisionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryOptimizerRule", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort$Field", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.ClassificationAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasIndex", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.MetaAware", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.IndexEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlParseEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.EdgeDefinition", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.MultiDocumentEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionVariable", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryCachePropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.GraphEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlFunctionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DatabaseEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.PrimarySort", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.EdgeNgram", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionNode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.TransactionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBEngine", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.UserEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ErrorEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.FieldLink", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlParseEntity$AstNode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoAnalyzerOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ShardEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryOptimizerRule$Flags", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionCollection", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NearestNeighborsAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.PipelineAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor$NumericReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.EdgeDefinition$Options", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBVersion", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.MinHashAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ConsolidationPolicy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.KeyOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionPlan", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevelEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CursorWarning", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CursorStats", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.StreamTransactionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogEntriesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.CollectionLink", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.StoredValue", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentImportEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryTrackingPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogEntriesEntity$Message", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexField", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionExpression", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.BaseEdgeDocument", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.BaseDocument", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.EdgeUpdateEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentCreateEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.VertexUpdateEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentDeleteEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.VertexEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentUpdateEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.EdgeEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.IdentityAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.PipelineAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NearestNeighborsAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.MinHashAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.ClassificationAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerRole", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor$SatelliteReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties$BreakMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerFeature", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBEngine$StorageEngineName", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasIndex$OperationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.StreamTransactionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryExecutionState", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryCachePropertiesEntity$CacheMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevelEntity$LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.StoreValuesType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LoadBalancingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort$Field$Direction", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.IndexType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ArangoSearchCompression", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.License", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzerCase", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties$ReturnType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StreamType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.KeyType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ViewType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties$GeoJSONAnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ShardingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ConsolidationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.Permissions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.IndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentImportOptions$OnDuplicate", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.OverwriteMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ImportType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.LogOptions$SortOrder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ComputedValue$ComputeOn", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionSchema$Level", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ZKDIndexOptions$FieldValueTypes", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentReadOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryOptions$Optimizer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DBCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlFunctionDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.AnalyzerDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.UserUpdateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.StreamTransactionOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentReplaceOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DatabaseUsersOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ViewRenameOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.SearchAliasPropertiesOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryExplainOptions$Options", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ViewCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexCollectionCreateOptions$Options", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.ArangoSearchOptionsBuilder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryParseOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.UserAccessOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ComputedValue", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.EdgeUpdateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexCollectionCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.ArangoSearchCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.EdgeCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.GraphCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionsReadOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.TransactionOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionTruncateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionSchema", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentImportOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryOptions$Options", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.EdgeReplaceOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexReplaceOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.GraphDocumentReadOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentUpdateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexUpdateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.OptionsBuilder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.TransactionCollectionOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.LogOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.UserCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionPropertiesOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DatabaseOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.GraphCreateOptions$SmartOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionCountOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.EdgeDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.SearchAliasOptionsBuilder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionRenameOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.SearchAliasCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentExistsOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlFunctionGetOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlFunctionCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryExplainOptions$Optimizer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryExplainOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.QueueTimeSample", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.SkiplistIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.GeoIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.TtlIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.FulltextIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.HashIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ZKDIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.InvertedIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.PersistentIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentImportOptions$OnDuplicate", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.OverwriteMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ImportType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.LogOptions$SortOrder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ComputedValue$ComputeOn", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionSchema$Level", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ZKDIndexOptions$FieldValueTypes", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.MetaAware", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.cursor.entity.InternalCursorEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.cursor.entity.InternalCursorEntity$Extras", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + } +] diff --git a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json new file mode 100644 index 000000000..3bb430bb1 --- /dev/null +++ b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/resource-config.json @@ -0,0 +1,10 @@ +{ + "resources": { + "includes": [ + { + "pattern": "META-INF/vertx/vertx-version.txt" + } + ] + }, + "bundles": [] +} diff --git a/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json new file mode 100644 index 000000000..7160b9bd4 --- /dev/null +++ b/driver/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/serialization-config.json @@ -0,0 +1,14 @@ +[ + { + "name": "com.arangodb.entity.ErrorEntity" + }, + { + "name": "com.arangodb.ArangoDBException" + }, + { + "name": "com.arangodb.ArangoDBMultipleException" + }, + { + "name": "com.arangodb.internal.net.ArangoDBRedirectException" + } +] diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/driver/src/test/java/com/arangodb/ArangoCollectionTest.java similarity index 69% rename from src/test/java/com/arangodb/ArangoCollectionTest.java rename to driver/src/test/java/com/arangodb/ArangoCollectionTest.java index f1467ce72..d32cf4992 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/driver/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -20,41 +20,29 @@ package com.arangodb; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.entity.CollectionEntity; -import com.arangodb.entity.CollectionPropertiesEntity; -import com.arangodb.entity.CollectionRevisionEntity; -import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.entity.DocumentDeleteEntity; -import com.arangodb.entity.DocumentEntity; -import com.arangodb.entity.DocumentImportEntity; -import com.arangodb.entity.DocumentUpdateEntity; -import com.arangodb.entity.IndexEntity; -import com.arangodb.entity.IndexType; -import com.arangodb.entity.MultiDocumentEntity; -import com.arangodb.entity.Permissions; -import com.arangodb.entity.ShardEntity; +import com.arangodb.entity.*; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; import com.arangodb.model.DocumentImportOptions.OnDuplicate; +import com.arangodb.serde.jackson.Id; +import com.arangodb.serde.jackson.JacksonSerde; +import com.arangodb.serde.jackson.Key; +import com.arangodb.serde.jackson.Rev; import com.arangodb.util.MapBuilder; -import com.arangodb.velocypack.VPackSlice; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawData; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -91,8 +79,7 @@ static void init() { @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocument(ArangoCollection collection) { - final DocumentCreateEntity doc = collection - .insertDocument(new BaseDocument(), null); + final DocumentCreateEntity doc = collection.insertDocument(new BaseDocument(), null); assertThat(doc).isNotNull(); assertThat(doc.getId()).isNotNull(); assertThat(doc.getKey()).isNotNull(); @@ -101,18 +88,15 @@ void insertDocument(ArangoCollection collection) { assertThat(doc.getId()).isEqualTo(COLLECTION_NAME + "/" + doc.getKey()); } - // FIXME: v7 @ParameterizedTest(name = "{index}") @MethodSource("cols") - @Disabled - @SuppressWarnings("unchecked") void insertDocumentWithArrayWithNullValues(ArangoCollection collection) { List arr = Arrays.asList("a", null); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("arr", arr); - final DocumentCreateEntity insertedDoc = collection - .insertDocument(doc, new DocumentCreateOptions().returnNew(true)); + final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, + new DocumentCreateOptions().returnNew(true)); assertThat(insertedDoc).isNotNull(); assertThat(insertedDoc.getId()).isNotNull(); assertThat(insertedDoc.getKey()).isNotNull(); @@ -122,16 +106,14 @@ void insertDocumentWithArrayWithNullValues(ArangoCollection collection) { assertThat((List) insertedDoc.getNew().getAttribute("arr")).containsAll(Arrays.asList("a", null)); } - // FIXME: v7 @ParameterizedTest(name = "{index}") @MethodSource("cols") - @Disabled void insertDocumentWithNullValues(ArangoCollection collection) { - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("null", null); - final DocumentCreateEntity insertedDoc = collection - .insertDocument(doc, new DocumentCreateOptions().returnNew(true)); + final DocumentCreateEntity insertedDoc = collection.insertDocument(doc, + new DocumentCreateOptions().returnNew(true)); assertThat(insertedDoc).isNotNull(); assertThat(insertedDoc.getId()).isNotNull(); assertThat(insertedDoc.getKey()).isNotNull(); @@ -143,18 +125,17 @@ void insertDocumentWithNullValues(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentUpdateRev(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); } @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentReturnNew(ArangoCollection collection) { final DocumentCreateOptions options = new DocumentCreateOptions().returnNew(true); - final DocumentCreateEntity doc = collection - .insertDocument(new BaseDocument(), options); + final DocumentCreateEntity doc = collection.insertDocument(new BaseDocument(), options); assertThat(doc).isNotNull(); assertThat(doc.getId()).isNotNull(); assertThat(doc.getKey()).isNotNull(); @@ -164,23 +145,37 @@ void insertDocumentReturnNew(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") - void insertDocumentOverwriteReturnOld(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 4)); - Long initialCount = collection.count().getCount(); - - final BaseDocument doc = new BaseDocument(); - doc.addAttribute("value", "a"); - final DocumentCreateEntity meta = collection.insertDocument(doc); + void insertDocumentWithTypeOverwriteModeReplace(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + assumeTrue(collection.getSerde().getUserSerde() instanceof JacksonSerde, "polymorphic deserialization support" + + " required"); + + String key = UUID.randomUUID().toString(); + Dog dog = new Dog(key, "Teddy"); + Cat cat = new Cat(key, "Luna"); + + final DocumentCreateOptions options = new DocumentCreateOptions() + .returnNew(true) + .returnOld(true) + .overwriteMode(OverwriteMode.replace); + collection.insertDocument(dog, options); + final DocumentCreateEntity doc = collection.insertDocument(cat, options, Animal.class); + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull().isEqualTo(key); + assertThat(doc.getRev()).isNotNull(); - doc.addAttribute("value", "b"); - final DocumentCreateEntity repsert = collection - .insertDocument(doc, new DocumentCreateOptions().overwrite(true).returnOld(true).returnNew(true)); + assertThat(doc.getOld()) + .isNotNull() + .isInstanceOf(Dog.class); + assertThat(doc.getOld().getKey()).isEqualTo(key); + assertThat(doc.getOld().getName()).isEqualTo("Teddy"); - assertThat(repsert).isNotNull(); - assertThat(repsert.getRev()).isNotEqualTo(meta.getRev()); - assertThat(repsert.getOld().getAttribute("value")).isEqualTo("a"); - assertThat(repsert.getNew().getAttribute("value")).isEqualTo("b"); - assertThat(collection.count().getCount()).isEqualTo(initialCount + 1L); + assertThat(doc.getNew()) + .isNotNull() + .isInstanceOf(Cat.class); + assertThat(doc.getNew().getKey()).isEqualTo(key); + assertThat(doc.getNew().getName()).isEqualTo("Luna"); } @ParameterizedTest(name = "{index}") @@ -191,12 +186,12 @@ void insertDocumentOverwriteModeIgnore(ArangoCollection collection) { String key = "key-" + UUID.randomUUID(); final BaseDocument doc = new BaseDocument(key); doc.addAttribute("foo", "a"); - final DocumentCreateEntity meta = collection.insertDocument(doc); + final DocumentCreateEntity meta = collection.insertDocument(doc); final BaseDocument doc2 = new BaseDocument(key); doc2.addAttribute("bar", "b"); - final DocumentCreateEntity insertIgnore = collection - .insertDocument(doc2, new DocumentCreateOptions().overwriteMode(OverwriteMode.ignore)); + final DocumentCreateEntity insertIgnore = collection.insertDocument(doc2, + new DocumentCreateOptions().overwriteMode(OverwriteMode.ignore)); assertThat(insertIgnore).isNotNull(); assertThat(insertIgnore.getRev()).isEqualTo(meta.getRev()); @@ -213,8 +208,8 @@ void insertDocumentOverwriteModeConflict(ArangoCollection collection) { collection.insertDocument(doc); final BaseDocument doc2 = new BaseDocument(key); - Throwable thrown = catchThrowable(() -> - collection.insertDocument(doc2, new DocumentCreateOptions().overwriteMode(OverwriteMode.conflict))); + Throwable thrown = catchThrowable(() -> collection.insertDocument(doc2, + new DocumentCreateOptions().overwriteMode(OverwriteMode.conflict))); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getResponseCode()).isEqualTo(409); @@ -229,12 +224,12 @@ void insertDocumentOverwriteModeReplace(ArangoCollection collection) { String key = "key-" + UUID.randomUUID(); final BaseDocument doc = new BaseDocument(key); doc.addAttribute("foo", "a"); - final DocumentCreateEntity meta = collection.insertDocument(doc); + final DocumentCreateEntity meta = collection.insertDocument(doc); final BaseDocument doc2 = new BaseDocument(key); doc2.addAttribute("bar", "b"); - final DocumentCreateEntity repsert = collection - .insertDocument(doc2, new DocumentCreateOptions().overwriteMode(OverwriteMode.replace).returnNew(true)); + final DocumentCreateEntity repsert = collection.insertDocument(doc2, +new DocumentCreateOptions().overwriteMode(OverwriteMode.replace).returnNew(true)); assertThat(repsert).isNotNull(); assertThat(repsert.getRev()).isNotEqualTo(meta.getRev()); @@ -247,13 +242,13 @@ void insertDocumentOverwriteModeReplace(ArangoCollection collection) { void insertDocumentOverwriteModeUpdate(ArangoCollection collection) { assumeTrue(isAtLeastVersion(3, 7)); - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("foo", "a"); - final DocumentCreateEntity meta = collection.insertDocument(doc); + final DocumentCreateEntity meta = collection.insertDocument(doc); doc.addAttribute("bar", "b"); - final DocumentCreateEntity updated = collection - .insertDocument(doc, new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); + final DocumentCreateEntity updated = collection.insertDocument(doc, + new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); assertThat(updated).isNotNull(); assertThat(updated.getRev()).isNotEqualTo(meta.getRev()); @@ -266,30 +261,62 @@ void insertDocumentOverwriteModeUpdate(ArangoCollection collection) { void insertDocumentOverwriteModeUpdateMergeObjectsFalse(ArangoCollection collection) { assumeTrue(isAtLeastVersion(3, 7)); - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); Map fieldA = Collections.singletonMap("a", "a"); doc.addAttribute("foo", fieldA); - final DocumentCreateEntity meta = collection.insertDocument(doc); + final DocumentCreateEntity meta = collection.insertDocument(doc); Map fieldB = Collections.singletonMap("b", "b"); doc.addAttribute("foo", fieldB); - final DocumentCreateEntity updated = collection - .insertDocument(doc, new DocumentCreateOptions() - .overwriteMode(OverwriteMode.update) - .mergeObjects(false) - .returnNew(true)); + final DocumentCreateEntity updated = collection.insertDocument(doc, + new DocumentCreateOptions().overwriteMode(OverwriteMode.update).mergeObjects(false).returnNew(true)); assertThat(updated).isNotNull(); assertThat(updated.getRev()).isNotEqualTo(meta.getRev()); assertThat(updated.getNew().getAttribute("foo")).isEqualTo(fieldB); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentOverwriteModeUpdateKeepNullTrue(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("foo", "bar"); + collection.insertDocument(doc); + + doc.updateAttribute("foo", null); + final BaseDocument updated = collection.insertDocument(doc, new DocumentCreateOptions() + .overwriteMode(OverwriteMode.update) + .keepNull(true) + .returnNew(true)).getNew(); + + assertThat(updated.getProperties()).containsEntry("foo", null); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentOverwriteModeUpdateKeepNullFalse(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 7)); + + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("foo", "bar"); + collection.insertDocument(doc); + + doc.updateAttribute("foo", null); + final BaseDocument updated = collection.insertDocument(doc, new DocumentCreateOptions() + .overwriteMode(OverwriteMode.update) + .keepNull(false) + .returnNew(true)).getNew(); + + assertThat(updated.getProperties()).doesNotContainKey("foo"); + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentWaitForSync(ArangoCollection collection) { final DocumentCreateOptions options = new DocumentCreateOptions().waitForSync(true); - final DocumentCreateEntity doc = collection - .insertDocument(new BaseDocument(), options); + final DocumentCreateEntity doc = collection.insertDocument(new BaseDocument(), options); assertThat(doc).isNotNull(); assertThat(doc.getId()).isNotNull(); assertThat(doc.getKey()).isNotNull(); @@ -301,20 +328,41 @@ void insertDocumentWaitForSync(ArangoCollection collection) { @MethodSource("cols") void insertDocumentAsJson(ArangoCollection collection) { String key = "doc-" + UUID.randomUUID(); - final DocumentCreateEntity doc = collection - .insertDocument("{\"_key\":\"" + key + "\",\"a\":\"test\"}", null); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\",\"a\":\"test\"}"); + final DocumentCreateEntity doc = collection.insertDocument(rawJson); assertThat(doc).isNotNull(); assertThat(doc.getId()).isEqualTo(collection.name() + "/" + key); assertThat(doc.getKey()).isEqualTo(key); assertThat(doc.getRev()).isNotNull(); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentAsBytes(ArangoCollection collection) { + String key = "doc-" + UUID.randomUUID(); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("a", "test"); + byte[] bytes = collection.getSerde().serializeUserData(doc); + RawBytes rawJson = RawBytes.of(bytes); + final DocumentCreateEntity createEntity = collection.insertDocument(rawJson, +new DocumentCreateOptions().returnNew(true)); + assertThat(createEntity).isNotNull(); + assertThat(createEntity.getId()).isEqualTo(collection.name() + "/" + key); + assertThat(createEntity.getKey()).isEqualTo(key); + assertThat(createEntity.getRev()).isNotNull(); + assertThat(createEntity.getNew()).isNotNull().isInstanceOf(RawBytes.class); + Map newDoc = collection.getSerde().deserializeUserData(createEntity.getNew().getValue(), + Map.class); + assertThat(newDoc).containsAllEntriesOf(doc); + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity meta = collection - .insertDocument(new BaseDocument(), new DocumentCreateOptions().silent(true)); + final DocumentCreateEntity meta = collection.insertDocument(new BaseDocument(), + new DocumentCreateOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); assertThat(meta.getKey()).isNull(); @@ -325,11 +373,11 @@ void insertDocumentSilent(ArangoCollection collection) { @MethodSource("cols") void insertDocumentSilentDontTouchInstance(ArangoCollection collection) { assumeTrue(isSingleServer()); - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final String key = "testkey-" + UUID.randomUUID(); doc.setKey(key); - final DocumentCreateEntity meta = collection - .insertDocument(doc, new DocumentCreateOptions().silent(true)); + final DocumentCreateEntity meta = collection.insertDocument(doc, + new DocumentCreateOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getKey()).isNull(); assertThat(doc.getKey()).isEqualTo(key); @@ -339,9 +387,9 @@ void insertDocumentSilentDontTouchInstance(ArangoCollection collection) { @MethodSource("cols") void insertDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final MultiDocumentEntity> info = collection - .insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument()), - new DocumentCreateOptions().silent(true)); + final MultiDocumentEntity> info = + collection.insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument()), +new DocumentCreateOptions().silent(true)); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); assertThat(info.getDocumentsAndErrors()).isEmpty(); @@ -351,11 +399,9 @@ void insertDocumentsSilent(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocument(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument(), null); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); assertThat(createResult.getKey()).isNotNull(); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); } @@ -363,12 +409,10 @@ void getDocument(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentIfMatch(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument(), null); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); assertThat(createResult.getKey()).isNotNull(); final DocumentReadOptions options = new DocumentReadOptions().ifMatch(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, options); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, options); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); } @@ -376,24 +420,20 @@ void getDocumentIfMatch(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentIfMatchFail(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument(), null); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); assertThat(createResult.getKey()).isNotNull(); final DocumentReadOptions options = new DocumentReadOptions().ifMatch("no"); - final BaseDocument document = collection - .getDocument(createResult.getKey(), BaseDocument.class, options); + final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, options); assertThat(document).isNull(); } @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentIfNoneMatch(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument(), null); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); assertThat(createResult.getKey()).isNotNull(); final DocumentReadOptions options = new DocumentReadOptions().ifNoneMatch("no"); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, options); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, options); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getId()).isEqualTo(COLLECTION_NAME + "/" + createResult.getKey()); } @@ -401,12 +441,10 @@ void getDocumentIfNoneMatch(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentIfNoneMatchFail(ArangoCollection collection) { - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument(), null); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument(), null); assertThat(createResult.getKey()).isNotNull(); final DocumentReadOptions options = new DocumentReadOptions().ifNoneMatch(createResult.getRev()); - final BaseDocument document = collection - .getDocument(createResult.getKey(), BaseDocument.class, options); + final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, options); assertThat(document).isNull(); } @@ -414,11 +452,10 @@ void getDocumentIfNoneMatchFail(ArangoCollection collection) { @MethodSource("cols") void getDocumentAsJson(ArangoCollection collection) { String key = rnd(); - collection.insertDocument("{\"_key\":\"" + key + "\",\"a\":\"test\"}", null); - final String readResult = collection.getDocument(key, String.class, null); - assertThat(readResult) - .contains("\"_key\":\"" + key + "\"") - .contains("\"_id\":\"" + COLLECTION_NAME + "/" + key + "\""); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\",\"a\":\"test\"}"); + collection.insertDocument(rawJson); + final RawJson readResult = collection.getDocument(key, RawJson.class); + assertThat(readResult.getValue()).contains("\"_key\":\"" + key + "\"").contains("\"_id\":\"" + COLLECTION_NAME + "/" + key + "\""); } @ParameterizedTest(name = "{index}") @@ -431,8 +468,7 @@ void getDocumentNotFound(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentNotFoundOptionsDefault(ArangoCollection collection) { - final BaseDocument document = collection - .getDocument("no", BaseDocument.class, new DocumentReadOptions()); + final BaseDocument document = collection.getDocument("no", BaseDocument.class, new DocumentReadOptions()); assertThat(document).isNull(); } @@ -443,14 +479,6 @@ void getDocumentNotFoundOptionsNull(ArangoCollection collection) { assertThat(document).isNull(); } - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void getDocumentNotFoundThrowException(ArangoCollection collection) { - Throwable thrown = catchThrowable(() -> - collection.getDocument("no", BaseDocument.class, new DocumentReadOptions().catchException(false))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentWrongKey(ArangoCollection collection) { @@ -461,11 +489,11 @@ void getDocumentWrongKey(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentDirtyRead(ArangoCollection collection) throws InterruptedException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); collection.insertDocument(doc, new DocumentCreateOptions()); Thread.sleep(2000); - final VPackSlice document = collection - .getDocument(doc.getKey(), VPackSlice.class, new DocumentReadOptions().allowDirtyRead(true)); + final RawJson document = collection.getDocument(doc.getKey(), RawJson.class, + new DocumentReadOptions().allowDirtyRead(true)); assertThat(document).isNotNull(); } @@ -477,12 +505,13 @@ void getDocuments(ArangoCollection collection) { values.add(new BaseDocument("2")); values.add(new BaseDocument("3")); collection.insertDocuments(values); - final MultiDocumentEntity documents = collection - .getDocuments(Arrays.asList("1", "2", "3"), BaseDocument.class); + final MultiDocumentEntity documents = collection.getDocuments(Arrays.asList("1", "2", "3"), +BaseDocument.class); assertThat(documents).isNotNull(); assertThat(documents.getDocuments()).hasSize(3); for (final BaseDocument document : documents.getDocuments()) { - assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", COLLECTION_NAME + "/" + "3"); + assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", + COLLECTION_NAME + "/" + "3"); } } @@ -490,24 +519,20 @@ void getDocuments(ArangoCollection collection) { @MethodSource("cols") void getDocumentsWithCustomShardingKey(ArangoCollection c) { ArangoCollection collection = c.db().collection("customShardingKeyCollection"); - if (collection.exists()) - collection.drop(); + if (collection.exists()) collection.drop(); - collection.create(new CollectionCreateOptions() - .shardKeys("customField") - .numberOfShards(10) - ); + collection.create(new CollectionCreateOptions().shardKeys("customField").numberOfShards(10)); - List values = IntStream.range(0, 10) - .mapToObj(String::valueOf).map(key -> new BaseDocument()) - .peek(it -> it.addAttribute("customField", rnd())) - .collect(Collectors.toList()); + List values = + IntStream.range(0, 10).mapToObj(String::valueOf).map(key -> new BaseDocument()).peek(it -> it.addAttribute( + "customField", rnd())).collect(Collectors.toList()); - MultiDocumentEntity> inserted = collection.insertDocuments(values); - List insertedKeys = inserted.getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); + MultiDocumentEntity> inserted = collection.insertDocuments(values); + List insertedKeys = + inserted.getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); - final Collection documents = collection - .getDocuments(insertedKeys, BaseDocument.class).getDocuments(); + final Collection documents = +collection.getDocuments(insertedKeys, BaseDocument.class).getDocuments(); assertThat(documents).hasSize(10); } @@ -520,21 +545,24 @@ void getDocumentsDirtyRead(ArangoCollection collection) { values.add(new BaseDocument("2")); values.add(new BaseDocument("3")); collection.insertDocuments(values); - final MultiDocumentEntity documents = collection - .getDocuments(Arrays.asList("1", "2", "3"), BaseDocument.class, - new DocumentReadOptions().allowDirtyRead(true)); + final MultiDocumentEntity documents = collection.getDocuments(Arrays.asList("1", "2", "3"), + BaseDocument.class, new DocumentReadOptions().allowDirtyRead(true)); assertThat(documents).isNotNull(); + if (isAtLeastVersion(3, 10)) { + assertThat(documents.isPotentialDirtyRead()).isTrue(); + } assertThat(documents.getDocuments()).hasSize(3); for (final BaseDocument document : documents.getDocuments()) { - assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", COLLECTION_NAME + "/" + "3"); + assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", + COLLECTION_NAME + "/" + "3"); } } @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentsNotFound(ArangoCollection collection) { - final MultiDocumentEntity readResult = collection - .getDocuments(Collections.singleton("no"), BaseDocument.class); + final MultiDocumentEntity readResult = collection.getDocuments(Collections.singleton("no"), + BaseDocument.class); assertThat(readResult).isNotNull(); assertThat(readResult.getDocuments()).isEmpty(); assertThat(readResult.getErrors()).hasSize(1); @@ -543,8 +571,8 @@ void getDocumentsNotFound(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocumentsWrongKey(ArangoCollection collection) { - final MultiDocumentEntity readResult = collection - .getDocuments(Collections.singleton("no/no"), BaseDocument.class); + final MultiDocumentEntity readResult = collection.getDocuments(Collections.singleton("no/no"), + BaseDocument.class); assertThat(readResult).isNotNull(); assertThat(readResult.getDocuments()).isEmpty(); assertThat(readResult.getErrors()).hasSize(1); @@ -553,16 +581,15 @@ void getDocumentsWrongKey(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocument(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); doc.addAttribute("b", "test"); doc.updateAttribute("c", null); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, null); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, +null); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getNew()).isNull(); @@ -570,8 +597,7 @@ void updateDocument(ArangoCollection collection) { assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getAttribute("a")).isNotNull(); assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); @@ -589,8 +615,8 @@ void updateDocumentWithDifferentReturnType(ArangoCollection collection) { doc.addAttribute("a", "test"); collection.insertDocument(doc); - final DocumentUpdateEntity updateResult = collection - .updateDocument(key, Collections.singletonMap("b", "test"), new DocumentUpdateOptions().returnNew(true), BaseDocument.class); + final DocumentUpdateEntity updateResult = collection.updateDocument(key, +Collections.singletonMap("b", "test"), new DocumentUpdateOptions().returnNew(true), BaseDocument.class); assertThat(updateResult).isNotNull(); assertThat(updateResult.getKey()).isEqualTo(key); BaseDocument updated = updateResult.getNew(); @@ -602,36 +628,37 @@ void updateDocumentWithDifferentReturnType(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentUpdateRev(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, null); - assertThat(doc.getRevision()).isEqualTo(updateResult.getRev()); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.addAttribute("foo", "bar"); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + null); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(updateResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); } @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentIfMatch(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); doc.addAttribute("b", "test"); doc.updateAttribute("c", null); final DocumentUpdateOptions options = new DocumentUpdateOptions().ifMatch(createResult.getRev()); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getAttribute("a")).isNotNull(); assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); @@ -644,11 +671,10 @@ void updateDocumentIfMatch(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentIfMatchFail(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); doc.addAttribute("b", "test"); doc.updateAttribute("c", null); @@ -661,15 +687,14 @@ void updateDocumentIfMatchFail(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentReturnNew(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); doc.addAttribute("b", "test"); final DocumentUpdateOptions options = new DocumentUpdateOptions().returnNew(true); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); @@ -685,15 +710,14 @@ void updateDocumentReturnNew(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentReturnOld(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); doc.addAttribute("b", "test"); final DocumentUpdateOptions options = new DocumentUpdateOptions().returnOld(true); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); @@ -708,21 +732,19 @@ void updateDocumentReturnOld(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentKeepNullTrue(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", null); final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(true); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getProperties()).containsKey("a"); } @@ -730,48 +752,39 @@ void updateDocumentKeepNullTrue(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentKeepNullFalse(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", null); final DocumentUpdateOptions options = new DocumentUpdateOptions().keepNull(false); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getId()).isEqualTo(createResult.getId()); assertThat(readResult.getRevision()).isNotNull(); assertThat(readResult.getProperties().keySet()).doesNotContain("a"); } - static class TestUpdateEntity { - @SuppressWarnings("unused") - private String a, b; - } - @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentSerializeNullTrue(ArangoCollection collection) { final TestUpdateEntity doc = new TestUpdateEntity(); doc.a = "foo"; doc.b = "foo"; - final DocumentCreateEntity createResult = collection.insertDocument(doc); + final DocumentCreateEntity createResult = collection.insertDocument(doc); final TestUpdateEntity patchDoc = new TestUpdateEntity(); patchDoc.a = "bar"; - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), patchDoc); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), patchDoc); assertThat(updateResult).isNotNull(); assertThat(updateResult.getKey()).isEqualTo(createResult.getKey()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getProperties()).containsKey("a"); assertThat(readResult.getAttribute("a")).isEqualTo("bar"); @@ -780,48 +793,43 @@ void updateDocumentSerializeNullTrue(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentSerializeNullFalse(ArangoCollection collection) { - final TestUpdateEntity doc = new TestUpdateEntity(); + final TestUpdateEntitySerializeNullFalse doc = new TestUpdateEntitySerializeNullFalse(); doc.a = "foo"; doc.b = "foo"; - final DocumentCreateEntity createResult = collection.insertDocument(doc); - final TestUpdateEntity patchDoc = new TestUpdateEntity(); + final DocumentCreateEntity createResult = collection.insertDocument(doc); + final TestUpdateEntitySerializeNullFalse patchDoc = new TestUpdateEntitySerializeNullFalse(); patchDoc.a = "bar"; - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), patchDoc, new DocumentUpdateOptions().serializeNull(false)); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), patchDoc); assertThat(updateResult).isNotNull(); assertThat(updateResult.getKey()).isEqualTo(createResult.getKey()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getProperties()).containsKeys("a", "b"); assertThat(readResult.getAttribute("a")).isEqualTo("bar"); assertThat(readResult.getAttribute("b")).isEqualTo("foo"); } - @SuppressWarnings("unchecked") @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentMergeObjectsTrue(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final Map a = new HashMap<>(); a.put("a", "test"); doc.addAttribute("a", a); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); a.clear(); a.put("b", "test"); doc.updateAttribute("a", a); final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(true); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, +options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); final Object aResult = readResult.getAttribute("a"); assertThat(aResult).isInstanceOf(Map.class); @@ -829,29 +837,26 @@ void updateDocumentMergeObjectsTrue(ArangoCollection collection) { assertThat(aMap).containsKeys("a", "b"); } - @SuppressWarnings("unchecked") @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentMergeObjectsFalse(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final Map a = new HashMap<>(); a.put("a", "test"); doc.addAttribute("a", a); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); a.clear(); a.put("b", "test"); doc.updateAttribute("a", a); final DocumentUpdateOptions options = new DocumentUpdateOptions().mergeObjects(false); - final DocumentUpdateEntity updateResult = collection - .updateDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), doc, + options); assertThat(updateResult).isNotNull(); assertThat(updateResult.getId()).isEqualTo(createResult.getId()); assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); final Object aResult = readResult.getAttribute("a"); assertThat(aResult).isInstanceOf(Map.class); @@ -863,10 +868,9 @@ void updateDocumentMergeObjectsFalse(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentIgnoreRevsFalse(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("a", "test1"); doc.setRevision("no"); @@ -879,10 +883,9 @@ void updateDocumentIgnoreRevsFalse(ArangoCollection collection) { @MethodSource("cols") void updateDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument()); - final DocumentUpdateEntity meta = collection - .updateDocument(createResult.getKey(), new BaseDocument(), new DocumentUpdateOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentUpdateEntity meta = collection.updateDocument(createResult.getKey(), + new BaseDocument(), new DocumentUpdateOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); assertThat(meta.getKey()).isNull(); @@ -893,11 +896,10 @@ void updateDocumentSilent(ArangoCollection collection) { @MethodSource("cols") void updateDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument()); - final MultiDocumentEntity> info = collection - .updateDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), - new DocumentUpdateOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final MultiDocumentEntity> info = +collection.updateDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), + new DocumentUpdateOptions().silent(true)); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); assertThat(info.getDocumentsAndErrors()).isEmpty(); @@ -923,15 +925,14 @@ void updateNonExistingDocument(ArangoCollection collection) { void updateDocumentPreconditionFailed(ArangoCollection collection) { final BaseDocument doc = new BaseDocument("test-" + rnd()); doc.addAttribute("foo", "a"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); doc.updateAttribute("foo", "b"); collection.updateDocument(doc.getKey(), doc, null); doc.updateAttribute("foo", "c"); - Throwable thrown = catchThrowable(() -> - collection.updateDocument(doc.getKey(), doc, new DocumentUpdateOptions().ifMatch(createResult.getRev()))); + Throwable thrown = catchThrowable(() -> collection.updateDocument(doc.getKey(), doc, + new DocumentUpdateOptions().ifMatch(createResult.getRev()))); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getResponseCode()).isEqualTo(412); @@ -943,14 +944,13 @@ void updateDocumentPreconditionFailed(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocument(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); - doc.getProperties().clear(); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); - final DocumentUpdateEntity replaceResult = collection - .replaceDocument(createResult.getKey(), doc, null); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), +doc, null); assertThat(replaceResult).isNotNull(); assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); assertThat(replaceResult.getNew()).isNull(); @@ -958,8 +958,7 @@ void replaceDocument(ArangoCollection collection) { assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); assertThat(readResult.getProperties().keySet()).doesNotContain("a"); @@ -970,34 +969,34 @@ void replaceDocument(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentUpdateRev(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); - final DocumentUpdateEntity replaceResult = collection - .replaceDocument(createResult.getKey(), doc, null); - assertThat(doc.getRevision()).isEqualTo(replaceResult.getRev()); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), + doc, null); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(replaceResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); } @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentIfMatch(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); - doc.getProperties().clear(); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch(createResult.getRev()); - final DocumentUpdateEntity replaceResult = collection - .replaceDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), + doc, options); assertThat(replaceResult).isNotNull(); assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - final BaseDocument readResult = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); assertThat(readResult.getProperties().keySet()).doesNotContain("a"); @@ -1008,11 +1007,10 @@ void replaceDocumentIfMatch(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentIfMatchFail(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); - doc.getProperties().clear(); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch("no"); @@ -1024,11 +1022,10 @@ void replaceDocumentIfMatchFail(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentIgnoreRevsFalse(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); - doc.getProperties().clear(); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); doc.setRevision("no"); @@ -1040,15 +1037,14 @@ void replaceDocumentIgnoreRevsFalse(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentReturnNew(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); - doc.getProperties().clear(); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().returnNew(true); - final DocumentUpdateEntity replaceResult = collection - .replaceDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), +doc, options); assertThat(replaceResult).isNotNull(); assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); @@ -1063,15 +1059,14 @@ void replaceDocumentReturnNew(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentReturnOld(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); - doc.getProperties().clear(); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().returnOld(true); - final DocumentUpdateEntity replaceResult = collection - .replaceDocument(createResult.getKey(), doc, options); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), + doc, options); assertThat(replaceResult).isNotNull(); assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); @@ -1087,10 +1082,9 @@ void replaceDocumentReturnOld(ArangoCollection collection) { @MethodSource("cols") void replaceDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument()); - final DocumentUpdateEntity meta = collection - .replaceDocument(createResult.getKey(), new BaseDocument(), new DocumentReplaceOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), +new BaseDocument(), new DocumentReplaceOptions().silent(true)); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); assertThat(meta.getKey()).isNull(); @@ -1101,25 +1095,23 @@ void replaceDocumentSilent(ArangoCollection collection) { @MethodSource("cols") void replaceDocumentSilentDontTouchInstance(ArangoCollection collection) { assumeTrue(isSingleServer()); - final BaseDocument doc = new BaseDocument(); - final DocumentCreateEntity createResult = collection.insertDocument(doc); - final String revision = doc.getRevision(); - assertThat(revision).isNotNull(); - final DocumentUpdateEntity meta = collection - .replaceDocument(createResult.getKey(), doc, new DocumentReplaceOptions().silent(true)); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc); + final DocumentUpdateEntity meta = collection.replaceDocument(createResult.getKey(), doc, + new DocumentReplaceOptions().silent(true)); assertThat(meta.getRev()).isNull(); - assertThat(doc.getRevision()).isEqualTo(revision); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); } @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument()); - final MultiDocumentEntity> info = collection - .replaceDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), - new DocumentReplaceOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final MultiDocumentEntity> info = + collection.replaceDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), + new DocumentReplaceOptions().silent(true)); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); assertThat(info.getDocumentsAndErrors()).isEmpty(); @@ -1129,25 +1121,22 @@ void replaceDocumentsSilent(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void deleteDocument(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); - collection.deleteDocument(createResult.getKey(), null, null); - final BaseDocument document = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); + collection.deleteDocument(createResult.getKey()); + final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(document).isNull(); } @ParameterizedTest(name = "{index}") @MethodSource("cols") void deleteDocumentReturnOld(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); final DocumentDeleteOptions options = new DocumentDeleteOptions().returnOld(true); - final DocumentDeleteEntity deleteResult = collection - .deleteDocument(createResult.getKey(), BaseDocument.class, options); + final DocumentDeleteEntity deleteResult = collection.deleteDocument(createResult.getKey(), + options, BaseDocument.class); assertThat(deleteResult.getOld()).isNotNull(); assertThat(deleteResult.getOld()).isInstanceOf(BaseDocument.class); assertThat(deleteResult.getOld().getAttribute("a")).isNotNull(); @@ -1157,24 +1146,21 @@ void deleteDocumentReturnOld(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void deleteDocumentIfMatch(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc, null); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch(createResult.getRev()); - collection.deleteDocument(createResult.getKey(), null, options); - final BaseDocument document = collection - .getDocument(createResult.getKey(), BaseDocument.class, null); + collection.deleteDocument(createResult.getKey(), options); + final BaseDocument document = collection.getDocument(createResult.getKey(), BaseDocument.class, null); assertThat(document).isNull(); } @ParameterizedTest(name = "{index}") @MethodSource("cols") void deleteDocumentIfMatchFail(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); - final DocumentCreateEntity createResult = collection - .insertDocument(doc, null); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> collection.deleteDocument(createResult.getKey(), null, options)); + Throwable thrown = catchThrowable(() -> collection.deleteDocument(createResult.getKey(), options)); assertThat(thrown).isInstanceOf(ArangoDBException.class); } @@ -1182,10 +1168,9 @@ void deleteDocumentIfMatchFail(ArangoCollection collection) { @MethodSource("cols") void deleteDocumentSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument()); - final DocumentDeleteEntity meta = collection - .deleteDocument(createResult.getKey(), BaseDocument.class, new DocumentDeleteOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final DocumentDeleteEntity meta = collection.deleteDocument(createResult.getKey(), + new DocumentDeleteOptions().silent(true), BaseDocument.class); assertThat(meta).isNotNull(); assertThat(meta.getId()).isNull(); assertThat(meta.getKey()).isNull(); @@ -1196,11 +1181,11 @@ void deleteDocumentSilent(ArangoCollection collection) { @MethodSource("cols") void deleteDocumentsSilent(ArangoCollection collection) { assumeTrue(isSingleServer()); - final DocumentCreateEntity createResult = collection - .insertDocument(new BaseDocument()); - final MultiDocumentEntity> info = collection - .deleteDocuments(Collections.singletonList(createResult.getKey()), BaseDocument.class, - new DocumentDeleteOptions().silent(true)); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final MultiDocumentEntity> info = collection.deleteDocuments( + Collections.singletonList(createResult.getKey()), + new DocumentDeleteOptions().silent(true), + BaseDocument.class); assertThat(info).isNotNull(); assertThat(info.getDocuments()).isEmpty(); assertThat(info.getDocumentsAndErrors()).isEmpty(); @@ -1323,6 +1308,9 @@ void createGeoIndex(ArangoCollection collection) { } else { assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); } + if (isAtLeastVersion(3, 10)) { + assertThat(indexResult.getLegacyPolygons()).isFalse(); + } } @ParameterizedTest(name = "{index}") @@ -1350,6 +1338,40 @@ void createGeoIndexWithOptions(ArangoCollection collection) { assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); } assertThat(indexResult.getName()).isEqualTo(name); + if (isAtLeastVersion(3, 10)) { + assertThat(indexResult.getLegacyPolygons()).isFalse(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createGeoIndexLegacyPolygons(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + String name = "geoIndex-" + rnd(); + final GeoIndexOptions options = new GeoIndexOptions(); + options.name(name); + options.legacyPolygons(true); + + String f1 = "field-" + rnd(); + final Collection fields = Collections.singletonList(f1); + final IndexEntity indexResult = collection.ensureGeoIndex(fields, options); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + if (isAtLeastVersion(3, 4)) { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo); + } else { + assertThat(indexResult.getType()).isEqualTo(IndexType.geo1); + } + assertThat(indexResult.getName()).isEqualTo(name); + if (isAtLeastVersion(3, 10)) { + assertThat(indexResult.getLegacyPolygons()).isTrue(); + } } @ParameterizedTest(name = "{index}") @@ -1469,6 +1491,60 @@ void createPersistentIndex(ArangoCollection collection) { assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); assertThat(indexResult.getUnique()).isFalse(); assertThat(indexResult.getDeduplicate()).isTrue(); + if (isAtLeastVersion(3, 10)) { + assertThat(indexResult.getCacheEnabled()).isFalse(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createPersistentIndexCacheEnabled(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + final Collection fields = Arrays.asList(f1, f2); + + final IndexEntity indexResult = collection.ensurePersistentIndex(fields, new PersistentIndexOptions().cacheEnabled(true)); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getDeduplicate()).isTrue(); + assertThat(indexResult.getCacheEnabled()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createPersistentIndexStoredValues(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + final Collection fields = Arrays.asList(f1, f2); + + final IndexEntity indexResult = collection.ensurePersistentIndex(fields, new PersistentIndexOptions().storedValues("v1", "v2")); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1); + assertThat(indexResult.getFields()).contains(f2); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getSparse()).isFalse(); + assertThat(indexResult.getType()).isEqualTo(IndexType.persistent); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getDeduplicate()).isTrue(); + assertThat(indexResult.getCacheEnabled()).isFalse(); + assertThat(indexResult.getStoredValues()) + .hasSize(2) + .contains("v1", "v2"); } @ParameterizedTest(name = "{index}") @@ -1527,9 +1603,8 @@ void createZKDIndexWithOptions(ArangoCollection collection) { collection.truncate(); String name = "ZKDIndex-" + rnd(); - final ZKDIndexOptions options = new ZKDIndexOptions() - .name(name) - .fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE); + final ZKDIndexOptions options = + new ZKDIndexOptions().name(name).fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE); String f1 = "field-" + rnd(); String f2 = "field-" + rnd(); @@ -1715,10 +1790,8 @@ void getIndexes(ArangoCollection collection) { String f1 = "field-" + rnd(); final Collection fields = Collections.singletonList(f1); collection.ensureHashIndex(fields, null); - long matchingIndexes = collection.getIndexes().stream() - .filter(i -> i.getType() == IndexType.hash) - .filter(i -> i.getFields().contains(f1)) - .count(); + long matchingIndexes = + collection.getIndexes().stream().filter(i -> i.getType() == IndexType.hash).filter(i -> i.getFields().contains(f1)).count(); assertThat(matchingIndexes).isEqualTo(1L); } @@ -1742,16 +1815,14 @@ void exists(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void truncate(ArangoCollection collection) { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); collection.insertDocument(doc, null); - final BaseDocument readResult = collection - .getDocument(doc.getKey(), BaseDocument.class, null); + final BaseDocument readResult = collection.getDocument(doc.getKey(), BaseDocument.class, null); assertThat(readResult.getKey()).isEqualTo(doc.getKey()); final CollectionEntity truncateResult = collection.truncate(); assertThat(truncateResult).isNotNull(); assertThat(truncateResult.getId()).isNotNull(); - final BaseDocument document = collection - .getDocument(doc.getKey(), BaseDocument.class, null); + final BaseDocument document = collection.getDocument(doc.getKey(), BaseDocument.class, null); assertThat(document).isNull(); } @@ -1759,35 +1830,30 @@ void truncate(ArangoCollection collection) { @MethodSource("cols") void getCount(ArangoCollection collection) { Long initialCount = collection.count().getCount(); - collection.insertDocument("{}", null); + collection.insertDocument(RawJson.of("{}")); final CollectionPropertiesEntity count = collection.count(); assertThat(count.getCount()).isEqualTo(initialCount + 1L); } @ParameterizedTest(name = "{index}") @MethodSource("cols") - void documentExists(ArangoCollection collection) throws JsonProcessingException { + void documentExists(ArangoCollection collection) { final Boolean existsNot = collection.documentExists(rnd(), null); assertThat(existsNot).isFalse(); String key = rnd(); - collection.insertDocument(mapper.writeValueAsString(Collections.singletonMap("_key", key)), null); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + collection.insertDocument(rawJson); final Boolean exists = collection.documentExists(key, null); assertThat(exists).isTrue(); } @ParameterizedTest(name = "{index}") @MethodSource("cols") - void documentExistsThrowExcpetion(ArangoCollection collection) { - Throwable thrown = catchThrowable(() -> collection.documentExists("no", new DocumentExistsOptions().catchException(false))); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void documentExistsIfMatch(ArangoCollection collection) throws JsonProcessingException { + void documentExistsIfMatch(ArangoCollection collection) { String key = rnd(); - final DocumentCreateEntity createResult = collection.insertDocument(mapper.writeValueAsString(Collections.singletonMap("_key", key)), null); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + final DocumentCreateEntity createResult = collection.insertDocument(rawJson); final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch(createResult.getRev()); final Boolean exists = collection.documentExists(key, options); assertThat(exists).isTrue(); @@ -1795,9 +1861,10 @@ void documentExistsIfMatch(ArangoCollection collection) throws JsonProcessingExc @ParameterizedTest(name = "{index}") @MethodSource("cols") - void documentExistsIfMatchFail(ArangoCollection collection) throws JsonProcessingException { + void documentExistsIfMatchFail(ArangoCollection collection) { String key = rnd(); - collection.insertDocument(mapper.writeValueAsString(Collections.singletonMap("_key", key)), null); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + collection.insertDocument(rawJson); final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch("no"); final Boolean exists = collection.documentExists(key, options); assertThat(exists).isFalse(); @@ -1805,9 +1872,10 @@ void documentExistsIfMatchFail(ArangoCollection collection) throws JsonProcessin @ParameterizedTest(name = "{index}") @MethodSource("cols") - void documentExistsIfNoneMatch(ArangoCollection collection) throws JsonProcessingException { + void documentExistsIfNoneMatch(ArangoCollection collection) { String key = rnd(); - collection.insertDocument(mapper.writeValueAsString(Collections.singletonMap("_key", key)), null); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + collection.insertDocument(rawJson); final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch("no"); final Boolean exists = collection.documentExists(key, options); assertThat(exists).isTrue(); @@ -1815,9 +1883,10 @@ void documentExistsIfNoneMatch(ArangoCollection collection) throws JsonProcessin @ParameterizedTest(name = "{index}") @MethodSource("cols") - void documentExistsIfNoneMatchFail(ArangoCollection collection) throws JsonProcessingException { + void documentExistsIfNoneMatchFail(ArangoCollection collection) { String key = rnd(); - final DocumentCreateEntity createResult = collection.insertDocument(mapper.writeValueAsString(Collections.singletonMap("_key", key)), null); + RawJson rawJson = RawJson.of("{\"_key\":\"" + key + "\"}"); + final DocumentCreateEntity createResult = collection.insertDocument(rawJson); final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch(createResult.getRev()); final Boolean exists = collection.documentExists(key, options); assertThat(exists).isFalse(); @@ -1826,14 +1895,10 @@ void documentExistsIfNoneMatchFail(ArangoCollection collection) throws JsonProce @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocuments(ArangoCollection collection) { - final Collection values = Arrays.asList( - new BaseDocument(), - new BaseDocument(), - new BaseDocument() - ); + final Collection values = Arrays.asList(new BaseDocument(), new BaseDocument(), + new BaseDocument()); - final MultiDocumentEntity> docs = collection - .insertDocuments(values, null); + final MultiDocumentEntity docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(3); @@ -1841,55 +1906,25 @@ void insertDocuments(ArangoCollection collection) { assertThat(docs.getErrors()).isEmpty(); } - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertDocumentsOverwrite(ArangoCollection collection) { - assumeTrue(isAtLeastVersion(3, 4)); - - final BaseDocument doc1 = new BaseDocument(); - doc1.addAttribute("value", "a"); - final DocumentCreateEntity meta1 = collection.insertDocument(doc1); - - final BaseDocument doc2 = new BaseDocument(); - doc2.addAttribute("value", "a"); - final DocumentCreateEntity meta2 = collection.insertDocument(doc2); - - doc1.addAttribute("value", "b"); - doc2.addAttribute("value", "b"); - - final MultiDocumentEntity> repsert = collection - .insertDocuments(Arrays.asList(doc1, doc2), - new DocumentCreateOptions().overwrite(true).returnOld(true).returnNew(true)); - assertThat(repsert).isNotNull(); - assertThat(repsert.getDocuments()).hasSize(2); - assertThat(repsert.getErrors()).isEmpty(); - for (final DocumentCreateEntity documentCreateEntity : repsert.getDocuments()) { - assertThat(documentCreateEntity.getRev()).isNotEqualTo(meta1.getRev()); - assertThat(documentCreateEntity.getRev()).isNotEqualTo(meta2.getRev()); - assertThat(documentCreateEntity.getOld().getAttribute("value")).isEqualTo("a"); - assertThat(documentCreateEntity.getNew().getAttribute("value")).isEqualTo("b"); - } - } - @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentsOverwriteModeUpdate(ArangoCollection collection) { assumeTrue(isAtLeastVersion(3, 7)); - final BaseDocument doc1 = new BaseDocument(); + final BaseDocument doc1 = new BaseDocument(UUID.randomUUID().toString()); doc1.addAttribute("foo", "a"); - final DocumentCreateEntity meta1 = collection.insertDocument(doc1); + final DocumentCreateEntity meta1 = collection.insertDocument(doc1); - final BaseDocument doc2 = new BaseDocument(); + final BaseDocument doc2 = new BaseDocument(UUID.randomUUID().toString()); doc2.addAttribute("foo", "a"); - final DocumentCreateEntity meta2 = collection.insertDocument(doc2); + final DocumentCreateEntity meta2 = collection.insertDocument(doc2); doc1.addAttribute("bar", "b"); doc2.addAttribute("bar", "b"); - final MultiDocumentEntity> repsert = collection - .insertDocuments(Arrays.asList(doc1, doc2), - new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); + final MultiDocumentEntity> repsert = + collection.insertDocuments(Arrays.asList(doc1, doc2), + new DocumentCreateOptions().overwriteMode(OverwriteMode.update).returnNew(true)); assertThat(repsert).isNotNull(); assertThat(repsert.getDocuments()).hasSize(2); assertThat(repsert.getErrors()).isEmpty(); @@ -1904,17 +1939,52 @@ void insertDocumentsOverwriteModeUpdate(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentsJson(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - values.add("{}"); - values.add("{}"); - values.add("{}"); - final MultiDocumentEntity> docs = collection - .insertDocuments(values); + final Collection values = new ArrayList<>(); + values.add(RawJson.of("{}")); + values.add(RawJson.of("{}")); + values.add(RawJson.of("{}")); + final MultiDocumentEntity docs = collection.insertDocuments(values); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsRawData(ArangoCollection collection) { + final RawData values = RawData.of("[{},{},{}]"); + final MultiDocumentEntity docs = collection.insertDocuments(values); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsRawDataReturnNew(ArangoCollection collection) { + final RawData values = RawData.of("[{\"aaa\":33},{\"aaa\":33},{\"aaa\":33}]"); + final MultiDocumentEntity> docs = + collection.insertDocuments(values, new DocumentCreateOptions().returnNew(true)); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(3); assertThat(docs.getErrors()).isNotNull(); assertThat(docs.getErrors()).isEmpty(); + + for (final DocumentCreateEntity doc : docs.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("aaa")).isTrue(); + assertThat(jn.get("aaa").intValue()).isEqualTo(33); + } } @ParameterizedTest(name = "{index}") @@ -1922,8 +1992,7 @@ void insertDocumentsJson(ArangoCollection collection) { void insertDocumentsOne(ArangoCollection collection) { final Collection values = new ArrayList<>(); values.add(new BaseDocument()); - final MultiDocumentEntity> docs = collection - .insertDocuments(values, null); + final MultiDocumentEntity docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(1); @@ -1935,8 +2004,7 @@ void insertDocumentsOne(ArangoCollection collection) { @MethodSource("cols") void insertDocumentsEmpty(ArangoCollection collection) { final Collection values = new ArrayList<>(); - final MultiDocumentEntity> docs = collection - .insertDocuments(values, null); + final MultiDocumentEntity docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).isEmpty(); @@ -1952,8 +2020,8 @@ void insertDocumentsReturnNew(ArangoCollection collection) { values.add(new BaseDocument()); values.add(new BaseDocument()); final DocumentCreateOptions options = new DocumentCreateOptions().returnNew(true); - final MultiDocumentEntity> docs = collection - .insertDocuments(values, options); + final MultiDocumentEntity> docs = collection.insertDocuments(values, + options); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(3); @@ -1972,14 +2040,10 @@ void insertDocumentsReturnNew(ArangoCollection collection) { void insertDocumentsFail(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); - final MultiDocumentEntity> docs = collection - .insertDocuments(values); + final MultiDocumentEntity docs = collection.insertDocuments(values); assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); assertThat(docs.getDocuments()).hasSize(2); @@ -1991,11 +2055,8 @@ void insertDocumentsFail(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void importDocuments(ArangoCollection collection) { - final Collection values = Arrays.asList( - new BaseDocument(), - new BaseDocument(), - new BaseDocument() - ); + final Collection values = Arrays.asList(new BaseDocument(), new BaseDocument(), + new BaseDocument()); final DocumentImportEntity docs = collection.importDocuments(values); assertThat(docs).isNotNull(); @@ -2010,10 +2071,10 @@ void importDocuments(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void importDocumentsJsonList(ArangoCollection collection) { - final Collection values = Arrays.asList( - "{}", - "{}", - "{}" + final Collection values = Arrays.asList( + RawJson.of("{}"), + RawJson.of("{}"), + RawJson.of("{}") ); final DocumentImportEntity docs = collection.importDocuments(values); @@ -2032,11 +2093,8 @@ void importDocumentsDuplicateDefaultError(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), +new BaseDocument(k2)); final DocumentImportEntity docs = collection.importDocuments(values); assertThat(docs).isNotNull(); @@ -2054,14 +2112,11 @@ void importDocumentsDuplicateError(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.error)); + final DocumentImportEntity docs = collection.importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.error)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2077,14 +2132,11 @@ void importDocumentsDuplicateIgnore(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); + final DocumentImportEntity docs = collection.importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2100,14 +2152,11 @@ void importDocumentsDuplicateReplace(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); + final DocumentImportEntity docs = collection.importDocuments(values, +new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2123,14 +2172,11 @@ void importDocumentsDuplicateUpdate(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.update)); + final DocumentImportEntity docs = collection.importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.update)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2146,13 +2192,11 @@ void importDocumentsCompleteFail(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); - Throwable thrown = catchThrowable(() -> collection.importDocuments(values, new DocumentImportOptions().complete(true))); + Throwable thrown = catchThrowable(() -> collection.importDocuments(values, + new DocumentImportOptions().complete(true))); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getErrorNum()).isEqualTo(1210); @@ -2164,14 +2208,10 @@ void importDocumentsDetails(ArangoCollection collection) { String k1 = rnd(); String k2 = rnd(); - final Collection values = Arrays.asList( - new BaseDocument(k1), - new BaseDocument(k2), - new BaseDocument(k2) - ); + final Collection values = Arrays.asList(new BaseDocument(k1), new BaseDocument(k2), + new BaseDocument(k2)); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().details(true)); + final DocumentImportEntity docs = collection.importDocuments(values, new DocumentImportOptions().details(true)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2211,17 +2251,14 @@ void importDocumentsOverwriteTrue(ArangoCollection collection) { @MethodSource("edges") void importDocumentsFromToPrefix(ArangoCollection edgeCollection) { final Collection values = new ArrayList<>(); - final String[] keys = { - rnd(), - rnd() - }; + final String[] keys = {rnd(), rnd()}; for (String s : keys) { values.add(new BaseEdgeDocument(s, "from", "to")); } assertThat(values).hasSize(keys.length); - final DocumentImportEntity importResult = edgeCollection - .importDocuments(values, new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); + final DocumentImportEntity importResult = edgeCollection.importDocuments(values, + new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); assertThat(importResult).isNotNull(); assertThat(importResult.getCreated()).isEqualTo(values.size()); for (String key : keys) { @@ -2235,12 +2272,10 @@ void importDocumentsFromToPrefix(ArangoCollection edgeCollection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void importDocumentsJson(ArangoCollection collection) throws JsonProcessingException { - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", rnd()), - Collections.singletonMap("_key", rnd()) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), + Collections.singletonMap("_key", rnd()))); - final DocumentImportEntity docs = collection.importDocuments(values); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2256,13 +2291,10 @@ void importDocumentsJsonDuplicateDefaultError(ArangoCollection collection) throw String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), - Collections.singletonMap("_key", k2) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection.importDocuments(values); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2278,14 +2310,11 @@ void importDocumentsJsonDuplicateError(ArangoCollection collection) throws JsonP String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), - Collections.singletonMap("_key", k2) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.error)); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.error)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2301,13 +2330,10 @@ void importDocumentsJsonDuplicateIgnore(ArangoCollection collection) throws Json String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), - Collections.singletonMap("_key", k2) - )); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2323,14 +2349,11 @@ void importDocumentsJsonDuplicateReplace(ArangoCollection collection) throws Jso String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), - Collections.singletonMap("_key", k2) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.replace)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2346,14 +2369,11 @@ void importDocumentsJsonDuplicateUpdate(ArangoCollection collection) throws Json String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), - Collections.singletonMap("_key", k2) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), +Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.update)); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.update)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2367,7 +2387,8 @@ void importDocumentsJsonDuplicateUpdate(ArangoCollection collection) throws Json @MethodSource("cols") void importDocumentsJsonCompleteFail(ArangoCollection collection) { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - Throwable thrown = catchThrowable(() -> collection.importDocuments(values, new DocumentImportOptions().complete(true))); + Throwable thrown = catchThrowable(() -> collection.importDocuments(RawData.of(values), + new DocumentImportOptions().complete(true))); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getErrorNum()).isEqualTo(1210); @@ -2379,14 +2400,11 @@ void importDocumentsJsonDetails(ArangoCollection collection) throws JsonProcessi String k1 = rnd(); String k2 = rnd(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", k1), - Collections.singletonMap("_key", k2), - Collections.singletonMap("_key", k2) - )); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", k1), + Collections.singletonMap("_key", k2), Collections.singletonMap("_key", k2))); - final DocumentImportEntity docs = collection - .importDocuments(values, new DocumentImportOptions().details(true)); + final DocumentImportEntity docs = collection.importDocuments(RawData.of(values), +new DocumentImportOptions().details(true)); assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); assertThat(docs.getEmpty()).isZero(); @@ -2403,11 +2421,9 @@ void importDocumentsJsonOverwriteFalse(ArangoCollection collection) throws JsonP collection.insertDocument(new BaseDocument()); Long initialCount = collection.count().getCount(); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", rnd()), - Collections.singletonMap("_key", rnd()) - )); - collection.importDocuments(values, new DocumentImportOptions().overwrite(false)); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), + Collections.singletonMap("_key", rnd()))); + collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(false)); assertThat(collection.count().getCount()).isEqualTo(initialCount + 2L); } @@ -2416,11 +2432,9 @@ void importDocumentsJsonOverwriteFalse(ArangoCollection collection) throws JsonP void importDocumentsJsonOverwriteTrue(ArangoCollection collection) throws JsonProcessingException { collection.insertDocument(new BaseDocument()); - final String values = mapper.writeValueAsString(Arrays.asList( - Collections.singletonMap("_key", rnd()), - Collections.singletonMap("_key", rnd()) - )); - collection.importDocuments(values, new DocumentImportOptions().overwrite(true)); + final String values = mapper.writeValueAsString(Arrays.asList(Collections.singletonMap("_key", rnd()), + Collections.singletonMap("_key", rnd()))); + collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(true)); assertThat(collection.count().getCount()).isEqualTo(2L); } @@ -2432,21 +2446,11 @@ void importDocumentsJsonFromToPrefix(ArangoCollection edgeCollection) throws Jso final String[] keys = {k1, k2}; - final String values = mapper.writeValueAsString(Arrays.asList( - new MapBuilder() - .put("_key", k1) - .put("_from", "from") - .put("_to", "to") - .get(), - new MapBuilder() - .put("_key", k2) - .put("_from", "from") - .put("_to", "to") - .get() - )); - - final DocumentImportEntity importResult = edgeCollection - .importDocuments(values, new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); + final String values = mapper.writeValueAsString(Arrays.asList(new MapBuilder().put("_key", k1).put("_from", + "from").put("_to", "to").get(), new MapBuilder().put("_key", k2).put("_from", "from").put("_to", "to").get())); + + final DocumentImportEntity importResult = edgeCollection.importDocuments(RawData.of(values), +new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")); assertThat(importResult).isNotNull(); assertThat(importResult.getCreated()).isEqualTo(2); for (String key : keys) { @@ -2462,25 +2466,43 @@ void importDocumentsJsonFromToPrefix(ArangoCollection edgeCollection) throws Jso void deleteDocumentsByKey(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection keys = new ArrayList<>(); keys.add("1"); keys.add("2"); - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(keys, null, null); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys); + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments()).hasSize(2); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isIn("1", "2"); + } + assertThat(deleteResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentsRawDataByKeyReturnOld(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"},{\"_key\":\"2\"}]"); + collection.insertDocuments(values); + final RawData keys = RawData.of("[\"1\",\"2\"]"); + MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, + new DocumentDeleteOptions().returnOld(true)); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).hasSize(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isIn("1", "2"); + assertThat(i.getOld()).isNotNull().isInstanceOf(RawJson.class); + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) i.getOld()).getValue()); + assertThat(jn.get("_key").asText()).isEqualTo(i.getKey()); } assertThat(deleteResult.getErrors()).isEmpty(); } @@ -2490,21 +2512,20 @@ void deleteDocumentsByKey(ArangoCollection collection) { void deleteDocumentsByDocuments(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } - collection.insertDocuments(values, null); - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(values, null, null); + collection.insertDocuments(values); + MultiDocumentEntity> deleteResult = collection.deleteDocuments(values); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).hasSize(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isIn("1", "2"); } assertThat(deleteResult.getErrors()).isEmpty(); @@ -2515,18 +2536,17 @@ void deleteDocumentsByDocuments(ArangoCollection collection) { void deleteDocumentsByKeyOne(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection keys = new ArrayList<>(); keys.add("1"); - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(keys, null, null); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).hasSize(1); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isEqualTo("1"); } assertThat(deleteResult.getErrors()).isEmpty(); @@ -2537,16 +2557,15 @@ void deleteDocumentsByKeyOne(ArangoCollection collection) { void deleteDocumentsByDocumentOne(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } - collection.insertDocuments(values, null); - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(values, null, null); + collection.insertDocuments(values); + final MultiDocumentEntity> deleteResult = collection.deleteDocuments(values); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).hasSize(1); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isEqualTo("1"); } assertThat(deleteResult.getErrors()).isEmpty(); @@ -2556,10 +2575,9 @@ void deleteDocumentsByDocumentOne(ArangoCollection collection) { @MethodSource("cols") void deleteDocumentsEmpty(ArangoCollection collection) { final Collection values = new ArrayList<>(); - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection keys = new ArrayList<>(); - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(keys, null, null); + final MultiDocumentEntity deleteResult = collection.deleteDocuments(keys); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).isEmpty(); assertThat(deleteResult.getErrors()).isEmpty(); @@ -2569,14 +2587,10 @@ void deleteDocumentsEmpty(ArangoCollection collection) { @MethodSource("cols") void deleteDocumentsByKeyNotExisting(ArangoCollection collection) { final Collection values = new ArrayList<>(); - collection.insertDocuments(values, null); - final Collection keys = Arrays.asList( - rnd(), - rnd() - ); + collection.insertDocuments(values); + final Collection keys = Arrays.asList(rnd(), rnd()); - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(keys, null, null); + final MultiDocumentEntity deleteResult = collection.deleteDocuments(keys); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).isEmpty(); assertThat(deleteResult.getErrors()).hasSize(2); @@ -2587,17 +2601,16 @@ void deleteDocumentsByKeyNotExisting(ArangoCollection collection) { void deleteDocumentsByDocumentsNotExisting(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } - final MultiDocumentEntity> deleteResult = collection - .deleteDocuments(values, null, null); + final MultiDocumentEntity deleteResult = collection.deleteDocuments(values); assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments()).isEmpty(); assertThat(deleteResult.getErrors()).hasSize(2); @@ -2606,15 +2619,11 @@ void deleteDocumentsByDocumentsNotExisting(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocuments(ArangoCollection collection) { - final Collection values = Arrays.asList( - new BaseDocument(rnd()), - new BaseDocument(rnd()) - ); - collection.insertDocuments(values, null); + final Collection values = Arrays.asList(new BaseDocument(rnd()), new BaseDocument(rnd())); + collection.insertDocuments(values); values.forEach(it -> it.addAttribute("a", "test")); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(values, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(values); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2622,33 +2631,26 @@ void updateDocuments(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentsWithDifferentReturnType(ArangoCollection collection) { - List keys = IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID()).collect(Collectors.toList()); - List docs = keys.stream() - .map(BaseDocument::new) - .peek(it -> it.addAttribute("a", "test")) - .collect(Collectors.toList()); + List keys = + IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID()).collect(Collectors.toList()); + List docs = + keys.stream().map(BaseDocument::new).peek(it -> it.addAttribute("a", "test")).collect(Collectors.toList()); collection.insertDocuments(docs); - List> modifiedDocs = docs.stream() - .peek(it -> it.addAttribute("b", "test")) - .map(it -> { - Map map = new HashMap<>(); - map.put("_key", it.getKey()); - map.put("a", it.getAttribute("a")); - map.put("b", it.getAttribute("b")); - return map; - }) - .collect(Collectors.toList()); - - final MultiDocumentEntity> updateResult = collection - .updateDocuments(modifiedDocs, new DocumentUpdateOptions().returnNew(true), BaseDocument.class); + List> modifiedDocs = docs.stream().peek(it -> it.addAttribute("b", "test")).map(it -> { + Map map = new HashMap<>(); + map.put("_key", it.getKey()); + map.put("a", it.getAttribute("a")); + map.put("b", it.getAttribute("b")); + return map; + }).collect(Collectors.toList()); + + final MultiDocumentEntity> updateResult = + collection.updateDocuments(modifiedDocs, new DocumentUpdateOptions().returnNew(true), BaseDocument.class); assertThat(updateResult.getDocuments()).hasSize(3); assertThat(updateResult.getErrors()).isEmpty(); - assertThat(updateResult.getDocuments().stream()) - .map(DocumentUpdateEntity::getNew) - .allMatch(it -> it.getAttribute("a").equals("test")) - .allMatch(it -> it.getAttribute("b").equals("test")); + assertThat(updateResult.getDocuments().stream()).map(DocumentUpdateEntity::getNew).allMatch(it -> it.getAttribute("a").equals("test")).allMatch(it -> it.getAttribute("b").equals("test")); } @ParameterizedTest(name = "{index}") @@ -2656,17 +2658,16 @@ void updateDocumentsWithDifferentReturnType(ArangoCollection collection) { void updateDocumentsOne(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection updatedValues = new ArrayList<>(); final BaseDocument first = values.iterator().next(); first.addAttribute("a", "test"); updatedValues.add(first); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(updatedValues, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(1); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2675,8 +2676,7 @@ void updateDocumentsOne(ArangoCollection collection) { @MethodSource("cols") void updateDocumentsEmpty(ArangoCollection collection) { final Collection values = new ArrayList<>(); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(values, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(values); assertThat(updateResult.getDocuments()).isEmpty(); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2688,15 +2688,14 @@ void updateDocumentsWithoutKey(ArangoCollection collection) { { values.add(new BaseDocument("1")); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } updatedValues.add(new BaseDocument()); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(updatedValues, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(1); assertThat(updateResult.getErrors()).hasSize(1); } @@ -2704,18 +2703,54 @@ void updateDocumentsWithoutKey(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void updateDocumentsJson(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - values.add("{\"_key\":\"1\"}"); - values.add("{\"_key\":\"2\"}"); + final Collection values = new ArrayList<>(); + values.add(RawJson.of("{\"_key\":\"1\"}")); + values.add(RawJson.of("{\"_key\":\"2\"}")); + collection.insertDocuments(values); + + final Collection updatedValues = new ArrayList<>(); + updatedValues.add(RawJson.of("{\"_key\":\"1\", \"foo\":\"bar\"}")); + updatedValues.add(RawJson.of("{\"_key\":\"2\", \"foo\":\"bar\"}")); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentsRawData(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentsRawDataReturnNew(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); collection.insertDocuments(values); - final Collection updatedValues = new ArrayList<>(); - updatedValues.add("{\"_key\":\"1\", \"foo\":\"bar\"}"); - updatedValues.add("{\"_key\":\"2\", \"foo\":\"bar\"}"); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(updatedValues); + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); + MultiDocumentEntity> updateResult = + collection.updateDocuments(updatedValues, new DocumentUpdateOptions().returnNew(true)); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); + for (DocumentUpdateEntity doc : updateResult.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("foo")).isTrue(); + assertThat(jn.get("foo").textValue()).isEqualTo("bar"); + } } @ParameterizedTest(name = "{index}") @@ -2726,14 +2761,13 @@ void replaceDocuments(ArangoCollection collection) { values.add(new BaseDocument("1")); values.add(new BaseDocument("2")); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } - final MultiDocumentEntity> updateResult = collection - .replaceDocuments(updatedValues, null); + final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2743,17 +2777,16 @@ void replaceDocuments(ArangoCollection collection) { void replaceDocumentsOne(ArangoCollection collection) { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection updatedValues = new ArrayList<>(); final BaseDocument first = values.iterator().next(); first.addAttribute("a", "test"); updatedValues.add(first); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(updatedValues, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(1); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2762,8 +2795,7 @@ void replaceDocumentsOne(ArangoCollection collection) { @MethodSource("cols") void replaceDocumentsEmpty(ArangoCollection collection) { final Collection values = new ArrayList<>(); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(values, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(values); assertThat(updateResult.getDocuments()).isEmpty(); assertThat(updateResult.getErrors()).isEmpty(); } @@ -2775,15 +2807,14 @@ void replaceDocumentsWithoutKey(ArangoCollection collection) { { values.add(new BaseDocument("1")); } - collection.insertDocuments(values, null); + collection.insertDocuments(values); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } updatedValues.add(new BaseDocument()); - final MultiDocumentEntity> updateResult = collection - .updateDocuments(updatedValues, null); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(1); assertThat(updateResult.getErrors()).hasSize(1); } @@ -2791,32 +2822,54 @@ void replaceDocumentsWithoutKey(ArangoCollection collection) { @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocumentsJson(ArangoCollection collection) { - final Collection values = new ArrayList<>(); - values.add("{\"_key\":\"1\"}"); - values.add("{\"_key\":\"2\"}"); + final Collection values = new ArrayList<>(); + values.add(RawJson.of("{\"_key\":\"1\"}")); + values.add(RawJson.of("{\"_key\":\"2\"}")); collection.insertDocuments(values); - final Collection updatedValues = new ArrayList<>(); - updatedValues.add("{\"_key\":\"1\", \"foo\":\"bar\"}"); - updatedValues.add("{\"_key\":\"2\", \"foo\":\"bar\"}"); - final MultiDocumentEntity> updateResult = collection - .replaceDocuments(updatedValues); + final Collection updatedValues = new ArrayList<>(); + updatedValues.add(RawJson.of("{\"_key\":\"1\", \"foo\":\"bar\"}")); + updatedValues.add(RawJson.of("{\"_key\":\"2\", \"foo\":\"bar\"}")); + final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues); assertThat(updateResult.getDocuments()).hasSize(2); assertThat(updateResult.getErrors()).isEmpty(); } @ParameterizedTest(name = "{index}") @MethodSource("cols") - void load(ArangoCollection collection) { - final CollectionEntity result = collection.load(); - assertThat(result.getName()).isEqualTo(COLLECTION_NAME); + void replaceDocumentsRawData(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); + final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); } @ParameterizedTest(name = "{index}") @MethodSource("cols") - void unload(ArangoCollection collection) { - final CollectionEntity result = collection.unload(); - assertThat(result.getName()).isEqualTo(COLLECTION_NAME); + void replaceDocumentsRawDataReturnNew(ArangoCollection collection) { + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); + MultiDocumentEntity> updateResult = + collection.replaceDocuments(updatedValues, new DocumentReplaceOptions().returnNew(true)); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + for (DocumentUpdateEntity doc : updateResult.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("foo")).isTrue(); + assertThat(jn.get("foo").textValue()).isEqualTo("bar"); + } } @ParameterizedTest(name = "{index}") @@ -2843,23 +2896,12 @@ void changeProperties(ArangoCollection collection) { assertThat(properties.getSchema()).isNull(); } - String schemaRule = ("{ " + - " \"properties\": {" + - " \"number\": {" + - " \"type\": \"number\"" + - " }" + - " }" + - " }") - .replaceAll("\\s", ""); + String schemaRule = ("{ " + " \"properties\": {" + " \"number\": {" + " " + +" \"type\": \"number\"" + " }" + " }" + " }").replaceAll("\\s", ""); String schemaMessage = "The document has problems!"; - CollectionPropertiesOptions updatedOptions = new CollectionPropertiesOptions() - .waitForSync(!properties.getWaitForSync()) - .schema(new CollectionSchema() - .setLevel(CollectionSchema.Level.NEW) - .setMessage(schemaMessage) - .setRule(schemaRule) - ); + CollectionPropertiesOptions updatedOptions = +new CollectionPropertiesOptions().waitForSync(!properties.getWaitForSync()).schema(new CollectionSchema().setLevel(CollectionSchema.Level.NEW).setMessage(schemaMessage).setRule(schemaRule)); final CollectionPropertiesEntity changedProperties = collection.changeProperties(updatedOptions); assertThat(changedProperties.getWaitForSync()).isNotNull(); @@ -2873,9 +2915,7 @@ void changeProperties(ArangoCollection collection) { // revert changes CollectionPropertiesEntity revertedProperties = collection.changeProperties(new CollectionPropertiesOptions() - .waitForSync(properties.getWaitForSync()) - .schema(CollectionSchema.NULL_SCHEMA) - ); + .waitForSync(properties.getWaitForSync()).schema(new CollectionSchema())); if (isAtLeastVersion(3, 7)) { assertThat(revertedProperties.getSchema()).isNull(); } @@ -3034,4 +3074,147 @@ void getPermissions(ArangoCollection collection) { assertThat(collection.getPermissions("root")).isEqualTo(Permissions.RW); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void annotationsInParamsAndMethods(ArangoCollection collection) { + assumeTrue(collection.getSerde().getUserSerde() instanceof JacksonSerde, "JacksonSerde only"); + AnnotatedEntity entity = new AnnotatedEntity(UUID.randomUUID().toString()); + AnnotatedEntity doc = collection.insertDocument(entity, new DocumentCreateOptions().returnNew(true)).getNew(); + assertThat(doc).isNotNull(); + assertThat(doc.getKey()).isEqualTo(entity.getKey()); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getRev()).isNotNull(); + } + + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") + public interface Animal { + String getKey(); + + String getName(); + } + + public static class Dog implements Animal { + + @Key + private String key; + private String name; + + public Dog() { + } + + public Dog(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Cat implements Animal { + @Key + private String key; + private String name; + + public Cat() { + } + + public Cat(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class TestUpdateEntity { + private String a, b; + + public String getA() { + return a; + } + + public String getB() { + return b; + } + } + + public static class TestUpdateEntitySerializeNullFalse { + private String a, b; + + @JsonInclude(JsonInclude.Include.NON_NULL) + public String getA() { + return a; + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + public String getB() { + return b; + } + } + + public static class AnnotatedEntity { + + private final String key; + private String id; + private String rev; + + public AnnotatedEntity(@Key String key) { + this.key = key; + } + + public String getKey() { + return key; + } + + public String getId() { + return id; + } + + @Id + public void setId(String id) { + this.id = id; + } + + public String getRev() { + return rev; + } + + @Rev + public void setRev(String rev) { + this.rev = rev; + } + } + } diff --git a/driver/src/test/java/com/arangodb/ArangoCursorTest.java b/driver/src/test/java/com/arangodb/ArangoCursorTest.java new file mode 100644 index 000000000..cfbd98775 --- /dev/null +++ b/driver/src/test/java/com/arangodb/ArangoCursorTest.java @@ -0,0 +1,133 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.model.AqlQueryOptions; +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoCursorTest extends BaseJunit5 { + + @BeforeAll + static void init() { + initDB(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void firstStream(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final Optional first = cursor.stream().findFirst(); + assertThat(first).isPresent(); + assertThat(first.get().isInt()).isTrue(); + assertThat(first.get().asLong()).isZero(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void next(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", new AqlQueryOptions().batchSize(5), + JsonNode.class); + while (cursor.hasNext()) { + cursor.next(); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void mapFilterCountStream(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final long count = cursor.stream().map(JsonNode::asLong).filter(t -> t < 50).count(); + assertThat(count).isEqualTo(50L); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void mapFilterCollectIntoSetStream(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final Set target = cursor.stream().map(JsonNode::asLong).filter(t -> t < 50).collect(Collectors.toSet()); + assertThat(target) + .isNotNull() + .hasSize(50); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void forEach(ArangoDatabase db) { + final AtomicLong i = new AtomicLong(0L); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + cursor.forEach(t -> assertThat(t.asLong()).isEqualTo(i.getAndIncrement())); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void mapForeachStream(ArangoDatabase db) { + final AtomicLong i = new AtomicLong(0L); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + cursor.stream().map(JsonNode::asLong).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void mapFilterForEachStream(ArangoDatabase db) { + final AtomicLong i = new AtomicLong(0L); + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + cursor.stream().map(JsonNode::asLong).filter(t -> t < 50).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void anyMatchStream(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final boolean match = cursor.stream().anyMatch(t -> t.asLong() == 50L); + assertThat(match).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void noneMatchStream(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final boolean match = cursor.stream().noneMatch(t -> t.asLong() == 100L); + assertThat(match).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void allMatchStream(ArangoDatabase db) { + final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", JsonNode.class); + final boolean match = cursor.stream().allMatch(t -> t.asLong() < 100L); + assertThat(match).isTrue(); + } + +} diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/driver/src/test/java/com/arangodb/ArangoDBTest.java similarity index 77% rename from src/test/java/com/arangodb/ArangoDBTest.java rename to driver/src/test/java/com/arangodb/ArangoDBTest.java index eadb0806c..5bd5e613e 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/driver/src/test/java/com/arangodb/ArangoDBTest.java @@ -20,15 +20,14 @@ package com.arangodb; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.*; -import com.arangodb.mapping.ArangoJack; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; import com.arangodb.model.LogOptions.SortOrder; +import com.arangodb.util.RawJson; import com.arangodb.util.TestUtils; -import com.arangodb.velocypack.exception.VPackException; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; -import com.arangodb.velocystream.Response; +import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; @@ -36,14 +35,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; @@ -106,7 +98,8 @@ void getVersion(ArangoDB arangoDB) { @ParameterizedTest(name = "{index}") @MethodSource("arangos") void createAndDeleteDatabase(ArangoDB arangoDB) { - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, supportsExtendedNames(arangoDB))); + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, + supportsExtendedNames(arangoDB))); final Boolean resultCreate; resultCreate = arangoDB.createDatabase(dbName); assertThat(resultCreate).isTrue(); @@ -135,7 +128,8 @@ void createWithNotNormalizedName(ArangoDB arangoDB) { void createDatabaseWithOptions(ArangoDB arangoDB) { assumeTrue(isCluster()); assumeTrue(isAtLeastVersion(3, 6)); - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, supportsExtendedNames(arangoDB))); + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, + supportsExtendedNames(arangoDB))); final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() .name(dbName) .options(new DatabaseOptions() @@ -147,10 +141,9 @@ void createDatabaseWithOptions(ArangoDB arangoDB) { assertThat(resultCreate).isTrue(); DatabaseEntity info = arangoDB.db(dbName).getInfo(); - assertThat(info.getReplicationFactor()).isEqualTo(2); + assertThat(info.getReplicationFactor().getValue()).isEqualTo(2); assertThat(info.getWriteConcern()).isEqualTo(2); assertThat(info.getSharding()).isEmpty(); - assertThat(info.getSatellite()).isNull(); final Boolean resultDelete = arangoDB.db(dbName).drop(); assertThat(resultDelete).isTrue(); @@ -163,20 +156,20 @@ void createDatabaseWithOptionsSatellite(ArangoDB arangoDB) { assumeTrue(isEnterprise()); assumeTrue(isAtLeastVersion(3, 6)); - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, supportsExtendedNames(arangoDB))); + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, + supportsExtendedNames(arangoDB))); final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() .name(dbName) .options(new DatabaseOptions() .writeConcern(2) - .satellite(true) + .replicationFactor(ReplicationFactor.ofSatellite()) .sharding("") ) ); assertThat(resultCreate).isTrue(); DatabaseEntity info = arangoDB.db(dbName).getInfo(); - assertThat(info.getReplicationFactor()).isNull(); - assertThat(info.getSatellite()).isTrue(); + assertThat(info.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); assertThat(info.getWriteConcern()).isEqualTo(2); assertThat(info.getSharding()).isEmpty(); @@ -187,7 +180,8 @@ void createDatabaseWithOptionsSatellite(ArangoDB arangoDB) { @ParameterizedTest(name = "{index}") @MethodSource("arangos") void createDatabaseWithUsers(ArangoDB arangoDB) throws InterruptedException { - final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, supportsExtendedNames(arangoDB))); + final DbName dbName = DbName.of("testDB-" + TestUtils.generateRandomDbName(20, + supportsExtendedNames(arangoDB))); final Map extra = Collections.singletonMap("key", "value"); final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() .name(dbName) @@ -213,10 +207,10 @@ void createDatabaseWithUsers(ArangoDB arangoDB) throws InterruptedException { assertThat(retrievedUser.getExtra()).isEqualTo(extra); // needed for active-failover tests only - Thread.sleep(1_000); + Thread.sleep(2_000); ArangoDB arangoDBTestUser = new ArangoDB.Builder() - .serializer(new ArangoJack()) + .loadProperties(config) .user("testUser") .password("testPasswd") .build(); @@ -378,7 +372,9 @@ void updateUserDefaultCollectionAccess(ArangoDB arangoDB) { @Test void authenticationFailPassword() { - final ArangoDB arangoDB = new ArangoDB.Builder().password("no").jwt(null).serializer(new ArangoJack()).build(); + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(config) + .password("no").jwt(null).build(); Throwable thrown = catchThrowable(arangoDB::getVersion); assertThat(thrown).isInstanceOf(ArangoDBException.class); assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(401); @@ -387,7 +383,9 @@ void authenticationFailPassword() { @ParameterizedTest(name = "{index}") @MethodSource("arangos") void authenticationFailUser() { - final ArangoDB arangoDB = new ArangoDB.Builder().user("no").jwt(null).serializer(new ArangoJack()).build(); + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(config) + .user("no").jwt(null).build(); Throwable thrown = catchThrowable(arangoDB::getVersion); assertThat(thrown).isInstanceOf(ArangoDBException.class); assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(401); @@ -395,107 +393,21 @@ void authenticationFailUser() { @ParameterizedTest(name = "{index}") @MethodSource("arangos") - void execute(ArangoDB arangoDB) throws VPackException { - final Response response = arangoDB.execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")); - assertThat(response.getBody().get("version").isString()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogs(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null); - assertThat(logs.getTotalAmount()).isPositive(); - assertThat(logs.getLid()).hasSize(logs.getTotalAmount().intValue()); - assertThat(logs.getLevel()).hasSize(logs.getTotalAmount().intValue()); - assertThat(logs.getTimestamp()).hasSize(logs.getTotalAmount().intValue()); - assertThat(logs.getText()).hasSize(logs.getTotalAmount().intValue()); - } - - @Disabled - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsUpto(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logsUpto = arangoDB.getLogs(new LogOptions().upto(LogLevel.WARNING)); - assertThat(logsUpto.getLevel()) - .isNotEmpty() - .doesNotContain(LogLevel.INFO); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsLevel(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logsInfo = arangoDB.getLogs(new LogOptions().level(LogLevel.INFO)); - assertThat(logsInfo.getLevel()).containsOnly(LogLevel.INFO); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsStart(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null); - assertThat(logs.getLid()).isNotEmpty(); - final LogEntity logsStart = arangoDB.getLogs(new LogOptions().start(logs.getLid().get(0) + 1)); - assertThat(logsStart.getLid()) - .isNotEmpty() - .doesNotContain(logs.getLid().get(0)); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsSize(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null); - assertThat(logs.getLid()).isNotEmpty(); - final LogEntity logsSize = arangoDB.getLogs(new LogOptions().size(logs.getLid().size() - 1)); - assertThat(logsSize.getLid()).hasSize(logs.getLid().size() - 1); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsOffset(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - assumeTrue(isLessThanVersion(3, 9)); // deprecated - final LogEntity logs = arangoDB.getLogs(null); - assertThat(logs.getTotalAmount()).isPositive(); - final LogEntity logsOffset = arangoDB.getLogs(new LogOptions().offset(1)); - assertThat(logsOffset.getLid()) - .isNotEmpty() - .doesNotContain(logs.getLid().get(0)); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsSearch(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null); - final LogEntity logsSearch = arangoDB.getLogs(new LogOptions().search(TEST_DB.get())); - assertThat(logs.getTotalAmount()).isGreaterThan(logsSearch.getTotalAmount()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsSortAsc(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(new LogOptions().sort(SortOrder.asc)); - long lastId = -1; - for (final Long id : logs.getLid()) { - assertThat(id).isGreaterThan(lastId); - lastId = id; - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("arangos") - void getLogsSortDesc(ArangoDB arangoDB) { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(new LogOptions().sort(SortOrder.desc)); - long lastId = Long.MAX_VALUE; - for (final Long id : logs.getLid()) { - assertThat(lastId).isGreaterThan(id); - lastId = id; + void executeGetVersion(ArangoDB arangoDB) { + Request request = Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.GET) + .path("/_api/version") + .queryParam("details", "true") + .build(); + final Response response = arangoDB.execute(request, RawJson.class); + JsonNode body = SerdeUtils.INSTANCE.parseJson(response.getBody().getValue()); + assertThat(body.get("version").isTextual()).isTrue(); + assertThat(body.get("details").isObject()).isTrue(); + assertThat(response.getResponseCode()).isEqualTo(200); + if (isAtLeastVersion(3, 9)) { + String header = response.getHeaders().get("x-arango-queue-time-seconds"); + assertThat(header).isNotNull(); } } @@ -644,6 +556,25 @@ void setAllLogLevel(ArangoDB arangoDB) { } } + @ParameterizedTest(name = "{index}") + @MethodSource("arangos") + void getQueryOptimizerRules(ArangoDB arangoDB) { + assumeTrue(isAtLeastVersion(3, 10)); + final Collection rules = arangoDB.getQueryOptimizerRules(); + assertThat(rules).isNotEmpty(); + for (QueryOptimizerRule rule : rules) { + assertThat(rule).isNotNull(); + assertThat(rule.getName()).isNotNull(); + QueryOptimizerRule.Flags flags = rule.getFlags(); + assertThat(flags.getHidden()).isNotNull(); + assertThat(flags.getClusterOnly()).isNotNull(); + assertThat(flags.getCanBeDisabled()).isNotNull(); + assertThat(flags.getCanCreateAdditionalPlans()).isNotNull(); + assertThat(flags.getDisabledByDefault()).isNotNull(); + assertThat(flags.getEnterpriseOnly()).isNotNull(); + } + } + @ParameterizedTest(name = "{index}") @MethodSource("arangos") void arangoDBException(ArangoDB arangoDB) { @@ -657,7 +588,9 @@ void arangoDBException(ArangoDB arangoDB) { @ParameterizedTest(name = "{index}") @MethodSource("arangos") void fallbackHost() { - final ArangoDB arangoDB = new ArangoDB.Builder().host("not-accessible", 8529).host("127.0.0.1", 8529).serializer(new ArangoJack()).build(); + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(config) + .host("not-accessible", 8529).host("127.0.0.1", 8529).build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); } @@ -665,19 +598,20 @@ void fallbackHost() { @ParameterizedTest(name = "{index}") @MethodSource("arangos") void loadproperties() { - Throwable thrown = catchThrowable(() -> - new ArangoDB.Builder().loadProperties(ArangoDBTest.class.getResourceAsStream("/arangodb-bad.properties")) + Throwable thrown = catchThrowable(() -> new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig("arangodb-bad.properties")) ); - assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown).isInstanceOf(IllegalArgumentException.class); } @ParameterizedTest(name = "{index}") @MethodSource("arangos") - void loadproperties2() { - Throwable thrown = catchThrowable(() -> - new ArangoDB.Builder().loadProperties(ArangoDBTest.class.getResourceAsStream("/arangodb-bad2.properties")) - ); - assertThat(thrown).isInstanceOf(ArangoDBException.class); + void loadpropertiesWithPrefix() { + ArangoDB adb = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig("arangodb-with-prefix.properties", "adb")) + .build(); + adb.getVersion(); + adb.shutdown(); } @ParameterizedTest(name = "{index}") @@ -691,6 +625,7 @@ void accessMultipleDatabases(ArangoDB arangoDB) { @ParameterizedTest(name = "{index}") @MethodSource("arangos") + @Disabled("Manual execution only") void queueTime(ArangoDB arangoDB) throws InterruptedException, ExecutionException { List> futures = IntStream.range(0, 80) .mapToObj(i -> CompletableFuture.runAsync( @@ -721,7 +656,7 @@ void queueTime(ArangoDB arangoDB) throws InterruptedException, ExecutionExceptio System.err.println(v.value); } } - assertThat(avg).isPositive(); + assertThat(avg).isNotNegative(); } else { assertThat(avg).isEqualTo(0.0); assertThat(values).isEmpty(); diff --git a/src/test/java/com/arangodb/ArangoDatabaseTest.java b/driver/src/test/java/com/arangodb/ArangoDatabaseTest.java similarity index 85% rename from src/test/java/com/arangodb/ArangoDatabaseTest.java rename to driver/src/test/java/com/arangodb/ArangoDatabaseTest.java index 4d6c5b10d..504679120 100644 --- a/src/test/java/com/arangodb/ArangoDatabaseTest.java +++ b/driver/src/test/java/com/arangodb/ArangoDatabaseTest.java @@ -22,15 +22,15 @@ import com.arangodb.entity.*; import com.arangodb.entity.AqlExecutionExplainEntity.ExecutionPlan; -import com.arangodb.entity.CursorEntity.Warning; import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; import com.arangodb.model.*; -import com.arangodb.model.TraversalOptions.Direction; import com.arangodb.util.MapBuilder; -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.ValueType; -import com.arangodb.velocypack.exception.VPackException; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -116,8 +116,7 @@ void createCollectionWithReplicationFactor(ArangoDatabase db) { assertThat(result).isNotNull(); assertThat(result.getId()).isNotNull(); CollectionPropertiesEntity props = db.collection(name).getProperties(); - assertThat(props.getReplicationFactor()).isEqualTo(2); - assertThat(props.getSatellite()).isNull(); + assertThat(props.getReplicationFactor().getValue()).isEqualTo(2); } @ParameterizedTest(name = "{index}") @@ -132,9 +131,8 @@ void createCollectionWithWriteConcern(ArangoDatabase db) { assertThat(result).isNotNull(); assertThat(result.getId()).isNotNull(); CollectionPropertiesEntity props = db.collection(name).getProperties(); - assertThat(props.getReplicationFactor()).isEqualTo(2); + assertThat(props.getReplicationFactor().getValue()).isEqualTo(2); assertThat(props.getWriteConcern()).isEqualTo(2); - assertThat(props.getSatellite()).isNull(); } @ParameterizedTest(name = "{index}") @@ -145,13 +143,12 @@ void createSatelliteCollection(ArangoDatabase db) { String name = "collection-" + rnd(); final CollectionEntity result = db - .createCollection(name, new CollectionCreateOptions().satellite(true)); + .createCollection(name, new CollectionCreateOptions().replicationFactor(ReplicationFactor.ofSatellite())); assertThat(result).isNotNull(); assertThat(result.getId()).isNotNull(); CollectionPropertiesEntity props = db.collection(name).getProperties(); - assertThat(props.getReplicationFactor()).isNull(); - assertThat(props.getSatellite()).isTrue(); + assertThat(props.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); } @ParameterizedTest(name = "{index}") @@ -212,10 +209,7 @@ void createCollectionWithSmartJoinAttributeWrong(ArangoDatabase db) { db.createCollection(name, new CollectionCreateOptions().smartJoinAttribute("test123")); } catch (ArangoDBException e) { assertThat(e.getErrorNum()).isEqualTo(4006); - // TODO: - // at the moment older server versions reply with response code 500, which is a misbehavior - // when the fix has been backported to all the supported db versions uncomment the following: - // assertThat(e.getResponseCode()).isEqualTo(400)); + assertThat(e.getResponseCode()).isEqualTo(400); } } @@ -336,11 +330,11 @@ void createCollectionWithJsonSchema(ArangoDatabase db) { assertThat(props.getSchema().getRule()).isEqualTo(rule); assertThat(props.getSchema().getMessage()).isEqualTo(message); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("number", 33); db.collection(name).insertDocument(doc); - BaseDocument wrongDoc = new BaseDocument(); + BaseDocument wrongDoc = new BaseDocument(UUID.randomUUID().toString()); wrongDoc.addAttribute("number", "notANumber"); Throwable thrown = catchThrowable(() -> db.collection(name).insertDocument(wrongDoc)); assertThat(thrown).isInstanceOf(ArangoDBException.class); @@ -351,6 +345,42 @@ void createCollectionWithJsonSchema(ArangoDatabase db) { assertThat(e.getErrorNum()).isEqualTo(1620); } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createCollectionWithComputedFields(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String cName = "collection-" + rnd(); + ComputedValue cv = new ComputedValue() + .name("foo") + .expression("RETURN 11") + .overwrite(false) + .computeOn(ComputedValue.ComputeOn.insert) + .keepNull(false) + .failOnWarning(true); + + final CollectionEntity result = db.createCollection(cName, new CollectionCreateOptions().computedValues(cv)); + + assertThat(result).isNotNull(); + assertThat(result.getComputedValues()) + .hasSize(1) + .contains(cv); + + ComputedValue cv2 = new ComputedValue() + .name("bar") + .expression("RETURN 22") + .overwrite(true) + .computeOn(ComputedValue.ComputeOn.update, ComputedValue.ComputeOn.replace) + .keepNull(true) + .failOnWarning(false); + + db.collection(cName).changeProperties(new CollectionPropertiesOptions().computedValues(cv2)); + + CollectionPropertiesEntity props = db.collection(cName).getProperties(); + assertThat(props.getComputedValues()) + .hasSize(1) + .contains(cv2); + } + @ParameterizedTest(name = "{index}") @MethodSource("dbs") void deleteCollection(ArangoDatabase db) { @@ -539,6 +569,15 @@ void query(ArangoDatabase db) { } } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithNullBindVar(ArangoDatabase db) { + final ArangoCursor cursor = db.query("return @foo", Collections.singletonMap("foo", null), null, + Object.class); + assertThat(cursor.hasNext()).isTrue(); + assertThat(cursor.next()).isNull(); + } + @ParameterizedTest(name = "{index}") @MethodSource("dbs") void queryForEach(ArangoDatabase db) { @@ -588,7 +627,8 @@ void queryWithLimitAndFullCount(ArangoDatabase db) { assertThat((Iterator) cursor).hasNext(); } assertThat(cursor.getStats()).isNotNull(); - assertThat(cursor.getStats().getFullCount()).isGreaterThanOrEqualTo(10L); + assertThat(((Number) cursor.getStats().get("executionTime")).doubleValue()).isPositive(); + assertThat((cursor.getStats().getFullCount())).isGreaterThanOrEqualTo(10); } @ParameterizedTest(name = "{index}") @@ -627,41 +667,34 @@ void queryIterateWithBatchSize(ArangoDatabase db) { assertThat(i.get()).isGreaterThanOrEqualTo(10); } - // FIXME -// /** -// * ignored. takes to long -// */ -// @Test -// @Ignore -// void queryWithTTL() throws InterruptedException { -// // set TTL to 1 seconds and get the second batch after 2 seconds! -// final int ttl = 1; -// final int wait = 2; -// try { -// db.createCollection(COLLECTION_NAME, null); -// for (int i = 0; i < 10; i++) { -// db.collection(COLLECTION_NAME).insertDocument(new BaseDocument(), null); -// } -// -// final ArangoCursor cursor = db -// .query("for i in db_test return i._id", null, new AqlQueryOptions().batchSize(5).ttl(ttl), -// String.class); -// -// assertThat(cursor).isNotNull(); -// -// for (int i = 0; i < 10; i++, cursor.next()) { -// assertThat(cursor.hasNext()).isEqualTo(true)); -// if (i == 1) { -// Thread.sleep(wait * 1000); -// } -// } -// fail("this should fail"); -// } catch (final ArangoDBException ex) { -// assertThat(ex.getMessage()).isEqualTo("Response: 404, Error: 1600 - cursor not found")); -// } finally { -// db.collection(COLLECTION_NAME).drop(); -// } -// } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithTTL(ArangoDatabase db) throws InterruptedException { + // set TTL to 1 seconds and get the second batch after 2 seconds! + final int ttl = 1; + final int wait = 2; + for (int i = 0; i < 10; i++) { + db.collection(CNAME1).insertDocument(new BaseDocument(), null); + } + + final ArangoCursor cursor = db + .query("for i in " + CNAME1 + " return i._id", null, new AqlQueryOptions().batchSize(5).ttl(ttl), + String.class); + + assertThat((Iterable) cursor).isNotNull(); + + try { + for (int i = 0; i < 10; i++, cursor.next()) { + assertThat(cursor.hasNext()).isTrue(); + if (i == 1) { + Thread.sleep(wait * 1000); + } + } + fail("this should fail"); + } catch (final ArangoDBException ex) { + assertThat(ex.getMessage()).isEqualTo("Response: 404, Error: 1600 - cursor not found"); + } + } @ParameterizedTest(name = "{index}") @MethodSource("dbs") @@ -718,7 +751,8 @@ void queryWithCache(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void queryWithMemoryLimit(ArangoDatabase db) { - Throwable thrown = catchThrowable(() -> db.query("RETURN 1..100000", null, new AqlQueryOptions().memoryLimit(32 * 1024L), String.class)); + Throwable thrown = catchThrowable(() -> db.query("RETURN 1..100000", null, + new AqlQueryOptions().memoryLimit(32 * 1024L), String.class)); assertThat(thrown).isInstanceOf(ArangoDBException.class); assertThat(((ArangoDBException) thrown).getErrorNum()).isEqualTo(32); } @@ -726,7 +760,8 @@ void queryWithMemoryLimit(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void queryWithFailOnWarningTrue(ArangoDatabase db) { - Throwable thrown = catchThrowable(() -> db.query("RETURN 1 / 0", null, new AqlQueryOptions().failOnWarning(true), String.class)); + Throwable thrown = catchThrowable(() -> db.query("RETURN 1 / 0", null, + new AqlQueryOptions().failOnWarning(true), String.class)); assertThat(thrown).isInstanceOf(ArangoDBException.class); } @@ -742,7 +777,8 @@ void queryWithFailOnWarningFalse(ArangoDatabase db) { @MethodSource("dbs") void queryWithTimeout(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 6)); - Throwable thrown = catchThrowable(() -> db.query("RETURN SLEEP(1)", null, new AqlQueryOptions().maxRuntime(0.1), String.class).next()); + Throwable thrown = catchThrowable(() -> db.query("RETURN SLEEP(1)", null, + new AqlQueryOptions().maxRuntime(0.1), String.class).next()); assertThat(thrown).isInstanceOf(ArangoDBException.class); assertThat(((ArangoDBException) thrown).getResponseCode()).isEqualTo(410); } @@ -755,7 +791,7 @@ void queryWithMaxWarningCount(ArangoDatabase db) { assertThat(cursorWithWarnings.getWarnings()).hasSize(1); final ArangoCursor cursorWithLimitedWarnings = db .query("RETURN 1 / 0", null, new AqlQueryOptions().maxWarningCount(0L), String.class); - final Collection warnings = cursorWithLimitedWarnings.getWarnings(); + final Collection warnings = cursorWithLimitedWarnings.getWarnings(); assertThat(warnings).isNullOrEmpty(); } @@ -811,7 +847,7 @@ void changeQueryTrackingProperties(ArangoDatabase db) { @MethodSource("dbs") void queryWithBindVars(ArangoDatabase db) { for (int i = 0; i < 10; i++) { - final BaseDocument baseDocument = new BaseDocument(); + final BaseDocument baseDocument = new BaseDocument(UUID.randomUUID().toString()); baseDocument.addAttribute("age", 20 + i); db.collection(CNAME1).insertDocument(baseDocument, null); } @@ -830,6 +866,19 @@ void queryWithBindVars(ArangoDatabase db) { } } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void queryWithRawBindVars(ArangoDatabase db) { + final Map bindVars = new HashMap<>(); + bindVars.put("foo", RawJson.of("\"fooValue\"")); + bindVars.put("bar", RawBytes.of(db.getSerde().serializeUserData(11))); + + final JsonNode res = db.query("RETURN {foo: @foo, bar: @bar}", bindVars, null, JsonNode.class).next(); + + assertThat(res.get("foo").textValue()).isEqualTo("fooValue"); + assertThat(res.get("bar").intValue()).isEqualTo(11); + } + @ParameterizedTest(name = "{index}") @MethodSource("arangos") void queryWithWarning(ArangoDB arangoDB) { @@ -843,9 +892,9 @@ void queryWithWarning(ArangoDB arangoDB) { @MethodSource("dbs") void queryStream(ArangoDatabase db) { if (isAtLeastVersion(3, 4)) { - final ArangoCursor cursor = db + final ArangoCursor cursor = db .query("FOR i IN 1..2 RETURN i", null, new AqlQueryOptions().stream(true).count(true), - VPackSlice.class); + Void.class); assertThat((Object) cursor).isNotNull(); assertThat(cursor.getCount()).isNull(); } @@ -892,6 +941,9 @@ void queryAllowDirtyRead(ArangoDatabase db) throws IOException { final ArangoCursor cursor = db.query("FOR i IN @@col FILTER i.test == @test RETURN i", new MapBuilder().put("@col", CNAME1).put("test", null).get(), new AqlQueryOptions().allowDirtyRead(true), BaseDocument.class); + if (isAtLeastVersion(3, 10)) { + assertThat(cursor.isPotentialDirtyRead()).isTrue(); + } cursor.close(); } @@ -910,6 +962,22 @@ void explainQuery(ArangoDatabase db) { assertThat(plan.getNodes()).isNotEmpty(); } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void explainQueryWithBindVars(ArangoDatabase db) { + final AqlExecutionExplainEntity explain = db.explainQuery("for i in 1..1 return @value", + Collections.singletonMap("value", 11), null); + assertThat(explain).isNotNull(); + assertThat(explain.getPlan()).isNotNull(); + assertThat(explain.getPlans()).isNull(); + final ExecutionPlan plan = explain.getPlan(); + assertThat(plan.getCollections()).isEmpty(); + assertThat(plan.getEstimatedCost()).isPositive(); + assertThat(plan.getEstimatedNrItems()).isPositive(); + assertThat(plan.getVariables()).hasSize(3); + assertThat(plan.getNodes()).isNotEmpty(); + } + @ParameterizedTest(name = "{index}") @MethodSource("dbs") void explainQueryWithIndexNode(ArangoDatabase db) { @@ -1080,14 +1148,14 @@ void createGraphSatellite(ArangoDatabase db) { assumeTrue(isEnterprise()); String name = "graph-" + rnd(); - final GraphEntity result = db.createGraph(name, null, new GraphCreateOptions().satellite(true)); - assertThat(result.getSatellite()).isTrue(); + final GraphEntity result = db.createGraph(name, null, new GraphCreateOptions().replicationFactor(ReplicationFactor.ofSatellite())); + assertThat(result.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); GraphEntity info = db.graph(name).getInfo(); - assertThat(info.getSatellite()).isTrue(); + assertThat(info.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); GraphEntity graph = db.getGraphs().stream().filter(g -> name.equals(g.getName())).findFirst().get(); - assertThat(graph.getSatellite()).isTrue(); + assertThat(graph.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); } @ParameterizedTest(name = "{index}") @@ -1098,12 +1166,13 @@ void createGraphReplicationFaktor(ArangoDatabase db) { final String edgeCollection = "edge-" + rnd(); final String fromCollection = "from-" + rnd(); final String toCollection = "to-" + rnd(); - final Collection edgeDefinitions = Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection)); + final Collection edgeDefinitions = + Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection)); final GraphEntity result = db.createGraph(name, edgeDefinitions, new GraphCreateOptions().replicationFactor(2)); assertThat(result).isNotNull(); for (final String collection : Arrays.asList(edgeCollection, fromCollection, toCollection)) { final CollectionPropertiesEntity properties = db.collection(collection).getProperties(); - assertThat(properties.getReplicationFactor()).isEqualTo(2); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(2); } } @@ -1115,7 +1184,8 @@ void createGraphNumberOfShards(ArangoDatabase db) { final String edgeCollection = "edge-" + rnd(); final String fromCollection = "from-" + rnd(); final String toCollection = "to-" + rnd(); - final Collection edgeDefinitions = Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection)); + final Collection edgeDefinitions = + Collections.singletonList(new EdgeDefinition().collection(edgeCollection).from(fromCollection).to(toCollection)); final GraphEntity result = db .createGraph(name, edgeDefinitions, new GraphCreateOptions().numberOfShards(2)); assertThat(result).isNotNull(); @@ -1140,8 +1210,8 @@ void getGraphs(ArangoDatabase db) { @MethodSource("dbs") void transactionString(ArangoDatabase db) { final TransactionOptions options = new TransactionOptions().params("test"); - final String result = db.transaction("function (params) {return params;}", String.class, options); - assertThat(result).isEqualTo("test"); + final RawJson result = db.transaction("function (params) {return params;}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"test\""); } @ParameterizedTest(name = "{index}") @@ -1154,32 +1224,32 @@ void transactionNumber(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void transactionVPack(ArangoDatabase db) throws VPackException { - final TransactionOptions options = new TransactionOptions().params(new VPackBuilder().add("test").slice()); - final VPackSlice result = db.transaction("function (params) {return params;}", VPackSlice.class, options); - assertThat(result.isString()).isTrue(); - assertThat(result.getAsString()).isEqualTo("test"); + void transactionJsonNode(ArangoDatabase db) { + final TransactionOptions options = new TransactionOptions().params(JsonNodeFactory.instance.textNode("test")); + final JsonNode result = db.transaction("function (params) {return params;}", JsonNode.class, options); + assertThat(result.isTextual()).isTrue(); + assertThat(result.asText()).isEqualTo("test"); } @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void transactionVPackObject(ArangoDatabase db) throws VPackException { - final VPackSlice params = new VPackBuilder().add(ValueType.OBJECT).add("foo", "hello").add("bar", "world") - .close().slice(); + void transactionJsonObject(ArangoDatabase db) { + ObjectNode params = JsonNodeFactory.instance.objectNode().put("foo", "hello").put("bar", "world"); final TransactionOptions options = new TransactionOptions().params(params); - final String result = db - .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", String.class, options); - assertThat(result).isEqualTo("hello world"); + final RawJson result = db + .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", RawJson.class, + options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void transactionVPackArray(ArangoDatabase db) throws VPackException { - final VPackSlice params = new VPackBuilder().add(ValueType.ARRAY).add("hello").add("world").close().slice(); + void transactionJsonArray(ArangoDatabase db) { + ArrayNode params = JsonNodeFactory.instance.arrayNode().add("hello").add("world"); final TransactionOptions options = new TransactionOptions().params(params); - final String result = db - .transaction("function (params) { return params[0] + ' ' + params[1];}", String.class, options); - assertThat(result).isEqualTo("hello world"); + final RawJson result = db + .transaction("function (params) { return params[0] + ' ' + params[1];}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @@ -1187,9 +1257,10 @@ void transactionVPackArray(ArangoDatabase db) throws VPackException { void transactionMap(ArangoDatabase db) { final Map params = new MapBuilder().put("foo", "hello").put("bar", "world").get(); final TransactionOptions options = new TransactionOptions().params(params); - final String result = db - .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", String.class, options); - assertThat(result).isEqualTo("hello world"); + final RawJson result = db + .transaction("function (params) { return params['foo'] + ' ' + params['bar'];}", RawJson.class, + options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @@ -1197,9 +1268,9 @@ void transactionMap(ArangoDatabase db) { void transactionArray(ArangoDatabase db) { final String[] params = new String[]{"hello", "world"}; final TransactionOptions options = new TransactionOptions().params(params); - final String result = db - .transaction("function (params) { return params[0] + ' ' + params[1];}", String.class, options); - assertThat(result).isEqualTo("hello world"); + final RawJson result = db + .transaction("function (params) { return params[0] + ' ' + params[1];}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @@ -1209,9 +1280,9 @@ void transactionCollection(ArangoDatabase db) { params.add("hello"); params.add("world"); final TransactionOptions options = new TransactionOptions().params(params); - final String result = db - .transaction("function (params) { return params[0] + ' ' + params[1];}", String.class, options); - assertThat(result).isEqualTo("hello world"); + final RawJson result = db + .transaction("function (params) { return params[0] + ' ' + params[1];}", RawJson.class, options); + assertThat(result.getValue()).isEqualTo("\"hello world\""); } @ParameterizedTest(name = "{index}") @@ -1224,7 +1295,7 @@ void transactionInsertJson(ArangoDatabase db) { + "var db = require('internal').db;" + "db." + CNAME1 + ".save(JSON.parse(params));" + "}", Void.class, options); - assertThat(db.collection(CNAME1).getDocument(key, String.class)).isNotNull(); + assertThat(db.collection(CNAME1).getDocument(key, RawJson.class)).isNotNull(); } @ParameterizedTest(name = "{index}") @@ -1238,13 +1309,13 @@ void transactionExclusiveWrite(ArangoDatabase db) { + "var db = require('internal').db;" + "db." + CNAME1 + ".save(JSON.parse(params));" + "}", Void.class, options); - assertThat(db.collection(CNAME1).getDocument(key, String.class)).isNotNull(); + assertThat(db.collection(CNAME1).getDocument(key, RawJson.class)).isNotNull(); } @ParameterizedTest(name = "{index}") @MethodSource("dbs") void transactionEmpty(ArangoDatabase db) { - db.transaction("function () {}", null, null); + db.transaction("function () {}", Void.class, null); } @ParameterizedTest(name = "{index}") @@ -1254,23 +1325,15 @@ void transactionAllowImplicit(ArangoDatabase db) { + "return {'a':db." + CNAME1 + ".all().toArray()[0], 'b':db." + CNAME2 + ".all().toArray()[0]};" + "}"; final TransactionOptions options = new TransactionOptions().readCollections(CNAME1); - db.transaction(action, VPackSlice.class, options); + db.transaction(action, JsonNode.class, options); options.allowImplicit(false); - Throwable thrown = catchThrowable(() -> db.transaction(action, VPackSlice.class, options)); + Throwable thrown = catchThrowable(() -> db.transaction(action, JsonNode.class, options)); assertThat(thrown) .isInstanceOf(ArangoDBException.class) .extracting(it -> ((ArangoDBException) it).getResponseCode()) .isEqualTo(400); } - static class TransactionTestEntity { - private String value; - - TransactionTestEntity() { - super(); - } - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void transactionPojoReturn(ArangoDatabase db) { @@ -1297,52 +1360,6 @@ void getInfo(ArangoDatabase db) { } } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void executeTraversal(ArangoDatabase db) { - String k1 = "key-" + rnd(); - String k2 = "key-" + rnd(); - String k3 = "key-" + rnd(); - String k4 = "key-" + rnd(); - String k5 = "key-" + rnd(); - - for (final String e : new String[]{ - k1, k2, k3, k4, k5 - }) { - db.collection(CNAME1).insertDocument(new BaseDocument(e), null); - } - for (final String[] e : new String[][]{ - new String[]{k1, k2}, new String[]{k2, k3}, - new String[]{k2, k4}, new String[]{k5, k1}, new String[]{k5, k2} - }) { - final BaseEdgeDocument edge = new BaseEdgeDocument(); - edge.setKey(e[0] + "_knows_" + e[1]); - edge.setFrom(CNAME1 + "/" + e[0]); - edge.setTo(CNAME1 + "/" + e[1]); - db.collection(ENAMES).insertDocument(edge, null); - } - - final TraversalOptions options = new TraversalOptions().edgeCollection(ENAMES).startVertex(CNAME1 + "/" + k1).direction(Direction.outbound); - final TraversalEntity traversal = db.executeTraversal(BaseDocument.class, BaseEdgeDocument.class, options); - assertThat(traversal).isNotNull(); - - final Collection vertices = traversal.getVertices(); - assertThat(vertices).hasSize(4); - - final Iterator verticesIterator = vertices.iterator(); - final Collection v = Arrays.asList(k1, k2, k3, k4); - while (verticesIterator.hasNext()) { - assertThat(v).contains(verticesIterator.next().getKey()); - } - - final Collection> paths = traversal.getPaths(); - assertThat(paths).hasSize(4); - final PathEntity first = paths.iterator().next(); - assertThat(first.getEdges()).isEmpty(); - assertThat(first.getVertices()).hasSize(1); - assertThat(first.getVertices().iterator().next().getKey()).isEqualTo(k1); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void getDocument(ArangoDatabase db) { @@ -1362,7 +1379,7 @@ void shouldIncludeExceptionMessage(ArangoDatabase db) { final String exceptionMessage = "My error context"; final String action = "function (params) {" + "throw '" + exceptionMessage + "';" + "}"; try { - db.transaction(action, VPackSlice.class, null); + db.transaction(action, Void.class, null); fail(); } catch (final ArangoDBException e) { assertThat(e.getErrorMessage()).isEqualTo(exceptionMessage); @@ -1381,4 +1398,16 @@ void getDocumentWrongId(ArangoDatabase db) { void reloadRouting(ArangoDatabase db) { db.reloadRouting(); } + + public static class TransactionTestEntity { + private String value; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } } diff --git a/src/test/java/com/arangodb/ArangoDocumentUtilTest.java b/driver/src/test/java/com/arangodb/ArangoDocumentUtilTest.java similarity index 100% rename from src/test/java/com/arangodb/ArangoDocumentUtilTest.java rename to driver/src/test/java/com/arangodb/ArangoDocumentUtilTest.java diff --git a/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java b/driver/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java similarity index 93% rename from src/test/java/com/arangodb/ArangoEdgeCollectionTest.java rename to driver/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java index 3baaab078..d25ed0e69 100644 --- a/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java +++ b/driver/src/test/java/com/arangodb/ArangoEdgeCollectionTest.java @@ -1,441 +1,445 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.*; -import com.arangodb.model.*; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Arrays; -import java.util.Collections; -import java.util.UUID; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoEdgeCollectionTest extends BaseJunit5 { - - private static final String GRAPH_NAME = "EdgeCollectionTest_graph"; - private static final String VERTEX_COLLECTION_NAME = "EdgeCollectionTest_vertex_collection"; - private static final String EDGE_COLLECTION_NAME = "EdgeCollectionTest_edge_collection"; - - private static Stream args() { - return dbsStream() - .map(db -> new Object[]{ - db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME), - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - }) - .map(Arguments::of); - } - - @BeforeAll - static void init() { - initCollections(VERTEX_COLLECTION_NAME); - initEdgeCollections(EDGE_COLLECTION_NAME); - initGraph( - GRAPH_NAME, - Collections.singletonList(new EdgeDefinition() - .collection(EDGE_COLLECTION_NAME) - .from(VERTEX_COLLECTION_NAME) - .to(VERTEX_COLLECTION_NAME) - ), - null - ); - } - - private BaseEdgeDocument createEdgeValue(ArangoVertexCollection vertices) { - final VertexEntity v1 = vertices.insertVertex(new BaseDocument()); - final VertexEntity v2 = vertices.insertVertex(new BaseDocument()); - - final BaseEdgeDocument value = new BaseEdgeDocument(); - value.setFrom(v1.getId()); - value.setTo(v2.getId()); - return value; - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void insertEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - assertThat(edge).isNotNull(); - final BaseEdgeDocument document = edges.getEdge(edge.getKey(), BaseEdgeDocument.class); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - assertThat(document.getFrom()).isNotNull(); - assertThat(document.getTo()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void insertEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - assertThat(value.getRevision()).isEqualTo(edge.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void insertEdgeViolatingUniqueConstraint(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - edges.graph().db().collection(EDGE_COLLECTION_NAME) - .ensurePersistentIndex(Arrays.asList("_from", "_to"), new PersistentIndexOptions().unique(true)); - - BaseEdgeDocument edge = createEdgeValue(vertices); - edges.insertEdge(edge); - - try { - edges.insertEdge(edge); - } catch (ArangoDBException e) { - assertThat(e.getResponseCode()).isEqualTo(409); - assertThat(e.getErrorNum()).isEqualTo(1210); - } - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final BaseEdgeDocument document = edges - .getEdge(edge.getKey(), BaseEdgeDocument.class); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - assertThat(document.getFrom()).isNotNull(); - assertThat(document.getTo()).isNotNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(edge.getRev()); - final BaseDocument document = edges.getEdge(edge.getKey(), - BaseDocument.class, options); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); - final BaseEdgeDocument edge2 = edges.getEdge(edge.getKey(), - BaseEdgeDocument.class, options); - assertThat(edge2).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdgeIfNoneMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); - final BaseDocument document = edges.getEdge(edge.getKey(), - BaseDocument.class, options); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(edge.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void getEdgeIfNoneMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final EdgeEntity edge = edges.insertEdge(value); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(edge.getRev()); - final BaseEdgeDocument edge2 = edges.getEdge(edge.getKey(), - BaseEdgeDocument.class, options); - assertThat(edge2).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void replaceEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.getProperties().clear(); - doc.addAttribute("b", "test"); - final EdgeUpdateEntity replaceResult = edges - .replaceEdge(createResult.getKey(), doc); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void replaceEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); - final EdgeUpdateEntity replaceResult = edges - .replaceEdge(createResult.getKey(), doc); - assertThat(doc.getRevision()).isEqualTo(replaceResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void replaceEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.getProperties().clear(); - doc.addAttribute("b", "test"); - final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch(createResult.getRev()); - final EdgeUpdateEntity replaceResult = edges - .replaceEdge(createResult.getKey(), doc, options); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void replaceEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.getProperties().clear(); - doc.addAttribute("b", "test"); - final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> edges.replaceEdge(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - // FIXME: atm the server replies 409 for HTTP_JSON or HTTP_VPACK - // assertThat(e.getResponseCode()).isEqualTo(412)); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc); - assertThat(doc.getRevision()).isEqualTo(updateResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch(createResult.getRev()); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> edges.updateEdge(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - // FIXME: atm the server replies 409 for HTTP_JSON or HTTP_VPACK - // assertThat(e.getResponseCode()).isEqualTo(412)); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeKeepNullTrue(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(true); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(1); - assertThat(readResult.getProperties()).containsKey("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void updateEdgeKeepNullFalse(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - doc.addAttribute("a", "test"); - final EdgeEntity createResult = edges.insertEdge(doc); - doc.updateAttribute("a", null); - final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(false); - final EdgeUpdateEntity updateResult = edges - .updateEdge(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseEdgeDocument readResult = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getRevision()).isNotNull(); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void deleteEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - edges.deleteEdge(createResult.getKey()); - final BaseEdgeDocument edge = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(edge).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void deleteEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch(createResult.getRev()); - edges.deleteEdge(createResult.getKey(), options); - final BaseEdgeDocument edge = edges - .getEdge(createResult.getKey(), BaseEdgeDocument.class); - assertThat(edge).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void deleteEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument doc = createEdgeValue(vertices); - final EdgeEntity createResult = edges.insertEdge(doc); - final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> edges.deleteEdge(createResult.getKey(), options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - // FIXME: atm the server replies 409 for HTTP_JSON or HTTP_VPACK - // assertThat(e.getResponseCode()).isEqualTo(412)); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("args") - void edgeKeyWithSpecialChars(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { - final BaseEdgeDocument value = createEdgeValue(vertices); - final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); - value.setKey(key); - final EdgeEntity edge = edges.insertEdge(value); - assertThat(edge).isNotNull(); - final BaseEdgeDocument document = edges.getEdge(edge.getKey(), BaseEdgeDocument.class); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(key); - assertThat(document.getFrom()).isNotNull(); - assertThat(document.getTo()).isNotNull(); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.*; +import com.arangodb.model.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Arrays; +import java.util.Collections; +import java.util.UUID; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoEdgeCollectionTest extends BaseJunit5 { + + private static final String GRAPH_NAME = "EdgeCollectionTest_graph"; + private static final String VERTEX_COLLECTION_NAME = "EdgeCollectionTest_vertex_collection"; + private static final String EDGE_COLLECTION_NAME = "EdgeCollectionTest_edge_collection"; + + private static Stream args() { + return dbsStream() + .map(db -> new Object[]{ + db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME), + db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + }) + .map(Arguments::of); + } + + @BeforeAll + static void init() { + initCollections(VERTEX_COLLECTION_NAME); + initEdgeCollections(EDGE_COLLECTION_NAME); + initGraph( + GRAPH_NAME, + Collections.singletonList(new EdgeDefinition() + .collection(EDGE_COLLECTION_NAME) + .from(VERTEX_COLLECTION_NAME) + .to(VERTEX_COLLECTION_NAME) + ), + null + ); + } + + private BaseEdgeDocument createEdgeValue(ArangoVertexCollection vertices) { + final VertexEntity v1 = vertices.insertVertex(new BaseDocument()); + final VertexEntity v2 = vertices.insertVertex(new BaseDocument()); + + final BaseEdgeDocument value = new BaseEdgeDocument(); + value.setFrom(v1.getId()); + value.setTo(v2.getId()); + return value; + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void insertEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + assertThat(edge).isNotNull(); + final BaseEdgeDocument document = edges.getEdge(edge.getKey(), BaseEdgeDocument.class); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + assertThat(document.getFrom()).isNotNull(); + assertThat(document.getTo()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void insertEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + assertThat(value.getRevision()).isNull(); + assertThat(edge.getRev()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void insertEdgeViolatingUniqueConstraint(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + edges.graph().db().collection(EDGE_COLLECTION_NAME) + .ensurePersistentIndex(Arrays.asList("_from", "_to"), new PersistentIndexOptions().unique(true)); + + BaseEdgeDocument edge = createEdgeValue(vertices); + edges.insertEdge(edge); + + try { + edges.insertEdge(edge); + } catch (ArangoDBException e) { + assertThat(e.getResponseCode()).isEqualTo(409); + assertThat(e.getErrorNum()).isEqualTo(1210); + } + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final BaseEdgeDocument document = edges + .getEdge(edge.getKey(), BaseEdgeDocument.class); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + assertThat(document.getFrom()).isNotNull(); + assertThat(document.getTo()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(edge.getRev()); + final BaseDocument document = edges.getEdge(edge.getKey(), + BaseDocument.class, options); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); + final BaseEdgeDocument edge2 = edges.getEdge(edge.getKey(), + BaseEdgeDocument.class, options); + assertThat(edge2).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdgeIfNoneMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); + final BaseDocument document = edges.getEdge(edge.getKey(), + BaseDocument.class, options); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(edge.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void getEdgeIfNoneMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final EdgeEntity edge = edges.insertEdge(value); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(edge.getRev()); + final BaseEdgeDocument edge2 = edges.getEdge(edge.getKey(), + BaseEdgeDocument.class, options); + assertThat(edge2).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void replaceEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final EdgeUpdateEntity replaceResult = edges + .replaceEdge(createResult.getKey(), doc); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void replaceEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + final EdgeUpdateEntity replaceResult = edges + .replaceEdge(createResult.getKey(), doc); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(replaceResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void replaceEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch(createResult.getRev()); + final EdgeUpdateEntity replaceResult = edges + .replaceEdge(createResult.getKey(), doc, options); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void replaceEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> edges.replaceEdge(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeUpdateRev(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(updateResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch(createResult.getRev()); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> edges.updateEdge(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeKeepNullTrue(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(true); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getProperties().keySet()).hasSize(6); + assertThat(readResult.getProperties()).containsKey("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void updateEdgeKeepNullFalse(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + doc.addAttribute("a", "test"); + final EdgeEntity createResult = edges.insertEdge(doc); + doc.updateAttribute("a", null); + final EdgeUpdateOptions options = new EdgeUpdateOptions().keepNull(false); + final EdgeUpdateEntity updateResult = edges + .updateEdge(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseEdgeDocument readResult = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getRevision()).isNotNull(); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void deleteEdge(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + edges.deleteEdge(createResult.getKey()); + final BaseEdgeDocument edge = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(edge).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void deleteEdgeIfMatch(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch(createResult.getRev()); + edges.deleteEdge(createResult.getKey(), options); + final BaseEdgeDocument edge = edges + .getEdge(createResult.getKey(), BaseEdgeDocument.class); + assertThat(edge).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void deleteEdgeIfMatchFail(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument doc = createEdgeValue(vertices); + final EdgeEntity createResult = edges.insertEdge(doc); + final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> edges.deleteEdge(createResult.getKey(), options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("args") + void edgeKeyWithSpecialChars(ArangoVertexCollection vertices, ArangoEdgeCollection edges) { + final BaseEdgeDocument value = createEdgeValue(vertices); + final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); + value.setKey(key); + final EdgeEntity edge = edges.insertEdge(value); + assertThat(edge).isNotNull(); + final BaseEdgeDocument document = edges.getEdge(edge.getKey(), BaseEdgeDocument.class); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(key); + assertThat(document.getFrom()).isNotNull(); + assertThat(document.getTo()).isNotNull(); + } + +} diff --git a/src/test/java/com/arangodb/ArangoGraphTest.java b/driver/src/test/java/com/arangodb/ArangoGraphTest.java similarity index 83% rename from src/test/java/com/arangodb/ArangoGraphTest.java rename to driver/src/test/java/com/arangodb/ArangoGraphTest.java index 93aa505ce..73e56711c 100644 --- a/src/test/java/com/arangodb/ArangoGraphTest.java +++ b/driver/src/test/java/com/arangodb/ArangoGraphTest.java @@ -23,6 +23,7 @@ import com.arangodb.entity.CollectionPropertiesEntity; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.GraphEntity; +import com.arangodb.entity.ReplicationFactor; import com.arangodb.model.GraphCreateOptions; import com.arangodb.model.VertexCollectionCreateOptions; import org.junit.jupiter.api.BeforeAll; @@ -57,8 +58,10 @@ class ArangoGraphTest extends BaseJunit5 { private static final Integer REPLICATION_FACTOR = 2; private static final Integer NUMBER_OF_SHARDS = 2; - private static final EdgeDefinition ed1 = new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2); - private static final EdgeDefinition ed2 = new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3); + private static final EdgeDefinition ed1 = + new EdgeDefinition().collection(EDGE_COL_1).from(VERTEX_COL_1).to(VERTEX_COL_2); + private static final EdgeDefinition ed2 = + new EdgeDefinition().collection(EDGE_COL_2).from(VERTEX_COL_2).to(VERTEX_COL_1, VERTEX_COL_3); private static Stream graphs() { return dbsStream() @@ -92,11 +95,12 @@ void createWithReplicationAndWriteConcern(ArangoDatabase db) { assumeTrue(isCluster()); final Collection edgeDefinitions = new ArrayList<>(); - final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, new GraphCreateOptions().isSmart(true).replicationFactor(2).writeConcern(2)); + final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, + new GraphCreateOptions().isSmart(true).replicationFactor(2).writeConcern(2)); assertThat(graph).isNotNull(); assertThat(graph.getName()).isEqualTo(GRAPH_NAME + "_1"); assertThat(graph.getWriteConcern()).isEqualTo(2); - assertThat(graph.getReplicationFactor()).isEqualTo(2); + assertThat(graph.getReplicationFactor().getValue()).isEqualTo(2); db.graph(GRAPH_NAME + "_1").drop(); } @@ -128,7 +132,7 @@ void getInfo(ArangoGraph graph) { if (isCluster()) { for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2, VERTEX_COL_1, VERTEX_COL_2}) { final CollectionPropertiesEntity properties = graph.db().collection(collection).getProperties(); - assertThat(properties.getReplicationFactor()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); } } @@ -158,19 +162,19 @@ void addVertexCollection(ArangoGraph graph) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void addSatelliteVertexCollection(ArangoDatabase db) { - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); assumeTrue(isEnterprise()); assumeTrue(isAtLeastVersion(3, 9)); String v1Name = "vertex-" + rnd(); ArangoGraph g = db.graph(GRAPH_NAME + rnd()); - g.create(Collections.emptyList(), new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")); + g.create(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")); g.addVertexCollection(v1Name, new VertexCollectionCreateOptions().satellites(v1Name)); Collection vertexCollections = g.getVertexCollections(); assertThat(vertexCollections).contains(v1Name); - assertThat(db.collection(v1Name).getProperties().getSatellite()).isTrue(); + assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); // revert g.drop(); @@ -208,7 +212,7 @@ void addEdgeDefinition(ArangoGraph graph) { } if (isCluster()) { final CollectionPropertiesEntity properties = graph.db().collection(EDGE_COL_3).getProperties(); - assertThat(properties.getReplicationFactor()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); } @@ -219,7 +223,7 @@ void addEdgeDefinition(ArangoGraph graph) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") void addSatelliteEdgeDefinition(ArangoDatabase db) { - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); assumeTrue(isEnterprise()); assumeTrue(isAtLeastVersion(3, 9)); @@ -229,7 +233,7 @@ void addSatelliteEdgeDefinition(ArangoDatabase db) { EdgeDefinition ed = new EdgeDefinition().collection(eName).from(v1Name).to(v2Name).satellites(v1Name); ArangoGraph g = db.graph(GRAPH_NAME + rnd()); - g.create(Collections.emptyList(), new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")); + g.create(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")); g.addEdgeDefinition(ed); final GraphEntity ge = g.getInfo(); assertThat(ge).isNotNull(); @@ -240,7 +244,7 @@ void addSatelliteEdgeDefinition(ArangoDatabase db) { assertThat(e.getFrom()).contains(v1Name); assertThat(e.getTo()).contains(v2Name); - assertThat(db.collection(v1Name).getProperties().getSatellite()).isTrue(); + assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); // revert g.drop(); @@ -289,13 +293,14 @@ void removeEdgeDefinition(ArangoGraph graph) { @MethodSource("dbs") void smartGraph(ArangoDatabase db) { assumeTrue(isEnterprise()); - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); final Collection edgeDefinitions = new ArrayList<>(); edgeDefinitions.add(new EdgeDefinition().collection("smartGraph-edge-" + rnd()).from("smartGraph-vertex-" + rnd()).to("smartGraph-vertex-" + rnd())); String graphId = GRAPH_NAME + rnd(); - final GraphEntity g = db.createGraph(graphId, edgeDefinitions, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test").numberOfShards(2)); + final GraphEntity g = db.createGraph(graphId, edgeDefinitions, + new GraphCreateOptions().isSmart(true).smartGraphAttribute("test").numberOfShards(2)); assertThat(g).isNotNull(); assertThat(g.getIsSmart()).isTrue(); @@ -307,7 +312,7 @@ void smartGraph(ArangoDatabase db) { @MethodSource("dbs") void hybridSmartGraph(ArangoDatabase db) { assumeTrue(isEnterprise()); - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); assumeTrue((isAtLeastVersion(3, 9))); final Collection edgeDefinitions = new ArrayList<>(); @@ -326,16 +331,16 @@ void hybridSmartGraph(ArangoDatabase db) { assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); assertThat(g.getNumberOfShards()).isEqualTo(2); - assertThat(db.collection(eName).getProperties().getSatellite()).isTrue(); - assertThat(db.collection(v1Name).getProperties().getSatellite()).isTrue(); - assertThat(db.collection(v2Name).getProperties().getReplicationFactor()).isEqualTo(2); + assertThat(db.collection(eName).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v2Name).getProperties().getReplicationFactor().getValue()).isEqualTo(2); } @ParameterizedTest(name = "{index}") @MethodSource("dbs") void disjointSmartGraph(ArangoDatabase db) { assumeTrue(isEnterprise()); - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); assumeTrue((isAtLeastVersion(3, 7))); final Collection edgeDefinitions = new ArrayList<>(); @@ -356,7 +361,7 @@ void disjointSmartGraph(ArangoDatabase db) { @MethodSource("dbs") void hybridDisjointSmartGraph(ArangoDatabase db) { assumeTrue(isEnterprise()); - assumeTrue(isCluster()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); assumeTrue((isAtLeastVersion(3, 9))); final Collection edgeDefinitions = new ArrayList<>(); @@ -376,8 +381,30 @@ void hybridDisjointSmartGraph(ArangoDatabase db) { assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); assertThat(g.getNumberOfShards()).isEqualTo(2); - assertThat(db.collection(v1Name).getProperties().getSatellite()).isTrue(); - assertThat(db.collection(v2Name).getProperties().getReplicationFactor()).isEqualTo(2); + assertThat(db.collection(v1Name).getProperties().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v2Name).getProperties().getReplicationFactor().getValue()).isEqualTo(2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void enterpriseGraph(ArangoDatabase db) { + assumeTrue(isEnterprise()); + assumeTrue(isCluster() || isAtLeastVersion(3, 10)); + + final Collection edgeDefinitions = new ArrayList<>(); + edgeDefinitions.add(new EdgeDefinition().collection("enterpriseGraph-edge-" + rnd()).from("enterpriseGraph-vertex-" + rnd()).to("enterpriseGraph-vertex-" + rnd())); + + String graphId = GRAPH_NAME + rnd(); + final GraphEntity g = db.createGraph(graphId, edgeDefinitions, new GraphCreateOptions().isSmart(true).numberOfShards(2)); + + assertThat(g).isNotNull(); + assertThat(g.getSmartGraphAttribute()).isNull(); + assertThat(g.getNumberOfShards()).isEqualTo(2); + if (isAtLeastVersion(3, 10)) { + assertThat(g.getIsSmart()).isTrue(); + } else { + assertThat(g.getIsSmart()).isFalse(); + } } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/driver/src/test/java/com/arangodb/ArangoSearchTest.java similarity index 69% rename from src/test/java/com/arangodb/ArangoSearchTest.java rename to driver/src/test/java/com/arangodb/ArangoSearchTest.java index 173c0a47e..deaecc588 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/driver/src/test/java/com/arangodb/ArangoSearchTest.java @@ -20,13 +20,13 @@ package com.arangodb; +import com.arangodb.entity.InvertedIndexField; import com.arangodb.entity.ViewEntity; import com.arangodb.entity.ViewType; import com.arangodb.entity.arangosearch.*; import com.arangodb.entity.arangosearch.analyzer.*; -import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; -import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; +import com.arangodb.model.InvertedIndexOptions; +import com.arangodb.model.arangosearch.*; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -60,6 +60,15 @@ void exists(ArangoDatabase db) { assertThat(db.arangoSearch(viewName).exists()).isTrue(); } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createAndExistsSearchAlias(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + db.createSearchAlias(viewName, new SearchAliasCreateOptions()); + assertThat(db.arangoSearch(viewName).exists()).isTrue(); + } + @ParameterizedTest(name = "{index}") @MethodSource("dbs") void getInfo(ArangoDatabase db) { @@ -99,7 +108,7 @@ void rename(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void create(ArangoDatabase db) { + void createArangoSearchView(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 4)); String viewName = "view-" + rnd(); final ViewEntity info = db.arangoSearch(viewName).create(); @@ -112,7 +121,20 @@ void create(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void createWithOptions(ArangoDatabase db) { + void createSearchAliasView(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + final ViewEntity info = db.searchAlias(viewName).create(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(db.searchAlias(viewName).exists()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createArangoSearchViewWithOptions(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 4)); String viewName = "view-" + rnd(); final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); @@ -126,7 +148,7 @@ void createWithOptions(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void createWithPrimarySort(ArangoDatabase db) { + void createArangoSearchViewWithPrimarySort(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 5)); String viewName = "view-" + rnd(); final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); @@ -162,7 +184,7 @@ void createWithPrimarySort(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void createWithCommitIntervalMsec(ArangoDatabase db) { + void createArangoSearchViewWithCommitIntervalMsec(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 5)); String viewName = "view-" + rnd(); final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); @@ -183,7 +205,60 @@ void createWithCommitIntervalMsec(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void getProperties(ArangoDatabase db) { + void createSearchAliasViewWithOptions(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions(); + final ViewEntity info = db.searchAlias(viewName).create(options); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(db.searchAlias(viewName).exists()).isTrue(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void createSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollection col = db.collection(COLL_1); + String idxName1 = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName1) + .fields(new InvertedIndexField().name("a" + rnd()))); + + String idxName2 = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))); + + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes( + new SearchAliasIndex(COLL_1, idxName1, SearchAliasIndex.OperationType.add), + new SearchAliasIndex(COLL_1, idxName2, SearchAliasIndex.OperationType.add), + new SearchAliasIndex(COLL_1, idxName2, SearchAliasIndex.OperationType.del) + ); + final ViewEntity info = db.searchAlias(viewName).create(options); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName1)); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getArangoSearchViewProperties(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 4)); String viewName = "view-" + rnd(); final ArangoSearch view = db.arangoSearch(viewName); @@ -203,7 +278,7 @@ void getProperties(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void updateProperties(ArangoDatabase db) { + void updateArangoSearchViewProperties(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 4)); String viewName = "view-" + rnd(); final ArangoSearch view = db.arangoSearch(viewName); @@ -236,7 +311,47 @@ void updateProperties(ArangoDatabase db) { @ParameterizedTest(name = "{index}") @MethodSource("dbs") - void replaceProperties(ArangoDatabase db) { + void updateSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollection col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))); + ArangoCollection col2 = db.collection(COLL_2); + String idxName2 = "idx-" + rnd(); + col2.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))); + + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options); + db.searchAlias(viewName).updateProperties(new SearchAliasPropertiesOptions() + .indexes(new SearchAliasIndex(COLL_2, idxName2))); + + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .hasSize(2) + .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)) + .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void replaceArangoSearchViewProperties(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 4)); String viewName = "view-" + rnd(); final ArangoSearch view = db.arangoSearch(viewName); @@ -253,43 +368,43 @@ void replaceProperties(ArangoDatabase db) { assertThat(link.getFields().iterator().next().getName()).isEqualTo("value"); } - private void createGetAndDeleteAnalyzer(ArangoDatabase db, AnalyzerEntity options) { - - String fullyQualifiedName = db.dbName().get() + "::" + options.getName(); - - // createAnalyzer - AnalyzerEntity createdAnalyzer = db.createAnalyzer(options); - - assertThat(createdAnalyzer.getName()).isEqualTo(fullyQualifiedName); - assertThat(createdAnalyzer.getType()).isEqualTo(options.getType()); - assertThat(createdAnalyzer.getFeatures()).isEqualTo(options.getFeatures()); - compareProperties(createdAnalyzer.getProperties(), options.getProperties()); - - // getAnalyzer - AnalyzerEntity gotAnalyzer = db.getAnalyzer(options.getName()); - assertThat(gotAnalyzer.getName()).isEqualTo(fullyQualifiedName); - assertThat(gotAnalyzer.getType()).isEqualTo(options.getType()); - assertThat(gotAnalyzer.getFeatures()).isEqualTo(options.getFeatures()); - compareProperties(gotAnalyzer.getProperties(), options.getProperties()); - - // getAnalyzers - @SuppressWarnings("OptionalGetWithoutIsPresent") - AnalyzerEntity foundAnalyzer = db.getAnalyzers().stream().filter(it -> it.getName().equals(fullyQualifiedName)) - .findFirst().get(); - - assertThat(foundAnalyzer.getName()).isEqualTo(fullyQualifiedName); - assertThat(foundAnalyzer.getType()).isEqualTo(options.getType()); - assertThat(foundAnalyzer.getFeatures()).isEqualTo(options.getFeatures()); - compareProperties(foundAnalyzer.getProperties(), options.getProperties()); + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void replaceSearchAliasViewWithIndexesAndGetProperties(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollection col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))); + ArangoCollection col2 = db.collection(COLL_2); + String idxName2 = "idx-" + rnd(); + col2.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))); - AnalyzerDeleteOptions deleteOptions = new AnalyzerDeleteOptions(); - deleteOptions.setForce(true); + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options); + db.searchAlias(viewName).replaceProperties(new SearchAliasPropertiesOptions() + .indexes(new SearchAliasIndex(COLL_2, idxName2))); - // deleteAnalyzer - db.deleteAnalyzer(options.getName(), deleteOptions); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); - Throwable thrown = catchThrowable(() -> db.getAnalyzer(options.getName())); - assertThat(thrown).isInstanceOf(ArangoDBException.class); + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .hasSize(1) + .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); } private void createGetAndDeleteTypedAnalyzer(ArangoDatabase db, SearchAnalyzer analyzer) { @@ -306,8 +421,8 @@ private void createGetAndDeleteTypedAnalyzer(ArangoDatabase db, SearchAnalyzer a assertThat(gotAnalyzer).isEqualTo(analyzer); // getAnalyzers - @SuppressWarnings("OptionalGetWithoutIsPresent") - SearchAnalyzer foundAnalyzer = db.getSearchAnalyzers().stream().filter(it -> it.getName().equals(fullyQualifiedName)) + SearchAnalyzer foundAnalyzer = + db.getSearchAnalyzers().stream().filter(it -> it.getName().equals(fullyQualifiedName)) .findFirst().get(); assertThat(foundAnalyzer).isEqualTo(analyzer); @@ -317,50 +432,13 @@ private void createGetAndDeleteTypedAnalyzer(ArangoDatabase db, SearchAnalyzer a db.deleteSearchAnalyzer(analyzer.getName(), deleteOptions); - Throwable thrown = catchThrowable(() -> db.getAnalyzer(analyzer.getName())); + Throwable thrown = catchThrowable(() -> db.getSearchAnalyzer(analyzer.getName())); assertThat(thrown).isInstanceOf(ArangoDBException.class); ArangoDBException e = (ArangoDBException) thrown; assertThat(e.getResponseCode()).isEqualTo(404); assertThat(e.getErrorNum()).isEqualTo(1202); } - @SuppressWarnings("unchecked") - private void compareProperties(Map actualProperties, Map expectedProperties) { - expectedProperties.forEach((key, expectedValue) -> { - Object actualValue = actualProperties.get(key); - if (expectedValue instanceof Map) { - assertThat(actualValue).isNotNull(); - assertThat(actualValue).isInstanceOf(Map.class); - compareProperties((Map) actualValue, (Map) expectedValue); - } else if (expectedValue instanceof Number) { - assertThat(Double.valueOf(actualValue.toString())).isEqualTo(Double.valueOf(expectedValue.toString())); - } else { - assertThat(actualValue).isEqualTo(expectedValue); - } - }); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void identityAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + rnd(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.identity); - options.setProperties(Collections.emptyMap()); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void identityAnalyzerTyped(ArangoDatabase db) { @@ -380,27 +458,6 @@ void identityAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, analyzer); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void delimiterAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + rnd(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.delimiter); - options.setProperties(Collections.singletonMap("delimiter", "-")); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void delimiterAnalyzerTyped(ArangoDatabase db) { @@ -424,27 +481,6 @@ void delimiterAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, analyzer); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void stemAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + rnd(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.stem); - options.setProperties(Collections.singletonMap("locale", "ru")); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void stemAnalyzerTyped(ArangoDatabase db) { @@ -468,32 +504,6 @@ void stemAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, options); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void normAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + rnd(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("locale", "ru"); - properties.put("case", "lower"); - properties.put("accent", true); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.norm); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void normAnalyzerTyped(ArangoDatabase db) { @@ -519,32 +529,6 @@ void normAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, options); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void ngramAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + rnd(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("max", 6L); - properties.put("min", 3L); - properties.put("preserveOriginal", true); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.ngram); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void ngramAnalyzerTyped(ArangoDatabase db) { @@ -571,35 +555,6 @@ void ngramAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, analyzer); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void enhancedNgramAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 6)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("max", 6L); - properties.put("min", 3L); - properties.put("preserveOriginal", true); - properties.put("startMarker", "^"); - properties.put("endMarker", "^"); - properties.put("streamType", "utf8"); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.ngram); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void enhancedNgramAnalyzerTyped(ArangoDatabase db) { @@ -628,34 +583,6 @@ void enhancedNgramAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, analyzer); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void textAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + rnd(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("locale", "ru"); - properties.put("case", "lower"); - properties.put("stopwords", Collections.emptyList()); - properties.put("accent", true); - properties.put("stemming", true); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.text); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void textAnalyzerTyped(ArangoDatabase db) { @@ -683,40 +610,6 @@ void textAnalyzerTyped(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, analyzer); } - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void enhancedTextAnalyzer(ArangoDatabase db) { - assumeTrue(isAtLeastVersion(3, 6)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map edgeNgram = new HashMap<>(); - edgeNgram.put("min", 2L); - edgeNgram.put("max", 100000L); - edgeNgram.put("preserveOriginal", true); - - Map properties = new HashMap<>(); - properties.put("locale", "ru"); - properties.put("case", "lower"); - properties.put("stopwords", Collections.emptyList()); - properties.put("accent", true); - properties.put("stemming", true); - properties.put("edgeNgram", edgeNgram); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.text); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(db, options); - } - @ParameterizedTest(name = "{index}") @MethodSource("dbs") void enhancedTextAnalyzerTyped(ArangoDatabase db) { @@ -754,19 +647,25 @@ void enhancedTextAnalyzerTyped(ArangoDatabase db) { void arangoSearchOptions(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 4)); String viewName = "view-" + rnd(); - ArangoSearchCreateOptions options = new ArangoSearchCreateOptions() - .link( - CollectionLink.on(COLL_1) - .analyzers("identity") - .fields( - FieldLink.on("id") - .analyzers("identity") - ) - .includeAllFields(true) - .storeValues(StoreValuesType.ID) - .trackListPositions(false) - - ); + FieldLink field = FieldLink.on("f1").inBackground(true); + if (isEnterprise()) { + field.nested(FieldLink.on("f2")); + } + CollectionLink link = CollectionLink.on(COLL_1) + .analyzers("identity") + .fields(field) + .includeAllFields(true) + .storeValues(StoreValuesType.ID) + .trackListPositions(false) + .inBackground(true) + .cache(true); + + if (isEnterprise()) { + link.nested(FieldLink.on("f3")); + } + ArangoSearchCreateOptions options = new ArangoSearchCreateOptions().link(link); + StoredValue storedValue = new StoredValue(Arrays.asList("a", "b"), ArangoSearchCompression.none, true); + options.storedValues(storedValue); final ArangoSearch view = db.arangoSearch(viewName); view.create(options); @@ -776,13 +675,35 @@ void arangoSearchOptions(ArangoDatabase db) { assertThat(properties.getId()).isNotNull(); assertThat(properties.getName()).isEqualTo(viewName); assertThat(properties.getType()).isEqualTo(ViewType.ARANGO_SEARCH); + assertThat(properties.getLinks()).isNotEmpty(); + + CollectionLink createdLink = properties.getLinks().iterator().next(); + assertThat(createdLink.getName()).isEqualTo(COLL_1); + assertThat(createdLink.getAnalyzers()).contains("identity"); + assertThat(createdLink.getIncludeAllFields()).isTrue(); + assertThat(createdLink.getStoreValues()).isEqualTo(StoreValuesType.ID); + assertThat(createdLink.getTrackListPositions()).isFalse(); + + if (isEnterprise() && isAtLeastVersion(3, 9, 5) && isLessThanVersion(3, 10)) { + assertThat(createdLink.getCache()).isTrue(); + assertThat(properties.getStoredValues()) + .isNotEmpty() + .allSatisfy(it -> assertThat(it.getCache()).isTrue()); + } - CollectionLink link = properties.getLinks().iterator().next(); - assertThat(link.getAnalyzers()).contains("identity"); - assertThat(link.getName()).isEqualTo(COLL_1); - assertThat(link.getIncludeAllFields()).isTrue(); - assertThat(link.getStoreValues()).isEqualTo(StoreValuesType.ID); - assertThat(link.getTrackListPositions()).isFalse(); + if (isEnterprise() && isAtLeastVersion(3, 10)) { + assertThat(createdLink.getNested()).isNotEmpty(); + FieldLink nested = createdLink.getNested().iterator().next(); + assertThat(nested.getName()).isEqualTo("f3"); + } + + FieldLink fieldLink = createdLink.getFields().iterator().next(); + assertThat(fieldLink.getName()).isEqualTo("f1"); + if (isEnterprise() && isAtLeastVersion(3, 10)) { + assertThat(fieldLink.getNested()).isNotEmpty(); + FieldLink nested = fieldLink.getNested().iterator().next(); + assertThat(nested.getName()).isEqualTo("f2"); + } } @ParameterizedTest(name = "{index}") @@ -855,9 +776,10 @@ void stopwordsAnalyzer(ArangoDatabase db) { createGetAndDeleteTypedAnalyzer(db, analyzer); db.createSearchAnalyzer(analyzer); - String res = db.query("RETURN FLATTEN(TOKENS(SPLIT('the fox and the dog and a theater', ' '), @aName))", - Collections.singletonMap("aName", name), String.class).next(); - assertThat(res).isEqualTo("[\"fox\",\"dog\",\"a\",\"theater\"]"); + Collection res = db.query("RETURN FLATTEN(TOKENS(SPLIT('the fox and the dog and a theater', ' '), " + + "@aName))", + Collections.singletonMap("aName", name), Collection.class).next(); + assertThat(res).containsExactly("fox", "dog", "a", "theater"); db.deleteSearchAnalyzer(name); } @@ -988,4 +910,101 @@ void collationAnalyzer(ArangoDatabase db) { } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void classificationAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + assumeTrue(isEnterprise()); + + ClassificationAnalyzerProperties properties = new ClassificationAnalyzerProperties(); + properties.setModelLocation("/tmp/foo.bin"); + properties.setTopK(2); + properties.setThreshold(.5); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + ClassificationAnalyzer analyzer = new ClassificationAnalyzer(); + analyzer.setName("test-" + UUID.randomUUID()); + analyzer.setProperties(properties); + analyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void nearestNeighborsAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + assumeTrue(isEnterprise()); + + NearestNeighborsAnalyzerProperties properties = new NearestNeighborsAnalyzerProperties(); + properties.setModelLocation("/tmp/foo.bin"); + properties.setTopK(2); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + NearestNeighborsAnalyzer analyzer = new NearestNeighborsAnalyzer(); + analyzer.setName("test-" + UUID.randomUUID()); + analyzer.setProperties(properties); + analyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void MinHashAnalyzer(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + assumeTrue(isEnterprise()); + + SegmentationAnalyzerProperties segProperties = new SegmentationAnalyzerProperties(); + segProperties.setBreakMode(SegmentationAnalyzerProperties.BreakMode.alpha); + segProperties.setAnalyzerCase(SearchAnalyzerCase.lower); + + SegmentationAnalyzer segAnalyzer = new SegmentationAnalyzer(); + segAnalyzer.setProperties(segProperties); + + MinHashAnalyzerProperties properties = new MinHashAnalyzerProperties(); + properties.setAnalyzer(segAnalyzer); + properties.setNumHashes(2); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + MinHashAnalyzer analyzer = new MinHashAnalyzer(); + analyzer.setName("test-" + UUID.randomUUID()); + analyzer.setProperties(properties); + analyzer.setFeatures(features); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void offsetFeature(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + + String name = "test-" + UUID.randomUUID(); + + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + features.add(AnalyzerFeature.offset); + + IdentityAnalyzer analyzer = new IdentityAnalyzer(); + analyzer.setFeatures(features); + analyzer.setName(name); + + createGetAndDeleteTypedAnalyzer(db, analyzer); + } + } diff --git a/src/test/java/com/arangodb/ArangoSslTest.java b/driver/src/test/java/com/arangodb/ArangoSslTest.java similarity index 81% rename from src/test/java/com/arangodb/ArangoSslTest.java rename to driver/src/test/java/com/arangodb/ArangoSslTest.java index 613f1632c..1c9c2bd3a 100644 --- a/src/test/java/com/arangodb/ArangoSslTest.java +++ b/driver/src/test/java/com/arangodb/ArangoSslTest.java @@ -1,92 +1,101 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.mapping.ArangoJack; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledIfSystemProperty; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLHandshakeException; -import javax.net.ssl.TrustManagerFactory; -import java.security.KeyStore; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -@EnabledIfSystemProperty(named = "SslTest", matches = "true") -class ArangoSslTest { - - /* - * a SSL trust store - * - * create the trust store for the self signed certificate: - * keytool -import -alias "my arangodb server cert" -file UnitTests/server.pem -keystore example.truststore - * - * Documentation: - * https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ssl/SSLSocketFactory.html - */ - private static final String SSL_TRUSTSTORE = "/example.truststore"; - private static final String SSL_TRUSTSTORE_PASSWORD = "12345678"; - - @Test - void connect() throws Exception { - final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); - ks.load(this.getClass().getResourceAsStream(SSL_TRUSTSTORE), SSL_TRUSTSTORE_PASSWORD.toCharArray()); - - final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, SSL_TRUSTSTORE_PASSWORD.toCharArray()); - - final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(ks); - - final SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - - final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(ArangoSslTest.class.getResourceAsStream("/arangodb-ssl.properties")).useSsl(true) - .sslContext(sc).serializer(new ArangoJack()).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } - - @Test - void connectWithoutValidSslContext() { - final ArangoDB arangoDB = new ArangoDB.Builder() - .loadProperties(ArangoSslTest.class.getResourceAsStream("/arangodb-ssl.properties")).useSsl(true) - .serializer(new ArangoJack()).build(); - Throwable thrown = catchThrowable(arangoDB::getVersion); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException ex = (ArangoDBException) thrown; - assertThat(ex.getCause()).isInstanceOf(ArangoDBMultipleException.class); - List exceptions = ((ArangoDBMultipleException) ex.getCause()).getExceptions(); - exceptions.forEach(e -> assertThat(e).isInstanceOf(SSLHandshakeException.class)); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.condition.EnabledIfSystemProperty; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.TrustManagerFactory; +import java.security.KeyStore; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +@Tag("ssl") +@EnabledIfSystemProperty(named = "SslTest", matches = "true") +class ArangoSslTest { + + /* + * a SSL trust store + * + * create the trust store for the self signed certificate: + * keytool -import -alias "my arangodb server cert" -file UnitTests/server.pem -keystore example.truststore + * + * Documentation: + * https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ssl/SSLSocketFactory.html + */ + private static final String SSL_TRUSTSTORE = "/example.truststore"; + private static final String SSL_TRUSTSTORE_PASSWORD = "12345678"; + + @ParameterizedTest + @EnumSource(Protocol.class) + void connect(Protocol protocol) throws Exception { + final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(this.getClass().getResourceAsStream(SSL_TRUSTSTORE), SSL_TRUSTSTORE_PASSWORD.toCharArray()); + + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, SSL_TRUSTSTORE_PASSWORD.toCharArray()); + + final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + + final SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + final ArangoDB arangoDB = new ArangoDB.Builder() + .useProtocol(protocol) + .host("localhost", 8529) + .password("test") + .useSsl(true) + .sslContext(sc).build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void connectWithoutValidSslContext(Protocol protocol) { + final ArangoDB arangoDB = new ArangoDB.Builder() + .useProtocol(protocol) + .host("localhost", 8529) + .useSsl(true) + .build(); + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException ex = (ArangoDBException) thrown; + assertThat(ex.getCause()).isInstanceOf(ArangoDBMultipleException.class); + List exceptions = ((ArangoDBMultipleException) ex.getCause()).getExceptions(); + exceptions.forEach(e -> assertThat(e).isInstanceOf(SSLHandshakeException.class)); + } + +} diff --git a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java b/driver/src/test/java/com/arangodb/ArangoVertexCollectionTest.java similarity index 88% rename from src/test/java/com/arangodb/ArangoVertexCollectionTest.java rename to driver/src/test/java/com/arangodb/ArangoVertexCollectionTest.java index 84283f19f..5b5504d80 100644 --- a/src/test/java/com/arangodb/ArangoVertexCollectionTest.java +++ b/driver/src/test/java/com/arangodb/ArangoVertexCollectionTest.java @@ -1,473 +1,480 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.VertexEntity; -import com.arangodb.entity.VertexUpdateEntity; -import com.arangodb.model.*; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Collection; -import java.util.Collections; -import java.util.UUID; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoVertexCollectionTest extends BaseJunit5 { - - private static final String GRAPH_NAME = "ArangoVertexCollectionTest_graph"; - private static final String COLLECTION_NAME = "ArangoVertexCollectionTest_vertex_collection"; - - private static Stream vertices() { - return dbsStream() - .map(db -> db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME)) - .map(Arguments::of); - } - - @BeforeAll - static void init() { - initCollections(COLLECTION_NAME); - initGraph( - GRAPH_NAME, - null, - new GraphCreateOptions().orphanCollections(COLLECTION_NAME) - ); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void dropVertexCollection(ArangoVertexCollection vertices) { - ArangoGraph graph = vertices.graph(); - vertices.drop(); - final Collection vertexCollections = graph.getVertexCollections(); - assertThat(vertexCollections).isEmpty(); - - // revert - graph.addVertexCollection(COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void insertVertex(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - assertThat(vertex).isNotNull(); - ArangoCollection collection = vertices.graph().db().collection(vertices.name()); - final BaseDocument document = collection - .getDocument(vertex.getKey(), BaseDocument.class, null); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void insertVertexViolatingUniqueConstraint(ArangoVertexCollection vertices) { - ArangoCollection collection = vertices.graph().db().collection(vertices.name()); - collection - .ensureSkiplistIndex(Collections.singletonList("field"), new SkiplistIndexOptions().unique(true).sparse(true)); - - VertexEntity inserted = vertices.insertVertex("{\"field\": 99}", null); - - try { - vertices.insertVertex("{\"field\": 99}", null); - } catch (ArangoDBException e) { - assertThat(e.getResponseCode()).isEqualTo(409); - assertThat(e.getErrorNum()).isEqualTo(1210); - } - - // revert - vertices.deleteVertex(inserted.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void duplicateInsertSameObjectVertex(ArangoVertexCollection vertices) { - - // ######################################################### - // Create a new BaseDocument - // ######################################################### - - UUID uuid = UUID.randomUUID(); - BaseDocument bd = new BaseDocument(); - bd.setKey(uuid.toString()); - bd.addAttribute("name", "Paul"); - - vertices.insertVertex(bd); - - UUID uuid2 = UUID.randomUUID(); - BaseDocument bd2 = new BaseDocument(); - bd2.setKey(uuid2.toString()); - bd2.addAttribute("name", "Paul"); - - vertices.insertVertex(bd2); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void insertVertexUpdateRev(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - final VertexEntity vertex = vertices.insertVertex(doc, null); - assertThat(doc.getRevision()).isEqualTo(vertex.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertex(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final BaseDocument document = vertices - .getVertex(vertex.getKey(), BaseDocument.class, null); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertexIfMatch(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(vertex.getRev()); - final BaseDocument document = vertices - .getVertex(vertex.getKey(), BaseDocument.class, options); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertexIfMatchFail(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); - final BaseDocument vertex2 = vertices - .getVertex(vertex.getKey(), BaseDocument.class, options); - assertThat(vertex2).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertexIfNoneMatch(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); - final BaseDocument document = vertices - .getVertex(vertex.getKey(), BaseDocument.class, options); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(vertex.getKey()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void getVertexIfNoneMatchFail(ArangoVertexCollection vertices) { - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(), null); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(vertex.getRev()); - final BaseDocument vertex2 = vertices - .getVertex(vertex.getKey(), BaseDocument.class, options); - assertThat(vertex2).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void replaceVertex(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.getProperties().clear(); - doc.addAttribute("b", "test"); - final VertexUpdateEntity replaceResult = vertices - .replaceVertex(createResult.getKey(), doc, null); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void replaceVertexUpdateRev(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); - final VertexUpdateEntity replaceResult = vertices - .replaceVertex(createResult.getKey(), doc, null); - assertThat(doc.getRevision()).isEqualTo(replaceResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void replaceVertexIfMatch(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.getProperties().clear(); - doc.addAttribute("b", "test"); - final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch(createResult.getRev()); - final VertexUpdateEntity replaceResult = vertices - .replaceVertex(createResult.getKey(), doc, options); - assertThat(replaceResult).isNotNull(); - assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); - assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); - assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void replaceVertexIfMatchFail(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.getProperties().clear(); - doc.addAttribute("b", "test"); - final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> vertices.replaceVertex(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - // FIXME: atm the server replies 409 for HTTP_JSON or HTTP_VPACK - // assertThat(e.getResponseCode()).isEqualTo(412)); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertex(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, null); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexUpdateRev(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - assertThat(doc.getRevision()).isEqualTo(createResult.getRev()); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, null); - assertThat(doc.getRevision()).isEqualTo(updateResult.getRev()); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexIfMatch(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch(createResult.getRev()); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getAttribute("a")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); - assertThat(readResult.getAttribute("b")).isNotNull(); - assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); - assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); - assertThat(readResult.getProperties()).containsKey("c"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexIfMatchFail(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - doc.addAttribute("a", "test"); - doc.addAttribute("c", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", "test1"); - doc.addAttribute("b", "test"); - doc.updateAttribute("c", null); - final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch("no"); - - Throwable thrown = catchThrowable(() -> vertices.updateVertex(createResult.getKey(), doc, options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - // FIXME: atm the server replies 409 for HTTP_JSON or HTTP_VPACK - // assertThat(e.getResponseCode()).isEqualTo(412)); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexKeepNullTrue(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", null); - final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(true); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(1); - assertThat(readResult.getProperties()).containsKey("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void updateVertexKeepNullFalse(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - doc.addAttribute("a", "test"); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - doc.updateAttribute("a", null); - final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(false); - final VertexUpdateEntity updateResult = vertices - .updateVertex(createResult.getKey(), doc, options); - assertThat(updateResult).isNotNull(); - assertThat(updateResult.getId()).isEqualTo(createResult.getId()); - assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); - assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); - - final BaseDocument readResult = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getId()).isEqualTo(createResult.getId()); - assertThat(readResult.getRevision()).isNotNull(); - assertThat(readResult.getProperties().keySet()).doesNotContain("a"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void deleteVertex(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - vertices.deleteVertex(createResult.getKey(), null); - final BaseDocument vertex = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(vertex).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void deleteVertexIfMatch(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch(createResult.getRev()); - vertices.deleteVertex(createResult.getKey(), options); - final BaseDocument vertex = vertices - .getVertex(createResult.getKey(), BaseDocument.class, null); - assertThat(vertex).isNull(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void deleteVertexIfMatchFail(ArangoVertexCollection vertices) { - final BaseDocument doc = new BaseDocument(); - final VertexEntity createResult = vertices - .insertVertex(doc, null); - final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch("no"); - Throwable thrown = catchThrowable(() -> vertices.deleteVertex(createResult.getKey(), options)); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - // FIXME: atm the server replies 409 for HTTP_JSON or HTTP_VPACK - // assertThat(e.getResponseCode()).isEqualTo(412)); - assertThat(e.getErrorNum()).isEqualTo(1200); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("vertices") - void vertexKeyWithSpecialChars(ArangoVertexCollection vertices) { - final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); - final VertexEntity vertex = vertices - .insertVertex(new BaseDocument(key), null); - assertThat(vertex).isNotNull(); - ArangoCollection collection = vertices.graph().db().collection(vertices.name()); - final BaseDocument document = collection - .getDocument(vertex.getKey(), BaseDocument.class, null); - assertThat(document).isNotNull(); - assertThat(document.getKey()).isEqualTo(key); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.VertexEntity; +import com.arangodb.entity.VertexUpdateEntity; +import com.arangodb.model.*; +import com.arangodb.util.RawJson; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Collection; +import java.util.Collections; +import java.util.UUID; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class ArangoVertexCollectionTest extends BaseJunit5 { + + private static final String GRAPH_NAME = "ArangoVertexCollectionTest_graph"; + private static final String COLLECTION_NAME = "ArangoVertexCollectionTest_vertex_collection"; + + private static Stream vertices() { + return dbsStream() + .map(db -> db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME)) + .map(Arguments::of); + } + + @BeforeAll + static void init() { + initCollections(COLLECTION_NAME); + initGraph( + GRAPH_NAME, + null, + new GraphCreateOptions().orphanCollections(COLLECTION_NAME) + ); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void dropVertexCollection(ArangoVertexCollection vertices) { + ArangoGraph graph = vertices.graph(); + vertices.drop(); + final Collection vertexCollections = graph.getVertexCollections(); + assertThat(vertexCollections).isEmpty(); + + // revert + graph.addVertexCollection(COLLECTION_NAME); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void insertVertex(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + assertThat(vertex).isNotNull(); + ArangoCollection collection = vertices.graph().db().collection(vertices.name()); + final BaseDocument document = collection + .getDocument(vertex.getKey(), BaseDocument.class, null); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void insertVertexViolatingUniqueConstraint(ArangoVertexCollection vertices) { + ArangoCollection collection = vertices.graph().db().collection(vertices.name()); + collection + .ensureSkiplistIndex(Collections.singletonList("field"), + new SkiplistIndexOptions().unique(true).sparse(true)); + + VertexEntity inserted = vertices.insertVertex(RawJson.of("{\"field\": 99}")); + + try { + vertices.insertVertex(RawJson.of("{\"field\": 99}")); + } catch (ArangoDBException e) { + assertThat(e.getResponseCode()).isEqualTo(409); + assertThat(e.getErrorNum()).isEqualTo(1210); + } + + // revert + vertices.deleteVertex(inserted.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void duplicateInsertSameObjectVertex(ArangoVertexCollection vertices) { + + // ######################################################### + // Create a new BaseDocument + // ######################################################### + + UUID uuid = UUID.randomUUID(); + BaseDocument bd = new BaseDocument(UUID.randomUUID().toString()); + bd.setKey(uuid.toString()); + bd.addAttribute("name", "Paul"); + + vertices.insertVertex(bd); + + UUID uuid2 = UUID.randomUUID(); + BaseDocument bd2 = new BaseDocument(UUID.randomUUID().toString()); + bd2.setKey(uuid2.toString()); + bd2.addAttribute("name", "Paul"); + + vertices.insertVertex(bd2); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void insertVertexUpdateRev(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity vertex = vertices.insertVertex(doc, null); + assertThat(doc.getRevision()).isNull(); + assertThat(vertex.getRev()).isNotNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertex(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final BaseDocument document = vertices + .getVertex(vertex.getKey(), BaseDocument.class, null); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertexIfMatch(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch(vertex.getRev()); + final BaseDocument document = vertices + .getVertex(vertex.getKey(), BaseDocument.class, options); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertexIfMatchFail(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); + final BaseDocument vertex2 = vertices + .getVertex(vertex.getKey(), BaseDocument.class, options); + assertThat(vertex2).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertexIfNoneMatch(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch("no"); + final BaseDocument document = vertices + .getVertex(vertex.getKey(), BaseDocument.class, options); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(vertex.getKey()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void getVertexIfNoneMatchFail(ArangoVertexCollection vertices) { + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(), null); + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(vertex.getRev()); + final BaseDocument vertex2 = vertices + .getVertex(vertex.getKey(), BaseDocument.class, options); + assertThat(vertex2).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void replaceVertex(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final VertexUpdateEntity replaceResult = vertices + .replaceVertex(createResult.getKey(), doc, null); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void replaceVertexUpdateRev(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + final VertexUpdateEntity replaceResult = vertices + .replaceVertex(createResult.getKey(), doc, null); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(replaceResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void replaceVertexIfMatch(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch(createResult.getRev()); + final VertexUpdateEntity replaceResult = vertices + .replaceVertex(createResult.getKey(), doc, options); + assertThat(replaceResult).isNotNull(); + assertThat(replaceResult.getId()).isEqualTo(createResult.getId()); + assertThat(replaceResult.getRev()).isNotEqualTo(replaceResult.getOldRev()); + assertThat(replaceResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getRevision()).isEqualTo(replaceResult.getRev()); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void replaceVertexIfMatchFail(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.removeAttribute("a"); + doc.addAttribute("b", "test"); + final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> vertices.replaceVertex(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertex(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, null); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexUpdateRev(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.addAttribute("foo", "bar"); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, null); + assertThat(doc.getRevision()).isNull(); + assertThat(createResult.getRev()).isNotNull(); + assertThat(updateResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexIfMatch(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch(createResult.getRev()); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getAttribute("a")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("a"))).isEqualTo("test1"); + assertThat(readResult.getAttribute("b")).isNotNull(); + assertThat(String.valueOf(readResult.getAttribute("b"))).isEqualTo("test"); + assertThat(readResult.getRevision()).isEqualTo(updateResult.getRev()); + assertThat(readResult.getProperties()).containsKey("c"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexIfMatchFail(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + doc.addAttribute("c", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", "test1"); + doc.addAttribute("b", "test"); + doc.updateAttribute("c", null); + final VertexUpdateOptions options = new VertexUpdateOptions().ifMatch("no"); + + Throwable thrown = catchThrowable(() -> vertices.updateVertex(createResult.getKey(), doc, options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexKeepNullTrue(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", null); + final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(true); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getProperties().keySet()).hasSize(4); + assertThat(readResult.getProperties()).containsKey("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void updateVertexKeepNullFalse(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + doc.addAttribute("a", "test"); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + doc.updateAttribute("a", null); + final VertexUpdateOptions options = new VertexUpdateOptions().keepNull(false); + final VertexUpdateEntity updateResult = vertices + .updateVertex(createResult.getKey(), doc, options); + assertThat(updateResult).isNotNull(); + assertThat(updateResult.getId()).isEqualTo(createResult.getId()); + assertThat(updateResult.getRev()).isNotEqualTo(updateResult.getOldRev()); + assertThat(updateResult.getOldRev()).isEqualTo(createResult.getRev()); + + final BaseDocument readResult = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); + assertThat(readResult.getId()).isEqualTo(createResult.getId()); + assertThat(readResult.getRevision()).isNotNull(); + assertThat(readResult.getProperties().keySet()).doesNotContain("a"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void deleteVertex(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + vertices.deleteVertex(createResult.getKey(), null); + final BaseDocument vertex = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(vertex).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void deleteVertexIfMatch(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch(createResult.getRev()); + vertices.deleteVertex(createResult.getKey(), options); + final BaseDocument vertex = vertices + .getVertex(createResult.getKey(), BaseDocument.class, null); + assertThat(vertex).isNull(); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void deleteVertexIfMatchFail(ArangoVertexCollection vertices) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final VertexEntity createResult = vertices + .insertVertex(doc, null); + final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch("no"); + Throwable thrown = catchThrowable(() -> vertices.deleteVertex(createResult.getKey(), options)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException e = (ArangoDBException) thrown; + assertThat(e.getResponseCode()).isEqualTo(412); + assertThat(e.getErrorNum()).isEqualTo(1200); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("vertices") + void vertexKeyWithSpecialChars(ArangoVertexCollection vertices) { + final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); + final VertexEntity vertex = vertices + .insertVertex(new BaseDocument(key), null); + assertThat(vertex).isNotNull(); + ArangoCollection collection = vertices.graph().db().collection(vertices.name()); + final BaseDocument document = collection + .getDocument(vertex.getKey(), BaseDocument.class, null); + assertThat(document).isNotNull(); + assertThat(document.getKey()).isEqualTo(key); + } + +} diff --git a/src/test/java/com/arangodb/ArangoViewTest.java b/driver/src/test/java/com/arangodb/ArangoViewTest.java similarity index 72% rename from src/test/java/com/arangodb/ArangoViewTest.java rename to driver/src/test/java/com/arangodb/ArangoViewTest.java index 5d63b02ac..09121b7ff 100644 --- a/src/test/java/com/arangodb/ArangoViewTest.java +++ b/driver/src/test/java/com/arangodb/ArangoViewTest.java @@ -26,6 +26,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import java.util.Collection; + import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assumptions.assumeTrue; @@ -61,6 +63,31 @@ void getInfo(ArangoDatabase db) { assertThat(info.getType()).isEqualTo(ViewType.ARANGO_SEARCH); } + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getInfoSearchAlias(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String name = "view-" + rnd(); + db.createView(name, ViewType.SEARCH_ALIAS); + final ViewEntity info = db.view(name).getInfo(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(name); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void getViews(ArangoDatabase db) { + assumeTrue(isAtLeastVersion(3, 10)); + String name1 = "view-" + rnd(); + String name2 = "view-" + rnd(); + db.createView(name1, ViewType.ARANGO_SEARCH); + db.createView(name2, ViewType.SEARCH_ALIAS); + Collection views = db.getViews(); + assertThat(views).extracting(ViewEntity::getName).contains(name1, name2); + } + @ParameterizedTest(name = "{index}") @MethodSource("dbs") void drop(ArangoDatabase db) { diff --git a/src/test/java/com/arangodb/BaseJunit5.java b/driver/src/test/java/com/arangodb/BaseJunit5.java similarity index 82% rename from src/test/java/com/arangodb/BaseJunit5.java rename to driver/src/test/java/com/arangodb/BaseJunit5.java index f6e9390ee..3e6c8e30a 100644 --- a/src/test/java/com/arangodb/BaseJunit5.java +++ b/driver/src/test/java/com/arangodb/BaseJunit5.java @@ -1,7 +1,8 @@ package com.arangodb; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.*; -import com.arangodb.mapping.ArangoJack; import com.arangodb.model.CollectionCreateOptions; import com.arangodb.model.GraphCreateOptions; import com.arangodb.util.TestUtils; @@ -13,18 +14,18 @@ import java.util.Collection; import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; import java.util.stream.Stream; class BaseJunit5 { protected static final DbName TEST_DB = DbName.of("java_driver_test_db"); - - private static final List adbs = Arrays.stream(Protocol.values()) - .map(p -> new ArangoDB.Builder() - .useProtocol(p) - .serializer(new ArangoJack()) - .build()) - .collect(Collectors.toList()); + protected static final ArangoConfigProperties config = ConfigUtils.loadConfig(); + private static final List adbs = Arrays.asList( + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.VST).build(), + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP_VPACK).build(), + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP_JSON).build(), + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP2_VPACK).build(), + new ArangoDB.Builder().loadProperties(config).useProtocol(Protocol.HTTP2_JSON).build() + ); protected static Stream dbsStream() { return adbs.stream().map(adb -> adb.db(TEST_DB)); @@ -86,7 +87,6 @@ static void init() { @AfterAll static void shutdown() { dropDB(TEST_DB); - adbs.forEach(ArangoDB::shutdown); } static String rnd() { diff --git a/src/test/java/com/arangodb/ConcurrencyTests.java b/driver/src/test/java/com/arangodb/ConcurrencyTests.java similarity index 84% rename from src/test/java/com/arangodb/ConcurrencyTests.java rename to driver/src/test/java/com/arangodb/ConcurrencyTests.java index 16c26ac08..3efdacc9c 100644 --- a/src/test/java/com/arangodb/ConcurrencyTests.java +++ b/driver/src/test/java/com/arangodb/ConcurrencyTests.java @@ -1,6 +1,6 @@ package com.arangodb; -import com.arangodb.mapping.ArangoJack; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -18,7 +18,9 @@ class ConcurrencyTests { @EnumSource(Protocol.class) void concurrentPendingRequests(Protocol protocol) throws ExecutionException, InterruptedException { ExecutorService es = Executors.newFixedThreadPool(10); - ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).serializer(new ArangoJack()).build(); + ArangoDB adb = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .useProtocol(protocol).build(); List> futures = IntStream.range(0, 10) .mapToObj(__ -> CompletableFuture.runAsync(() -> adb.db().query("RETURN SLEEP(1)", Void.class), es)) .collect(Collectors.toList()); diff --git a/src/test/java/com/arangodb/DocumentTest.java b/driver/src/test/java/com/arangodb/DocumentTest.java similarity index 87% rename from src/test/java/com/arangodb/DocumentTest.java rename to driver/src/test/java/com/arangodb/DocumentTest.java index 327f07bb8..0ce14ff53 100644 --- a/src/test/java/com/arangodb/DocumentTest.java +++ b/driver/src/test/java/com/arangodb/DocumentTest.java @@ -1,138 +1,138 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.DocumentCreateEntity; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.Map; -import java.util.UUID; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class DocumentTest extends BaseJunit5 { - - private static final String COLLECTION_NAME = "DocumentTest_collection"; - - private static Stream cols() { - return dbsStream() - .map(db -> db.collection(COLLECTION_NAME)) - .map(Arguments::of); - } - - - @BeforeAll - static void init() { - initCollections(COLLECTION_NAME); - } - - @SuppressWarnings("unchecked") - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertAsJson(ArangoCollection collection) { - //@formatter:off - final String json = - "{" - + "\"article\": {" - + "\"artist\": \"PREGARDIEN/RHEINISCHE KANTOREI/DAS\"," - + "\"releaseDate\": \"1970-01-01\"," - + "\"composer\": \"BACH\"," - + "\"format\": \"CD\"," - + "\"vat\": \"H\"," - + "\"carriers\": 1," - + "\"label\": \"CAPRICCIO\"," - + "\"title\": \"BACH ST MATTHEW PASSION BWV244\"," - + "\"barcode\": [" - + "\"4006408600466\"" - + "]," - + "\"conductor\": \"MAX, H.\"" - + "}," - + "\"stock\": {" - + "\"status\": \"RMV\"," - + "\"lastUpdate\": \"2016-11-01 00:00\"" - + "}" - + "}"; - //@formatter:on - final DocumentCreateEntity createResult = collection.insertDocument(json); - final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); - assertThat(doc).isNotNull(); - final Object article = doc.getAttribute("article"); - assertThat(article).isNotNull(); - final Object artist = ((Map) article).get("artist"); - assertThat(artist).isNotNull(); - assertThat(artist.toString()).isEqualTo("PREGARDIEN/RHEINISCHE KANTOREI/DAS"); - } - - @SuppressWarnings("unchecked") - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void insertAsBaseDocument(ArangoCollection collection) { - final BaseDocument document = new BaseDocument(); - { - final BaseDocument article = new BaseDocument(); - document.addAttribute("article", article); - article.addAttribute("artist", "PREGARDIEN/RHEINISCHE KANTOREI/DAS"); - article.addAttribute("releaseDate", "1970-01-01"); - article.addAttribute("composer", "BACH"); - article.addAttribute("format", "CD"); - article.addAttribute("vat", "H"); - article.addAttribute("carriers", 1); - article.addAttribute("label", "CAPRICCIO"); - article.addAttribute("title", "BACH ST MATTHEW PASSION BWV244"); - article.addAttribute("barcode", new String[]{"4006408600466"}); - article.addAttribute("conductor", "MAX, H."); - final BaseDocument stock = new BaseDocument(); - document.addAttribute("stock", stock); - stock.addAttribute("status", "RMV"); - stock.addAttribute("lastUpdate", "2016-11-01 00:00"); - } - final DocumentCreateEntity createResult = collection.insertDocument(document); - final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); - assertThat(doc).isNotNull(); - final Object article = doc.getAttribute("article"); - assertThat(article).isNotNull(); - final Object artist = ((Map) article).get("artist"); - assertThat(artist).isNotNull(); - assertThat(artist.toString()).isEqualTo("PREGARDIEN/RHEINISCHE KANTOREI/DAS"); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("cols") - void documentKeyWithSpecialChars(ArangoCollection collection) { - final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); - final BaseDocument document = new BaseDocument(key); - final DocumentCreateEntity createResult = collection.insertDocument(document); - final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); - assertThat(doc).isNotNull(); - assertThat(doc.getKey()).isEqualTo(key); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.DocumentCreateEntity; +import com.arangodb.util.RawJson; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Map; +import java.util.UUID; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +class DocumentTest extends BaseJunit5 { + + private static final String COLLECTION_NAME = "DocumentTest_collection"; + + private static Stream cols() { + return dbsStream() + .map(db -> db.collection(COLLECTION_NAME)) + .map(Arguments::of); + } + + + @BeforeAll + static void init() { + initCollections(COLLECTION_NAME); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertAsJson(ArangoCollection collection) { + //@formatter:off + final RawJson json = RawJson.of( + "{" + + "\"article\": {" + + "\"artist\": \"PREGARDIEN/RHEINISCHE KANTOREI/DAS\"," + + "\"releaseDate\": \"1970-01-01\"," + + "\"composer\": \"BACH\"," + + "\"format\": \"CD\"," + + "\"vat\": \"H\"," + + "\"carriers\": 1," + + "\"label\": \"CAPRICCIO\"," + + "\"title\": \"BACH ST MATTHEW PASSION BWV244\"," + + "\"barcode\": [" + + "\"4006408600466\"" + + "]," + + "\"conductor\": \"MAX, H.\"" + + "}," + + "\"stock\": {" + + "\"status\": \"RMV\"," + + "\"lastUpdate\": \"2016-11-01 00:00\"" + + "}" + + "}" + ); + //@formatter:on + final DocumentCreateEntity createResult = collection.insertDocument(json); + final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); + assertThat(doc).isNotNull(); + final Object article = doc.getAttribute("article"); + assertThat(article).isNotNull(); + final Object artist = ((Map) article).get("artist"); + assertThat(artist).isNotNull(); + assertThat(artist.toString()).isEqualTo("PREGARDIEN/RHEINISCHE KANTOREI/DAS"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertAsBaseDocument(ArangoCollection collection) { + final BaseDocument document = new BaseDocument(UUID.randomUUID().toString()); + { + final BaseDocument article = new BaseDocument(UUID.randomUUID().toString()); + document.addAttribute("article", article); + article.addAttribute("artist", "PREGARDIEN/RHEINISCHE KANTOREI/DAS"); + article.addAttribute("releaseDate", "1970-01-01"); + article.addAttribute("composer", "BACH"); + article.addAttribute("format", "CD"); + article.addAttribute("vat", "H"); + article.addAttribute("carriers", 1); + article.addAttribute("label", "CAPRICCIO"); + article.addAttribute("title", "BACH ST MATTHEW PASSION BWV244"); + article.addAttribute("barcode", new String[]{"4006408600466"}); + article.addAttribute("conductor", "MAX, H."); + final BaseDocument stock = new BaseDocument(UUID.randomUUID().toString()); + document.addAttribute("stock", stock); + stock.addAttribute("status", "RMV"); + stock.addAttribute("lastUpdate", "2016-11-01 00:00"); + } + final DocumentCreateEntity createResult = collection.insertDocument(document); + final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); + assertThat(doc).isNotNull(); + final Object article = doc.getAttribute("article"); + assertThat(article).isNotNull(); + final Object artist = ((Map) article).get("artist"); + assertThat(artist).isNotNull(); + assertThat(artist.toString()).isEqualTo("PREGARDIEN/RHEINISCHE KANTOREI/DAS"); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void documentKeyWithSpecialChars(ArangoCollection collection) { + final String key = "_-:.@()+,=;$!*'%" + UUID.randomUUID(); + final BaseDocument document = new BaseDocument(key); + final DocumentCreateEntity createResult = collection.insertDocument(document); + final BaseDocument doc = collection.getDocument(createResult.getKey(), BaseDocument.class); + assertThat(doc).isNotNull(); + assertThat(doc.getKey()).isEqualTo(key); + } + +} diff --git a/driver/src/test/java/com/arangodb/InvertedIndexTest.java b/driver/src/test/java/com/arangodb/InvertedIndexTest.java new file mode 100644 index 000000000..e96bc70ef --- /dev/null +++ b/driver/src/test/java/com/arangodb/InvertedIndexTest.java @@ -0,0 +1,194 @@ +package com.arangodb; + +import com.arangodb.entity.*; +import com.arangodb.entity.arangosearch.*; +import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer; +import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties; +import com.arangodb.model.InvertedIndexOptions; +import com.arangodb.model.PersistentIndexOptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.*; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +public class InvertedIndexTest extends BaseJunit5 { + + private static final String COLLECTION_NAME = "InvertedIndexTest_collection"; + + private static Stream cols() { + return dbsStream().map(db -> db.collection(COLLECTION_NAME)).map(Arguments::of); + } + + @BeforeAll + static void init() { + initCollections(COLLECTION_NAME); + } + + private void createAnalyzer(String analyzerName, ArangoDatabase db) { + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + DelimiterAnalyzer da = new DelimiterAnalyzer(); + da.setName(analyzerName); + da.setFeatures(features); + DelimiterAnalyzerProperties props = new DelimiterAnalyzerProperties(); + props.setDelimiter("-"); + da.setProperties(props); + + db.createSearchAnalyzer(da); + } + + private InvertedIndexOptions createOptions(String analyzerName) { + InvertedIndexField field = new InvertedIndexField() + .name("foo") + .analyzer(AnalyzerType.identity.toString()) + .includeAllFields(true) + .searchField(false) + .trackListPositions(false) + .features( + AnalyzerFeature.position, + AnalyzerFeature.frequency, + AnalyzerFeature.norm, + AnalyzerFeature.offset + ); + + if (isEnterprise()) { + field.nested( + new InvertedIndexField() + .name("bar") + .analyzer(analyzerName) + .searchField(true) + .features(AnalyzerFeature.position, AnalyzerFeature.frequency) + .nested( + new InvertedIndexField() + .name("baz") + .analyzer(AnalyzerType.identity.toString()) + .searchField(false) + .features(AnalyzerFeature.frequency) + ) + ); + } + + return new InvertedIndexOptions() + .name("invertedIndex-" + UUID.randomUUID()) + .inBackground(true) + .parallelism(5) + .primarySort(new InvertedIndexPrimarySort() + .fields( + new InvertedIndexPrimarySort.Field("f1", InvertedIndexPrimarySort.Field.Direction.asc), + new InvertedIndexPrimarySort.Field("f2", InvertedIndexPrimarySort.Field.Direction.desc) + ) + .compression(ArangoSearchCompression.lz4) + ) + .storedValues(new StoredValue(Arrays.asList("f3", "f4"), ArangoSearchCompression.none)) + .analyzer(analyzerName) + .features(AnalyzerFeature.position, AnalyzerFeature.frequency) + .includeAllFields(false) + .trackListPositions(true) + .searchField(true) + .fields(field) + .consolidationIntervalMsec(11L) + .commitIntervalMsec(22L) + .cleanupIntervalStep(33L) + .consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.TIER) + .segmentsMin(3L) + .segmentsMax(44L) + .segmentsBytesMax(55555L) + .segmentsBytesFloor(666L) + .minScore(77L) + ) + .writebufferIdle(44L) + .writebufferActive(55L) + .writebufferSizeMax(66L); + } + + private void assertCorrectIndexEntity(InvertedIndexEntity indexResult, InvertedIndexOptions options) { + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getId()).isNotNull().isNotEmpty(); + // FIXME: in single server this is null + // assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getVersion()).isNotNull(); + assertThat(indexResult.getCode()).isNotNull(); + assertThat(indexResult.getType()).isEqualTo(IndexType.inverted); + assertThat(indexResult.getName()).isEqualTo(options.getName()); + assertThat(indexResult.getFields()).containsExactlyElementsOf(options.getFields()); + assertThat(indexResult.getSearchField()).isEqualTo(options.getSearchField()); + assertThat(indexResult.getStoredValues()).containsExactlyElementsOf(options.getStoredValues()); + assertThat(indexResult.getPrimarySort()).isEqualTo(options.getPrimarySort()); + assertThat(indexResult.getAnalyzer()).isEqualTo(options.getAnalyzer()); + assertThat(indexResult.getFeatures()).hasSameElementsAs(options.getFeatures()); + assertThat(indexResult.getIncludeAllFields()).isEqualTo(options.getIncludeAllFields()); + assertThat(indexResult.getTrackListPositions()).isEqualTo(options.getTrackListPositions()); + assertThat(indexResult.getCleanupIntervalStep()).isEqualTo(options.getCleanupIntervalStep()); + assertThat(indexResult.getCommitIntervalMsec()).isEqualTo(options.getCommitIntervalMsec()); + assertThat(indexResult.getConsolidationIntervalMsec()).isEqualTo(options.getConsolidationIntervalMsec()); + assertThat(indexResult.getConsolidationPolicy()).isEqualTo(options.getConsolidationPolicy()); + assertThat(indexResult.getWritebufferIdle()).isEqualTo(options.getWritebufferIdle()); + assertThat(indexResult.getWritebufferActive()).isEqualTo(options.getWritebufferActive()); + assertThat(indexResult.getWritebufferSizeMax()).isEqualTo(options.getWritebufferSizeMax()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void createAndGetInvertedIndex(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options); + assertCorrectIndexEntity(created, options); + InvertedIndexEntity loadedIndex = collection.getInvertedIndex(created.getName()); + assertCorrectIndexEntity(loadedIndex, options); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getInvertedIndexesShouldNotReturnOtherIndexTypes(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + // create persistent index + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); + + // create inverted index + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options); + + Collection loadedIndexes = collection.getInvertedIndexes(); + assertThat(loadedIndexes).map(InvertedIndexEntity::getName) + .doesNotContain("persistentIndex") + .contains(created.getName()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void getIndexesShouldNotReturnInvertedIndexes(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 10)); + + // create persistent index + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); + + // create inverted index + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options); + + Collection loadedIndexes = collection.getIndexes(); + assertThat(loadedIndexes).map(IndexEntity::getName) + .doesNotContain(created.getName()) + .contains("persistentIndex"); + } + +} diff --git a/src/test/java/com/arangodb/JwtAuthTest.java b/driver/src/test/java/com/arangodb/JwtAuthTest.java similarity index 75% rename from src/test/java/com/arangodb/JwtAuthTest.java rename to driver/src/test/java/com/arangodb/JwtAuthTest.java index 6c0c3029f..d2127e7ba 100644 --- a/src/test/java/com/arangodb/JwtAuthTest.java +++ b/driver/src/test/java/com/arangodb/JwtAuthTest.java @@ -1,10 +1,6 @@ package com.arangodb; -import com.arangodb.mapping.ArangoJack; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; -import com.arangodb.velocystream.Response; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -14,6 +10,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; /** @@ -25,11 +22,29 @@ class JwtAuthTest { @BeforeAll static void init() { - ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); jwt = getJwt(arangoDB); arangoDB.shutdown(); } + private static String getJwt(ArangoDB arangoDB) { + Map reqBody = new HashMap<>(); + reqBody.put("username", "root"); + reqBody.put("password", "test"); + + Request req = Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.POST) + .path("/_open/auth") + .body(reqBody) + .build(); + + Response resp = arangoDB.execute(req, Map.class); + return (String) resp.getBody().get("jwt"); + } + @ParameterizedTest @EnumSource(Protocol.class) void notAuthenticated(Protocol protocol) { @@ -54,13 +69,11 @@ void authenticated(Protocol protocol) { @ParameterizedTest @EnumSource(Protocol.class) void updateJwt(Protocol protocol) { + assumeTrue(protocol != Protocol.VST, "DE-423"); ArangoDB arangoDB = getBuilder(protocol) .jwt(jwt) .build(); arangoDB.getVersion(); - if (protocol == Protocol.VST) { - arangoDB.shutdown(); - } arangoDB.updateJwt("bla"); Throwable thrown = catchThrowable(arangoDB::getVersion); @@ -75,24 +88,10 @@ void updateJwt(Protocol protocol) { private ArangoDB.Builder getBuilder(Protocol protocol) { return new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) .useProtocol(protocol) - .serializer(new ArangoJack()) .jwt(null) // unset credentials from properties file .user(null) // unset credentials from properties file .password(null); // unset credentials from properties file } - - private static String getJwt(ArangoDB arangoDB) { - ArangoSerialization serde = arangoDB.util(); - Map reqBody = new HashMap<>(); - reqBody.put("username", "root"); - reqBody.put("password", "test"); - - Request req = new Request(DbName.SYSTEM, RequestType.POST, "/_open/auth"); - req.setBody(serde.serialize(reqBody)); - - Response resp = arangoDB.execute(req); - Map respBody = serde.deserialize(resp.getBody(), Map.class); - return respBody.get("jwt"); - } } diff --git a/driver/src/test/java/com/arangodb/PackageVersionTest.java b/driver/src/test/java/com/arangodb/PackageVersionTest.java new file mode 100644 index 000000000..b77408364 --- /dev/null +++ b/driver/src/test/java/com/arangodb/PackageVersionTest.java @@ -0,0 +1,41 @@ +package com.arangodb; + +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +class PackageVersionTest extends BaseJunit5 { + + private static final String EXPECTED_VERSION = "7.0.0-ALPHA.2"; + + @Test + void packageVersion() { + assertThat(PackageVersion.VERSION).isEqualTo(EXPECTED_VERSION); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void userAgentHeader(Protocol protocol) { + assumeTrue(protocol != Protocol.VST); + ArangoDB adb = new ArangoDB.Builder() + .loadProperties(config) + .useProtocol(protocol) + .build(); + + Response resp = adb.execute(Request.builder() + .method(Request.Method.GET) + .path("/_admin/echo") + .build(), JsonNode.class); + String headerValue = resp.getBody().get("headers").get("x-arango-driver").textValue(); + + String jvmVersion = System.getProperty("java.specification.version"); + String expected = "JavaDriver/" + PackageVersion.VERSION + " (JVM/" + jvmVersion + ")"; + + assertThat(headerValue).isEqualTo(expected); + adb.shutdown(); + } +} diff --git a/driver/src/test/java/com/arangodb/ParallelTest.java b/driver/src/test/java/com/arangodb/ParallelTest.java new file mode 100644 index 000000000..9c4b98f96 --- /dev/null +++ b/driver/src/test/java/com/arangodb/ParallelTest.java @@ -0,0 +1,42 @@ +package com.arangodb; + +import com.arangodb.config.ConfigUtils; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +class ParallelTest { + + @ParameterizedTest(name = "{index}") + @EnumSource(Protocol.class) + void connectionParallelism(Protocol protocol) throws InterruptedException { + // test that connections are internally async and can have multiple pending requests + // BTS-1102: the server does not run pipelined HTTP/1.1 requests in parallel + assumeTrue(protocol != Protocol.HTTP_JSON && protocol != Protocol.HTTP_VPACK); + ArangoDB adb = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .useProtocol(protocol) + .maxConnections(1) + .build(); + + ExecutorService es = Executors.newFixedThreadPool(3); + List> tasks = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + tasks.add(es.submit(() -> adb.db().query("return sleep(1)", Void.class))); + } + + Thread.sleep(2_000); + assertThat(tasks).allMatch(Future::isDone); + adb.shutdown(); + es.shutdown(); + } + +} diff --git a/driver/src/test/java/com/arangodb/SerializableTest.java b/driver/src/test/java/com/arangodb/SerializableTest.java new file mode 100644 index 000000000..17b1ec1da --- /dev/null +++ b/driver/src/test/java/com/arangodb/SerializableTest.java @@ -0,0 +1,65 @@ +package com.arangodb; + +import com.arangodb.entity.ErrorEntity; +import com.arangodb.internal.net.ArangoDBRedirectException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import org.junit.jupiter.api.Test; + +import java.io.*; +import java.util.Collections; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class SerializableTest { + + @Test + void serializeArangoDBException() throws IOException, ClassNotFoundException { + ObjectMapper mapper = new ObjectMapper(); + JsonNode jn = JsonNodeFactory.instance.objectNode() + .put("errorMessage", "boomError") + .put("exception", "boomException") + .put("code", 11) + .put("errorNum", 22); + ErrorEntity ee = mapper.readerFor(ErrorEntity.class).readValue(jn); + ArangoDBException e = new ArangoDBException(ee); + + ArangoDBException e2 = roundTrip(e); + assertThat(e2.getException()).isEqualTo(e.getException()); + assertThat(e2.getResponseCode()).isEqualTo(e.getResponseCode()); + assertThat(e2.getErrorNum()).isEqualTo(e.getErrorNum()); + assertThat(e2.getRequestId()).isEqualTo(e.getRequestId()); + } + + @Test + void serializeArangoDBRedirectException() throws IOException, ClassNotFoundException { + ArangoDBRedirectException e = new ArangoDBRedirectException("foo", "bar"); + ArangoDBRedirectException e2 = roundTrip(e); + assertThat(e2.getMessage()).isEqualTo(e.getMessage()); + assertThat(e2.getLocation()).isEqualTo(e.getLocation()); + } + + @Test + void serializeArangoDBMultipleException() throws IOException, ClassNotFoundException { + List exceptions = Collections.singletonList(new RuntimeException("foo")); + ArangoDBMultipleException e = new ArangoDBMultipleException(exceptions); + ArangoDBMultipleException e2 = roundTrip(e); + assertThat(e2.getExceptions()).hasSize(1); + assertThat(e2.getExceptions().iterator().next().getMessage()).isEqualTo("foo"); + } + + private T roundTrip(T input) throws IOException, ClassNotFoundException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(os); + objectOutputStream.writeObject(input); + + InputStream is = new ByteArrayInputStream(os.toByteArray()); + ObjectInputStream objectInputStream = new ObjectInputStream(is); + T output = (T) objectInputStream.readObject(); + objectInputStream.close(); + + return output; + } +} diff --git a/src/test/java/com/arangodb/StreamTransactionConflictsTest.java b/driver/src/test/java/com/arangodb/StreamTransactionConflictsTest.java similarity index 100% rename from src/test/java/com/arangodb/StreamTransactionConflictsTest.java rename to driver/src/test/java/com/arangodb/StreamTransactionConflictsTest.java diff --git a/src/test/java/com/arangodb/StreamTransactionGraphTest.java b/driver/src/test/java/com/arangodb/StreamTransactionGraphTest.java similarity index 93% rename from src/test/java/com/arangodb/StreamTransactionGraphTest.java rename to driver/src/test/java/com/arangodb/StreamTransactionGraphTest.java index 039d2d86c..e4d73fa33 100644 --- a/src/test/java/com/arangodb/StreamTransactionGraphTest.java +++ b/driver/src/test/java/com/arangodb/StreamTransactionGraphTest.java @@ -28,6 +28,7 @@ import org.junit.jupiter.params.provider.MethodSource; import java.util.Collections; +import java.util.UUID; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; @@ -67,8 +68,10 @@ static void init() { private BaseEdgeDocument createEdgeValue(String streamTransactionId, ArangoGraph graph) { ArangoVertexCollection vertexCollection1 = graph.vertexCollection(VERTEX_COLLECTION_1); ArangoVertexCollection vertexCollection2 = graph.vertexCollection(VERTEX_COLLECTION_2); - VertexEntity v1 = vertexCollection1.insertVertex(new BaseDocument(), new VertexCreateOptions().streamTransactionId(streamTransactionId)); - VertexEntity v2 = vertexCollection2.insertVertex(new BaseDocument(), new VertexCreateOptions().streamTransactionId(streamTransactionId)); + VertexEntity v1 = vertexCollection1.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(streamTransactionId)); + VertexEntity v2 = vertexCollection2.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(streamTransactionId)); BaseEdgeDocument value = new BaseEdgeDocument(); value.setFrom(v1.getId()); value.setTo(v2.getId()); @@ -113,7 +116,8 @@ void createVertex(ArangoVertexCollection vertexCollection1) { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); // insert a vertex from within the tx - VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument(), new VertexCreateOptions().streamTransactionId(tx.getId())); + VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(tx.getId())); // assert that the vertex is not found from outside the tx assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null)).isNull(); @@ -135,7 +139,7 @@ void replaceVertex(ArangoVertexCollection vertexCollection1) { assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("test", "foo"); VertexEntity createdVertex = vertexCollection1.insertVertex(doc, null); @@ -147,8 +151,7 @@ void replaceVertex(ArangoVertexCollection vertexCollection1) { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); // replace vertex from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); vertexCollection1.replaceVertex(createdVertex.getKey(), doc, new VertexReplaceOptions().streamTransactionId(tx.getId())); @@ -158,7 +161,8 @@ void replaceVertex(ArangoVertexCollection vertexCollection1) { // assert that the vertex has been replaced from within the tx assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" + , "bar"); db.commitStreamTransaction(tx.getId()); @@ -174,7 +178,7 @@ void updateVertex(ArangoVertexCollection vertexCollection1) { assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("test", "foo"); VertexEntity createdDoc = vertexCollection1.insertVertex(doc, null); @@ -186,9 +190,9 @@ void updateVertex(ArangoVertexCollection vertexCollection1) { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); // update vertex from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); - vertexCollection1.updateVertex(createdDoc.getKey(), doc, new VertexUpdateOptions().streamTransactionId(tx.getId())); + doc.updateAttribute("test", "bar"); + vertexCollection1.updateVertex(createdDoc.getKey(), doc, + new VertexUpdateOptions().streamTransactionId(tx.getId())); // assert that the vertex has not been updated from outside the tx assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null) @@ -196,7 +200,8 @@ void updateVertex(ArangoVertexCollection vertexCollection1) { // assert that the vertex has been updated from within the tx assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" + , "bar"); db.commitStreamTransaction(tx.getId()); @@ -275,7 +280,8 @@ void createEdge(ArangoEdgeCollection edgeCollection) { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); // insert an edge from within the tx - EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(tx.getId(), edgeCollection.graph()), new EdgeCreateOptions().streamTransactionId(tx.getId())); + EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(tx.getId(), edgeCollection.graph()), + new EdgeCreateOptions().streamTransactionId(tx.getId())); // assert that the edge is not found from outside the tx assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null)).isNull(); @@ -309,8 +315,7 @@ void replaceEdge(ArangoEdgeCollection edgeCollection) { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); // replace edge from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); edgeCollection.replaceEdge(createdEdge.getKey(), doc, new EdgeReplaceOptions().streamTransactionId(tx.getId())); @@ -320,7 +325,8 @@ void replaceEdge(ArangoEdgeCollection edgeCollection) { // assert that the edge has been replaced from within the tx assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" + , "bar"); db.commitStreamTransaction(tx.getId()); @@ -348,8 +354,7 @@ void updateEdge(ArangoEdgeCollection edgeCollection) { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)); // update edge from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); edgeCollection.updateEdge(createdDoc.getKey(), doc, new EdgeUpdateOptions().streamTransactionId(tx.getId())); // assert that the edge has not been updated from outside the tx @@ -358,7 +363,8 @@ void updateEdge(ArangoEdgeCollection edgeCollection) { // assert that the edge has been updated from within the tx assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test" + , "bar"); db.commitStreamTransaction(tx.getId()); diff --git a/src/test/java/com/arangodb/StreamTransactionTest.java b/driver/src/test/java/com/arangodb/StreamTransactionTest.java similarity index 94% rename from src/test/java/com/arangodb/StreamTransactionTest.java rename to driver/src/test/java/com/arangodb/StreamTransactionTest.java index 4330b13fd..3b47d9222 100644 --- a/src/test/java/com/arangodb/StreamTransactionTest.java +++ b/driver/src/test/java/com/arangodb/StreamTransactionTest.java @@ -26,6 +26,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import java.io.IOException; import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -375,7 +376,7 @@ void replaceDocument(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("test", "foo"); ArangoCollection collection = db.collection(COLLECTION_NAME); @@ -385,8 +386,7 @@ void replaceDocument(ArangoDatabase db) { new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); // replace document from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); collection.replaceDocument(createdDoc.getKey(), doc, new DocumentReplaceOptions().streamTransactionId(tx.getId())); @@ -396,7 +396,8 @@ void replaceDocument(ArangoDatabase db) { // assert that the document has been replaced from within the tx assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, - new DocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", "bar"); + new DocumentReadOptions().streamTransactionId(tx.getId())).getProperties()).containsEntry("test", + "bar"); db.commitStreamTransaction(tx.getId()); @@ -426,8 +427,7 @@ void replaceDocuments(ArangoDatabase db) { new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); List modifiedDocs = createdDocs.stream().peek(doc -> { - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); }).collect(Collectors.toList()); // replace document from within the tx @@ -460,7 +460,7 @@ void updateDocument(ArangoDatabase db) { assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("test", "foo"); ArangoCollection collection = db.collection(COLLECTION_NAME); @@ -470,8 +470,7 @@ void updateDocument(ArangoDatabase db) { new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); // update document from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); collection .updateDocument(createdDoc.getKey(), doc, new DocumentUpdateOptions().streamTransactionId(tx.getId())); @@ -513,8 +512,7 @@ void updateDocuments(ArangoDatabase db) { new StreamTransactionOptions().readCollections(COLLECTION_NAME).writeCollections(COLLECTION_NAME)); List modifiedDocs = createdDocs.stream().peek(doc -> { - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); }).collect(Collectors.toList()); // update documents from within the tx @@ -556,7 +554,7 @@ void deleteDocument(ArangoDatabase db) { // delete document from within the tx collection - .deleteDocument(createdDoc.getKey(), null, new DocumentDeleteOptions().streamTransactionId(tx.getId())); + .deleteDocument(createdDoc.getKey(), new DocumentDeleteOptions().streamTransactionId(tx.getId())); // assert that the document has not been deleted from outside the tx assertThat(collection.getDocument(createdDoc.getKey(), BaseDocument.class, null)).isNotNull(); @@ -580,7 +578,7 @@ void deleteDocuments(ArangoDatabase db) { ArangoCollection collection = db.collection(COLLECTION_NAME); List keys = collection - .insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument(), new BaseDocument()), null) + .insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument(), new BaseDocument())) .getDocuments().stream().map(DocumentEntity::getKey).collect(Collectors.toList()); StreamTransactionEntity tx = db.beginStreamTransaction( @@ -588,7 +586,7 @@ void deleteDocuments(ArangoDatabase db) { // delete document from within the tx collection - .deleteDocuments(keys, null, new DocumentDeleteOptions().streamTransactionId(tx.getId())); + .deleteDocuments(keys, new DocumentDeleteOptions().streamTransactionId(tx.getId())); // assert that the documents has not been deleted from outside the tx assertThat(collection.getDocuments(keys, BaseDocument.class, null).getDocuments()).hasSize(keys.size()); @@ -756,7 +754,7 @@ void getStreamTransactions(ArangoDatabase db) { assertThat(gotTxs).hasSameSizeAs(createdIds); assertThat(gotTxs.stream() - .allMatch(it -> it.getStatus() == StreamTransactionStatus.running)).isTrue(); + .allMatch(it -> it.getState() == StreamTransactionStatus.running)).isTrue(); db.abortStreamTransaction(tx1.getId()); db.abortStreamTransaction(tx2.getId()); @@ -788,4 +786,35 @@ void transactionAllowImplicitFalse(ArangoDatabase db) { db.abortStreamTransaction(tx.getId()); } + + @ParameterizedTest(name = "{index}") + @MethodSource("dbs") + void transactionDirtyRead(ArangoDatabase db) throws IOException { + assumeTrue(isCluster()); + assumeTrue(isAtLeastVersion(3, 10)); + + ArangoCollection collection = db.collection(COLLECTION_NAME); + DocumentCreateEntity doc = collection.insertDocument(new BaseDocument()); + + StreamTransactionEntity tx = db + .beginStreamTransaction(new StreamTransactionOptions() + .readCollections(COLLECTION_NAME) + .allowDirtyRead(true)); + + MultiDocumentEntity readDocs = collection.getDocuments(Collections.singletonList(doc.getKey()), + BaseDocument.class, + new DocumentReadOptions().streamTransactionId(tx.getId())); + + assertThat(readDocs.isPotentialDirtyRead()).isTrue(); + assertThat(readDocs.getDocuments()).hasSize(1); + + final ArangoCursor cursor = db.query("FOR i IN @@col RETURN i", + Collections.singletonMap("@col", COLLECTION_NAME), + new AqlQueryOptions().streamTransactionId(tx.getId()), BaseDocument.class); + assertThat(cursor.isPotentialDirtyRead()).isTrue(); + cursor.close(); + + db.abortStreamTransaction(tx.getId()); + } + } diff --git a/src/test/java/com/arangodb/async/ArangoCollectionTest.java b/driver/src/test/java/com/arangodb/async/ArangoCollectionTest.java similarity index 84% rename from src/test/java/com/arangodb/async/ArangoCollectionTest.java rename to driver/src/test/java/com/arangodb/async/ArangoCollectionTest.java index 541d147ae..1e7bfd36a 100644 --- a/src/test/java/com/arangodb/async/ArangoCollectionTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoCollectionTest.java @@ -22,8 +22,15 @@ import com.arangodb.ArangoDBException; import com.arangodb.entity.*; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; import com.arangodb.model.DocumentImportOptions.OnDuplicate; +import com.arangodb.serde.jackson.JacksonSerde; +import com.arangodb.serde.jackson.Key; +import com.arangodb.util.RawData; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -102,6 +109,40 @@ void insertDocumentReturnNew() throws InterruptedException, ExecutionException { .get(); } + @Test + void insertDocumentWithTypeOverwriteModeReplace() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); + assumeTrue(db.getSerde().getUserSerde() instanceof JacksonSerde, "polymorphic deserialization support " + + "required"); + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + String key = UUID.randomUUID().toString(); + Dog dog = new Dog(key, "Teddy"); + Cat cat = new Cat(key, "Luna"); + + final DocumentCreateOptions options = new DocumentCreateOptions() + .returnNew(true) + .returnOld(true) + .overwriteMode(OverwriteMode.replace); + collection.insertDocument(dog, options).get(); + final DocumentCreateEntity doc = collection.insertDocument(cat, options, Animal.class).get(); + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull().isEqualTo(key); + assertThat(doc.getRev()).isNotNull(); + + assertThat(doc.getOld()) + .isNotNull() + .isInstanceOf(Dog.class); + assertThat(doc.getOld().getKey()).isEqualTo(key); + assertThat(doc.getOld().getName()).isEqualTo("Teddy"); + + assertThat(doc.getNew()) + .isNotNull() + .isInstanceOf(Cat.class); + assertThat(doc.getNew().getKey()).isEqualTo(key); + assertThat(doc.getNew().getName()).isEqualTo("Luna"); + } + @Test void insertDocumentWaitForSync() throws InterruptedException, ExecutionException { final DocumentCreateOptions options = new DocumentCreateOptions().waitForSync(true); @@ -120,7 +161,7 @@ void insertDocumentWaitForSync() throws InterruptedException, ExecutionException @Test void insertDocumentAsJson() throws InterruptedException, ExecutionException { db.collection(COLLECTION_NAME) - .insertDocument("{\"_key\":\"docRaw\",\"a\":\"test\"}", null) + .insertDocument(RawJson.of("{\"_key\":\"docRaw\",\"a\":\"test\"}"), null) .whenComplete((doc, ex) -> { assertThat(doc).isNotNull(); assertThat(doc.getId()).isNotNull(); @@ -195,11 +236,11 @@ void getDocumentIfNoneMatchFail() throws InterruptedException, ExecutionExceptio @Test void getDocumentAsJson() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).insertDocument("{\"_key\":\"docRaw\",\"a\":\"test\"}", null).get(); - db.collection(COLLECTION_NAME).getDocument("docRaw", String.class, null) + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"docRaw\",\"a\":\"test\"}")).get(); + db.collection(COLLECTION_NAME).getDocument("docRaw", RawJson.class) .whenComplete((readResult, ex) -> { - assertThat(readResult.contains("\"_key\":\"docRaw\"")).isEqualTo(true); - assertThat(readResult.contains("\"_id\":\"db_collection_test/docRaw\"")).isEqualTo(true); + assertThat(readResult.getValue().contains("\"_key\":\"docRaw\"")).isEqualTo(true); + assertThat(readResult.getValue().contains("\"_id\":\"db_collection_test/docRaw\"")).isEqualTo(true); }) .get(); } @@ -213,7 +254,8 @@ void getDocumentNotFound() throws InterruptedException, ExecutionException { @Test void getDocumentWrongKey() { - Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).getDocument("no/no", BaseDocument.class)); + Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).getDocument("no/no", + BaseDocument.class)); assertThat(thrown).isInstanceOf(ArangoDBException.class); } @@ -229,7 +271,8 @@ void getDocuments() throws InterruptedException, ExecutionException { assertThat(documents).isNotNull(); assertThat(documents.getDocuments()).hasSize(3); for (final BaseDocument document : documents.getDocuments()) { - assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", COLLECTION_NAME + "/" + "3"); + assertThat(document.getId()).isIn(COLLECTION_NAME + "/" + "1", COLLECTION_NAME + "/" + "2", + COLLECTION_NAME + "/" + "3"); } } @@ -253,7 +296,7 @@ void getDocumentsWrongKey() throws InterruptedException, ExecutionException { @Test void updateDocument() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) @@ -294,7 +337,8 @@ void updateDocumentWithDifferentReturnType() throws ExecutionException, Interrup collection.insertDocument(doc).get(); final DocumentUpdateEntity updateResult = collection - .updateDocument(key, Collections.singletonMap("b", "test"), new DocumentUpdateOptions().returnNew(true), BaseDocument.class).get(); + .updateDocument(key, Collections.singletonMap("b", "test"), + new DocumentUpdateOptions().returnNew(true), BaseDocument.class).get(); assertThat(updateResult).isNotNull(); assertThat(updateResult.getKey()).isEqualTo(key); BaseDocument updated = updateResult.getNew(); @@ -305,7 +349,7 @@ void updateDocumentWithDifferentReturnType() throws ExecutionException, Interrup @Test void updateDocumentIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) @@ -338,7 +382,7 @@ void updateDocumentIfMatch() throws InterruptedException, ExecutionException { @Test void updateDocumentIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) @@ -357,7 +401,7 @@ void updateDocumentIfMatchFail() throws InterruptedException, ExecutionException @Test void updateDocumentReturnNew() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); @@ -382,7 +426,7 @@ void updateDocumentReturnNew() throws InterruptedException, ExecutionException { @Test void updateDocumentReturnOld() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); @@ -406,7 +450,7 @@ void updateDocumentReturnOld() throws InterruptedException, ExecutionException { @Test void updateDocumentKeepNullTrue() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); @@ -429,7 +473,7 @@ void updateDocumentKeepNullTrue() throws InterruptedException, ExecutionExceptio @Test void updateDocumentKeepNullFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); @@ -452,10 +496,9 @@ void updateDocumentKeepNullFalse() throws InterruptedException, ExecutionExcepti assertThat(readResult.getProperties().keySet()).doesNotContain("a"); } - @SuppressWarnings("unchecked") @Test void updateDocumentMergeObjectsTrue() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final Map a = new HashMap<>(); a.put("a", "test"); doc.addAttribute("a", a); @@ -484,10 +527,9 @@ void updateDocumentMergeObjectsTrue() throws InterruptedException, ExecutionExce assertThat(aMap).containsKey("b"); } - @SuppressWarnings("unchecked") @Test void updateDocumentMergeObjectsFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final Map a = new HashMap<>(); a.put("a", "test"); doc.addAttribute("a", a); @@ -518,7 +560,7 @@ void updateDocumentMergeObjectsFalse() throws InterruptedException, ExecutionExc @Test void updateDocumentIgnoreRevsFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); @@ -535,11 +577,11 @@ void updateDocumentIgnoreRevsFalse() throws InterruptedException, ExecutionExcep @Test void replaceDocument() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final CompletableFuture> f = db.collection(COLLECTION_NAME) .replaceDocument(createResult.getKey(), doc, null); @@ -564,11 +606,11 @@ void replaceDocument() throws InterruptedException, ExecutionException { @Test void replaceDocumentIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch(createResult.getRev()); final CompletableFuture> f = db.collection(COLLECTION_NAME) @@ -592,11 +634,11 @@ void replaceDocumentIfMatch() throws InterruptedException, ExecutionException { @Test void replaceDocumentIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); try { final DocumentReplaceOptions options = new DocumentReplaceOptions().ifMatch("no"); @@ -609,11 +651,11 @@ void replaceDocumentIfMatchFail() throws InterruptedException, ExecutionExceptio @Test void replaceDocumentIgnoreRevsFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); doc.setRevision("no"); try { @@ -627,11 +669,11 @@ void replaceDocumentIgnoreRevsFalse() throws InterruptedException, ExecutionExce @Test void replaceDocumentReturnNew() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().returnNew(true); db.collection(COLLECTION_NAME).replaceDocument(createResult.getKey(), doc, options) @@ -651,11 +693,11 @@ void replaceDocumentReturnNew() throws InterruptedException, ExecutionException @Test void replaceDocumentReturnOld() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final DocumentReplaceOptions options = new DocumentReplaceOptions().returnOld(true); db.collection(COLLECTION_NAME).replaceDocument(createResult.getKey(), doc, options) @@ -675,10 +717,10 @@ void replaceDocumentReturnOld() throws InterruptedException, ExecutionException @Test void deleteDocument() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); - db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), null, null).get(); + db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey()).get(); db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, null) .whenComplete((document, ex) -> assertThat(document).isNull()) .get(); @@ -686,12 +728,12 @@ void deleteDocument() throws InterruptedException, ExecutionException { @Test void deleteDocumentReturnOld() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); final DocumentDeleteOptions options = new DocumentDeleteOptions().returnOld(true); - db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), BaseDocument.class, options) + db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), options, BaseDocument.class) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult.getOld()).isNotNull(); assertThat(deleteResult.getOld()).isInstanceOf(BaseDocument.class); @@ -703,11 +745,11 @@ void deleteDocumentReturnOld() throws InterruptedException, ExecutionException { @Test void deleteDocumentIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch(createResult.getRev()); - db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), null, options).get(); + db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), options).get(); db.collection(COLLECTION_NAME).getDocument(createResult.getKey(), BaseDocument.class, null) .whenComplete((document, ex) -> assertThat(document).isNull()) .get(); @@ -715,12 +757,12 @@ void deleteDocumentIfMatch() throws InterruptedException, ExecutionException { @Test void deleteDocumentIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME).insertDocument(doc, null) .get(); final DocumentDeleteOptions options = new DocumentDeleteOptions().ifMatch("no"); try { - db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), null, options).get(); + db.collection(COLLECTION_NAME).deleteDocument(createResult.getKey(), options).get(); fail(); } catch (final ExecutionException e) { assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); @@ -1225,7 +1267,7 @@ void exists() throws InterruptedException, ExecutionException { @Test void truncate() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); db.collection(COLLECTION_NAME).insertDocument(doc, null).get(); final BaseDocument readResult = db.collection(COLLECTION_NAME) .getDocument(doc.getKey(), BaseDocument.class, null).get(); @@ -1250,7 +1292,7 @@ void getCount() throws InterruptedException, ExecutionException { }) .get(); - db.collection(COLLECTION_NAME).insertDocument("{}", null).get(); + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{}"), null).get(); db.collection(COLLECTION_NAME).count() .whenComplete((count, ex) -> assertThat(count.getCount()).isEqualTo(1L)) @@ -1263,7 +1305,7 @@ void documentExists() throws InterruptedException, ExecutionException { .whenComplete((existsNot, ex) -> assertThat(existsNot).isEqualTo(false)) .get(); - db.collection(COLLECTION_NAME).insertDocument("{\"_key\":\"abc\"}", null).get(); + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); db.collection(COLLECTION_NAME).documentExists("abc", null) .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(true)) @@ -1272,8 +1314,8 @@ void documentExists() throws InterruptedException, ExecutionException { @Test void documentExistsIfMatch() throws InterruptedException, ExecutionException { - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) - .insertDocument("{\"_key\":\"abc\"}", null).get(); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) + .insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch(createResult.getRev()); db.collection(COLLECTION_NAME).documentExists("abc", options) .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(true)) @@ -1282,7 +1324,7 @@ void documentExistsIfMatch() throws InterruptedException, ExecutionException { @Test void documentExistsIfMatchFail() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).insertDocument("{\"_key\":\"abc\"}", null).get(); + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); final DocumentExistsOptions options = new DocumentExistsOptions().ifMatch("no"); db.collection(COLLECTION_NAME).documentExists("abc", options) .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(false)) @@ -1291,7 +1333,7 @@ void documentExistsIfMatchFail() throws InterruptedException, ExecutionException @Test void documentExistsIfNoneMatch() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).insertDocument("{\"_key\":\"abc\"}", null).get(); + db.collection(COLLECTION_NAME).insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch("no"); db.collection(COLLECTION_NAME).documentExists("abc", options) .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(true)) @@ -1300,8 +1342,8 @@ void documentExistsIfNoneMatch() throws InterruptedException, ExecutionException @Test void documentExistsIfNoneMatchFail() throws InterruptedException, ExecutionException { - final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) - .insertDocument("{\"_key\":\"abc\"}", null).get(); + final DocumentCreateEntity createResult = db.collection(COLLECTION_NAME) + .insertDocument(RawJson.of("{\"_key\":\"abc\"}")).get(); final DocumentExistsOptions options = new DocumentExistsOptions().ifNoneMatch(createResult.getRev()); db.collection(COLLECTION_NAME).documentExists("abc", options) .whenComplete((exists, ex) -> assertThat(exists).isEqualTo(false)) @@ -1314,7 +1356,7 @@ void insertDocuments() throws InterruptedException, ExecutionException { values.add(new BaseDocument()); values.add(new BaseDocument()); values.add(new BaseDocument()); - db.collection(COLLECTION_NAME).insertDocuments(values, null) + db.collection(COLLECTION_NAME).insertDocuments(values) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); @@ -1329,7 +1371,7 @@ void insertDocuments() throws InterruptedException, ExecutionException { void insertDocumentsOne() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); values.add(new BaseDocument()); - db.collection(COLLECTION_NAME).insertDocuments(values, null) + db.collection(COLLECTION_NAME).insertDocuments(values) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); @@ -1343,7 +1385,7 @@ void insertDocumentsOne() throws InterruptedException, ExecutionException { @Test void insertDocumentsEmpty() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).insertDocuments(values, null) + db.collection(COLLECTION_NAME).insertDocuments(values) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getDocuments()).isNotNull(); @@ -1395,6 +1437,40 @@ void insertDocumentsFail() throws InterruptedException, ExecutionException { .get(); } + @Test + void insertDocumentsRawData() throws ExecutionException, InterruptedException { + final RawData values = RawData.of("[{},{},{}]"); + final MultiDocumentEntity docs = db.collection(COLLECTION_NAME).insertDocuments(values).get(); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + } + + @Test + void insertDocumentsRawDataReturnNew() throws ExecutionException, InterruptedException { + final RawData values = RawData.of("[{\"aaa\":33},{\"aaa\":33},{\"aaa\":33}]"); + final MultiDocumentEntity> docs = + db.collection(COLLECTION_NAME).insertDocuments(values, new DocumentCreateOptions().returnNew(true)).get(); + assertThat(docs).isNotNull(); + assertThat(docs.getDocuments()).isNotNull(); + assertThat(docs.getDocuments()).hasSize(3); + assertThat(docs.getErrors()).isNotNull(); + assertThat(docs.getErrors()).isEmpty(); + + for (final DocumentCreateEntity doc : docs.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("aaa")).isTrue(); + assertThat(jn.get("aaa").intValue()).isEqualTo(33); + } + } + @Test void importDocuments() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); @@ -1439,7 +1515,8 @@ void importDocumentsDuplicateError() throws InterruptedException, ExecutionExcep values.add(new BaseDocument("1")); values.add(new BaseDocument("2")); values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.error)) + db.collection(COLLECTION_NAME).importDocuments(values, +new DocumentImportOptions().onDuplicate(OnDuplicate.error)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1458,7 +1535,8 @@ void importDocumentsDuplicateIgnore() throws InterruptedException, ExecutionExce values.add(new BaseDocument("1")); values.add(new BaseDocument("2")); values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) + db.collection(COLLECTION_NAME).importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1477,7 +1555,8 @@ void importDocumentsDuplicateReplace() throws InterruptedException, ExecutionExc values.add(new BaseDocument("1")); values.add(new BaseDocument("2")); values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) + db.collection(COLLECTION_NAME).importDocuments(values, +new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1496,7 +1575,8 @@ void importDocumentsDuplicateUpdate() throws InterruptedException, ExecutionExce values.add(new BaseDocument("1")); values.add(new BaseDocument("2")); values.add(new BaseDocument("2")); - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.update)) + db.collection(COLLECTION_NAME).importDocuments(values, + new DocumentImportOptions().onDuplicate(OnDuplicate.update)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1601,7 +1681,7 @@ void importDocumentsFromToPrefix() throws InterruptedException, ExecutionExcepti @Test void importDocumentsJson() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1617,7 +1697,7 @@ void importDocumentsJson() throws InterruptedException, ExecutionException { @Test void importDocumentsJsonDuplicateDefaultError() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1633,7 +1713,8 @@ void importDocumentsJsonDuplicateDefaultError() throws InterruptedException, Exe @Test void importDocumentsJsonDuplicateError() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.error)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.error)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1649,7 +1730,8 @@ void importDocumentsJsonDuplicateError() throws InterruptedException, ExecutionE @Test void importDocumentsJsonDuplicateIgnore() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.ignore)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1665,7 +1747,8 @@ void importDocumentsJsonDuplicateIgnore() throws InterruptedException, Execution @Test void importDocumentsJsonDuplicateReplace() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.replace)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1681,7 +1764,8 @@ void importDocumentsJsonDuplicateReplace() throws InterruptedException, Executio @Test void importDocumentsJsonDuplicateUpdate() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().onDuplicate(OnDuplicate.update)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().onDuplicate(OnDuplicate.update)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1698,7 +1782,8 @@ void importDocumentsJsonDuplicateUpdate() throws InterruptedException, Execution void importDocumentsJsonCompleteFail() throws InterruptedException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; try { - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().complete(true)).get(); + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), + new DocumentImportOptions().complete(true)).get(); fail(); } catch (ExecutionException e) { assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); @@ -1709,7 +1794,7 @@ void importDocumentsJsonCompleteFail() throws InterruptedException { @Test void importDocumentsJsonDetails() throws InterruptedException, ExecutionException { final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"},{\"_key\":\"2\"}]"; - db.collection(COLLECTION_NAME).importDocuments(values, new DocumentImportOptions().details(true)) + db.collection(COLLECTION_NAME).importDocuments(RawData.of(values), new DocumentImportOptions().details(true)) .whenComplete((docs, ex) -> { assertThat(docs).isNotNull(); assertThat(docs.getCreated()).isEqualTo(2); @@ -1730,7 +1815,7 @@ void importDocumentsJsonOverwriteFalse() throws InterruptedException, ExecutionE assertThat(collection.count().get().getCount()).isEqualTo(1L); final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"}]"; - collection.importDocuments(values, new DocumentImportOptions().overwrite(false)).get(); + collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(false)).get(); assertThat(collection.count().get().getCount()).isEqualTo(3L); } @@ -1741,7 +1826,7 @@ void importDocumentsJsonOverwriteTrue() throws InterruptedException, ExecutionEx assertThat(collection.count().get().getCount()).isEqualTo(1L); final String values = "[{\"_key\":\"1\"},{\"_key\":\"2\"}]"; - collection.importDocuments(values, new DocumentImportOptions().overwrite(true)).get(); + collection.importDocuments(RawData.of(values), new DocumentImportOptions().overwrite(true)).get(); assertThat(collection.count().get().getCount()).isEqualTo(2L); } @@ -1751,10 +1836,12 @@ void importDocumentsJsonFromToPrefix() throws InterruptedException, ExecutionExc final ArangoCollectionAsync collection = db.collection(COLLECTION_NAME + "_edge"); try { final String[] keys = {"1", "2"}; - final String values = "[{\"_key\":\"1\",\"_from\":\"from\",\"_to\":\"to\"},{\"_key\":\"2\",\"_from\":\"from\",\"_to\":\"to\"}]"; + final String values = "[{\"_key\":\"1\",\"_from\":\"from\",\"_to\":\"to\"},{\"_key\":\"2\"," + + "\"_from\":\"from\",\"_to\":\"to\"}]"; final DocumentImportEntity importResult = collection - .importDocuments(values, new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")).get(); + .importDocuments(RawData.of(values), + new DocumentImportOptions().fromPrefix("foo").toPrefix("bar")).get(); assertThat(importResult).isNotNull(); assertThat(importResult.getCreated()).isEqualTo(2); for (String key : keys) { @@ -1773,24 +1860,24 @@ void importDocumentsJsonFromToPrefix() throws InterruptedException, ExecutionExc void deleteDocumentsByKey() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection keys = new ArrayList<>(); keys.add("1"); keys.add("2"); - db.collection(COLLECTION_NAME).deleteDocuments(keys, null, null) + db.collection(COLLECTION_NAME).deleteDocuments(keys) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isIn("1", "2"); } assertThat(deleteResult.getErrors().size()).isEqualTo(0); @@ -1802,21 +1889,21 @@ void deleteDocumentsByKey() throws InterruptedException, ExecutionException { void deleteDocumentsByDocuments() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); - db.collection(COLLECTION_NAME).deleteDocuments(values, null, null) + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + db.collection(COLLECTION_NAME).deleteDocuments(values) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(2); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isIn("1", "2"); } assertThat(deleteResult.getErrors().size()).isEqualTo(0); @@ -1828,18 +1915,18 @@ void deleteDocumentsByDocuments() throws InterruptedException, ExecutionExceptio void deleteDocumentsByKeyOne() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection keys = new ArrayList<>(); keys.add("1"); - db.collection(COLLECTION_NAME).deleteDocuments(keys, null, null) + db.collection(COLLECTION_NAME).deleteDocuments(keys) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(1); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isEqualTo("1"); } assertThat(deleteResult.getErrors().size()).isEqualTo(0); @@ -1851,16 +1938,16 @@ void deleteDocumentsByKeyOne() throws InterruptedException, ExecutionException { void deleteDocumentsByDocumentOne() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); - db.collection(COLLECTION_NAME).deleteDocuments(values, null, null) + db.collection(COLLECTION_NAME).insertDocuments(values).get(); + db.collection(COLLECTION_NAME).deleteDocuments(values) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(1); - for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { assertThat(i.getKey()).isEqualTo("1"); } assertThat(deleteResult.getErrors().size()).isEqualTo(0); @@ -1871,9 +1958,9 @@ void deleteDocumentsByDocumentOne() throws InterruptedException, ExecutionExcept @Test void deleteDocumentsEmpty() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection keys = new ArrayList<>(); - db.collection(COLLECTION_NAME).deleteDocuments(keys, null, null) + db.collection(COLLECTION_NAME).deleteDocuments(keys) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(0); @@ -1885,11 +1972,11 @@ void deleteDocumentsEmpty() throws InterruptedException, ExecutionException { @Test void deleteDocumentsByKeyNotExisting() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection keys = new ArrayList<>(); keys.add("1"); keys.add("2"); - db.collection(COLLECTION_NAME).deleteDocuments(keys, null, null) + db.collection(COLLECTION_NAME).deleteDocuments(keys) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(0); @@ -1902,16 +1989,16 @@ void deleteDocumentsByKeyNotExisting() throws InterruptedException, ExecutionExc void deleteDocumentsByDocumentsNotExisting() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } - db.collection(COLLECTION_NAME).deleteDocuments(values, null, null) + db.collection(COLLECTION_NAME).deleteDocuments(values) .whenComplete((deleteResult, ex) -> { assertThat(deleteResult).isNotNull(); assertThat(deleteResult.getDocuments().size()).isEqualTo(0); @@ -1920,26 +2007,45 @@ void deleteDocumentsByDocumentsNotExisting() throws InterruptedException, Execut .get(); } + @Test + void deleteDocumentsRawDataByKeyReturnOld() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + final RawData values = RawData.of("[{\"_key\":\"1\"},{\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + final RawData keys = RawData.of("[\"1\",\"2\"]"); + MultiDocumentEntity> deleteResult = collection.deleteDocuments(keys, + new DocumentDeleteOptions().returnOld(true)).get(); + assertThat(deleteResult).isNotNull(); + assertThat(deleteResult.getDocuments()).hasSize(2); + for (final DocumentDeleteEntity i : deleteResult.getDocuments()) { + assertThat(i.getKey()).isIn("1", "2"); + assertThat(i.getOld()).isNotNull().isInstanceOf(RawJson.class); + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) i.getOld()).getValue()); + assertThat(jn.get("_key").asText()).isEqualTo(i.getKey()); + } + assertThat(deleteResult.getErrors()).isEmpty(); + } + @Test void updateDocuments() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("2"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } - db.collection(COLLECTION_NAME).updateDocuments(updatedValues, null) + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(2); assertThat(updateResult.getErrors().size()).isEqualTo(0); @@ -1950,7 +2056,8 @@ void updateDocuments() throws InterruptedException, ExecutionException { @Test void updateDocumentsWithDifferentReturnType() throws ExecutionException, InterruptedException { ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); - List keys = IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID()).collect(Collectors.toList()); + List keys = + IntStream.range(0, 3).mapToObj(it -> "key-" + UUID.randomUUID()).collect(Collectors.toList()); List docs = keys.stream() .map(BaseDocument::new) .peek(it -> it.addAttribute("a", "test")) @@ -1982,16 +2089,16 @@ void updateDocumentsWithDifferentReturnType() throws ExecutionException, Interru void updateDocumentsOne() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection updatedValues = new ArrayList<>(); final BaseDocument first = values.iterator().next(); first.addAttribute("a", "test"); updatedValues.add(first); - db.collection(COLLECTION_NAME).updateDocuments(updatedValues, null) + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(1); assertThat(updateResult.getErrors().size()).isEqualTo(0); @@ -2002,7 +2109,7 @@ void updateDocumentsOne() throws InterruptedException, ExecutionException { @Test void updateDocumentsEmpty() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).updateDocuments(values, null) + db.collection(COLLECTION_NAME).updateDocuments(values) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(0); assertThat(updateResult.getErrors().size()).isEqualTo(0); @@ -2016,14 +2123,14 @@ void updateDocumentsWithoutKey() throws InterruptedException, ExecutionException { values.add(new BaseDocument("1")); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } updatedValues.add(new BaseDocument()); - db.collection(COLLECTION_NAME).updateDocuments(updatedValues, null) + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(1); assertThat(updateResult.getErrors().size()).isEqualTo(1); @@ -2031,6 +2138,43 @@ void updateDocumentsWithoutKey() throws InterruptedException, ExecutionException .get(); } + @Test + void updateDocumentsRawData() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); + final MultiDocumentEntity updateResult = collection.updateDocuments(updatedValues).get(); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + } + + @Test + void updateDocumentsRawDataReturnNew() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + +"\"foo\":\"bar\"}]"); + MultiDocumentEntity> updateResult = + collection.updateDocuments(updatedValues, new DocumentUpdateOptions().returnNew(true)).get(); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + for (DocumentUpdateEntity doc : updateResult.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("foo")).isTrue(); + assertThat(jn.get("foo").textValue()).isEqualTo("bar"); + } + } + @Test void replaceDocuments() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); @@ -2038,13 +2182,13 @@ void replaceDocuments() throws InterruptedException, ExecutionException { values.add(new BaseDocument("1")); values.add(new BaseDocument("2")); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } - db.collection(COLLECTION_NAME).replaceDocuments(updatedValues, null) + db.collection(COLLECTION_NAME).replaceDocuments(updatedValues) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(2); assertThat(updateResult.getErrors().size()).isEqualTo(0); @@ -2056,16 +2200,16 @@ void replaceDocuments() throws InterruptedException, ExecutionException { void replaceDocumentsOne() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); { - final BaseDocument e = new BaseDocument(); + final BaseDocument e = new BaseDocument(UUID.randomUUID().toString()); e.setKey("1"); values.add(e); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection updatedValues = new ArrayList<>(); final BaseDocument first = values.iterator().next(); first.addAttribute("a", "test"); updatedValues.add(first); - db.collection(COLLECTION_NAME).updateDocuments(updatedValues, null) + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(1); assertThat(updateResult.getErrors().size()).isEqualTo(0); @@ -2076,7 +2220,7 @@ void replaceDocumentsOne() throws InterruptedException, ExecutionException { @Test void replaceDocumentsEmpty() throws InterruptedException, ExecutionException { final Collection values = new ArrayList<>(); - db.collection(COLLECTION_NAME).updateDocuments(values, null) + db.collection(COLLECTION_NAME).updateDocuments(values) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(0); assertThat(updateResult.getErrors().size()).isEqualTo(0); @@ -2090,14 +2234,14 @@ void replaceDocumentsWithoutKey() throws InterruptedException, ExecutionExceptio { values.add(new BaseDocument("1")); } - db.collection(COLLECTION_NAME).insertDocuments(values, null).get(); + db.collection(COLLECTION_NAME).insertDocuments(values).get(); final Collection updatedValues = new ArrayList<>(); for (final BaseDocument i : values) { i.addAttribute("a", "test"); updatedValues.add(i); } updatedValues.add(new BaseDocument()); - db.collection(COLLECTION_NAME).updateDocuments(updatedValues, null) + db.collection(COLLECTION_NAME).updateDocuments(updatedValues) .whenComplete((updateResult, ex) -> { assertThat(updateResult.getDocuments().size()).isEqualTo(1); assertThat(updateResult.getErrors().size()).isEqualTo(1); @@ -2106,17 +2250,42 @@ void replaceDocumentsWithoutKey() throws InterruptedException, ExecutionExceptio } @Test - void load() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).load() - .whenComplete((result, ex) -> assertThat(result.getName()).isEqualTo(COLLECTION_NAME)) - .get(); + void replaceDocumentsRawData() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + +"\"foo\":\"bar\"}]"); + final MultiDocumentEntity updateResult = collection.replaceDocuments(updatedValues).get(); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); } @Test - void unload() throws InterruptedException, ExecutionException { - db.collection(COLLECTION_NAME).unload() - .whenComplete((result, ex) -> assertThat(result.getName()).isEqualTo(COLLECTION_NAME)) - .get(); + void replaceDocumentsRawDataReturnNew() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + + final RawData values = RawData.of("[{\"_key\":\"1\"}, {\"_key\":\"2\"}]"); + collection.insertDocuments(values).get(); + + final RawData updatedValues = RawData.of("[{\"_key\":\"1\", \"foo\":\"bar\"}, {\"_key\":\"2\", " + + "\"foo\":\"bar\"}]"); + MultiDocumentEntity> updateResult = + collection.replaceDocuments(updatedValues, new DocumentReplaceOptions().returnNew(true)).get(); + assertThat(updateResult.getDocuments()).hasSize(2); + assertThat(updateResult.getErrors()).isEmpty(); + for (DocumentUpdateEntity doc : updateResult.getDocuments()) { + RawData d = doc.getNew(); + assertThat(d) + .isNotNull() + .isInstanceOf(RawJson.class); + + JsonNode jn = SerdeUtils.INSTANCE.parseJson(((RawJson) d).getValue()); + assertThat(jn.has("foo")).isTrue(); + assertThat(jn.get("foo").textValue()).isEqualTo("bar"); + } } @Test @@ -2145,7 +2314,6 @@ void changeProperties() throws InterruptedException, ExecutionException { assertThat(properties.getWaitForSync()).isNotNull(); final CollectionPropertiesOptions options = new CollectionPropertiesOptions(); options.waitForSync(!properties.getWaitForSync()); - options.journalSize(2000000L); db.collection(collection).changeProperties(options) .whenComplete((changedProperties, ex) -> { assertThat(changedProperties.getWaitForSync()).isNotNull(); @@ -2229,7 +2397,8 @@ void grantAccessNONE() throws InterruptedException, ExecutionException { @Test void grantAccessUserNotFound() { - Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.RW).get()); + Throwable thrown = + catchThrowable(() -> db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.RW).get()); assertThat(thrown).isInstanceOf(ExecutionException.class); } @@ -2245,7 +2414,8 @@ void revokeAccess() throws InterruptedException, ExecutionException { @Test void revokeAccessUserNotFound() { - Throwable thrown = catchThrowable(() -> db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.NONE).get()); + Throwable thrown = + catchThrowable(() -> db.collection(COLLECTION_NAME).grantAccess("user1", Permissions.NONE).get()); assertThat(thrown).isInstanceOf(ExecutionException.class); } @@ -2269,4 +2439,76 @@ void resetAccessUserNotFound() { void getPermissions() throws InterruptedException, ExecutionException { assertThat(db.collection(COLLECTION_NAME).getPermissions("root").get()).isEqualTo(Permissions.RW); } + + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") + public interface Animal { + String getKey(); + + String getName(); + } + + public static class Dog implements Animal { + + @Key + private String key; + private String name; + + public Dog() { + } + + public Dog(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Cat implements Animal { + @Key + private String key; + private String name; + + public Cat() { + } + + public Cat(String key, String name) { + this.key = key; + this.name = name; + } + + @Override + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } } diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/driver/src/test/java/com/arangodb/async/ArangoDBTest.java similarity index 71% rename from src/test/java/com/arangodb/async/ArangoDBTest.java rename to driver/src/test/java/com/arangodb/async/ArangoDBTest.java index 89ea13f5f..2a76db54c 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -21,14 +21,13 @@ package com.arangodb.async; import com.arangodb.*; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.*; -import com.arangodb.mapping.ArangoJack; +import com.arangodb.internal.serde.SerdeUtils; import com.arangodb.model.*; -import com.arangodb.model.LogOptions.SortOrder; +import com.arangodb.util.RawJson; import com.arangodb.util.TestUtils; -import com.arangodb.velocypack.exception.VPackException; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; @@ -56,8 +55,12 @@ class ArangoDBTest { private static final String PW = "machts der hund"; private static Boolean extendedNames; - private final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); - private final ArangoDB arangoDBSync = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + private final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); + private final ArangoDB arangoDBSync = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); private boolean isEnterprise() { return arangoDBSync.getVersion().getLicense() == License.ENTERPRISE; @@ -76,10 +79,9 @@ private boolean isLessThanVersion(final int major, final int minor) { } private boolean supportsExtendedNames() { - final ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); if (extendedNames == null) { try { - ArangoDatabase testDb = arangoDB.db(DbName.of("test-" + TestUtils.generateRandomDbName(20, true))); + ArangoDatabase testDb = arangoDBSync.db(DbName.of("test-" + TestUtils.generateRandomDbName(20, true))); testDb.create(); extendedNames = true; testDb.drop(); @@ -169,10 +171,9 @@ void createDatabaseWithOptions() throws ExecutionException, InterruptedException assertThat(resultCreate).isTrue(); DatabaseEntity info = arangoDB.db(dbName).getInfo().get(); - assertThat(info.getReplicationFactor()).isEqualTo(2); + assertThat(info.getReplicationFactor().getValue()).isEqualTo(2); assertThat(info.getWriteConcern()).isEqualTo(2); assertThat(info.getSharding()).isEmpty(); - assertThat(info.getSatellite()).isNull(); final Boolean resultDelete = arangoDB.db(dbName).drop().get(); assertThat(resultDelete).isTrue(); @@ -189,15 +190,14 @@ void createDatabaseWithOptionsSatellite() throws ExecutionException, Interrupted .name(dbName) .options(new DatabaseOptions() .writeConcern(2) - .satellite(true) + .replicationFactor(ReplicationFactor.ofSatellite()) .sharding("") ) ).get(); assertThat(resultCreate).isTrue(); DatabaseEntity info = arangoDB.db(dbName).getInfo().get(); - assertThat(info.getReplicationFactor()).isNull(); - assertThat(info.getSatellite()).isTrue(); + assertThat(info.getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); assertThat(info.getWriteConcern()).isEqualTo(2); assertThat(info.getSharding()).isEmpty(); @@ -417,7 +417,9 @@ void updateUserDefaultCollectionAccess() throws InterruptedException, ExecutionE @Test void authenticationFailPassword() throws InterruptedException { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().password("no").jwt(null).serializer(new ArangoJack()).build(); + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .password("no").jwt(null).build(); try { arangoDB.getVersion().get(); fail(); @@ -428,7 +430,9 @@ void authenticationFailPassword() throws InterruptedException { @Test void authenticationFailUser() throws InterruptedException { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().user("no").jwt(null).serializer(new ArangoJack()).build(); + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .user("no").jwt(null).build(); try { arangoDB.getVersion().get(); fail(); @@ -438,147 +442,34 @@ void authenticationFailUser() throws InterruptedException { } @Test - void execute() throws VPackException, InterruptedException, ExecutionException { + void execute() throws InterruptedException, ExecutionException { arangoDB - .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) + .execute(Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.GET) + .path("/_api/version") + .build(), RawJson.class) .whenComplete((response, ex) -> { assertThat(response.getBody()).isNotNull(); - assertThat(response.getBody().get("version").isString()).isTrue(); + assertThat(SerdeUtils.INSTANCE.parseJson(response.getBody().getValue()).get("version").isTextual()).isTrue(); }) .get(); } @Test - void execute_acquireHostList_enabled() throws VPackException, InterruptedException, ExecutionException { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().acquireHostList(true).serializer(new ArangoJack()).build(); + void execute_acquireHostList_enabled() throws InterruptedException, ExecutionException { + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .acquireHostList(true).build(); arangoDB - .execute(new Request(DbName.SYSTEM, RequestType.GET, "/_api/version")) + .execute(Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.GET) + .path("/_api/version") + .build(), RawJson.class) .whenComplete((response, ex) -> { assertThat(response.getBody()).isNotNull(); - assertThat(response.getBody().get("version").isString()).isTrue(); - }) - .get(); - } - - @Test - void getLogs() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - arangoDB.getLogs(null) - .whenComplete((logs, ex) -> { - assertThat(logs).isNotNull(); - assertThat(logs.getTotalAmount()).isPositive(); - assertThat((long) logs.getLid().size()).isEqualTo(logs.getTotalAmount()); - assertThat((long) logs.getLevel().size()).isEqualTo(logs.getTotalAmount()); - assertThat((long) logs.getTimestamp().size()).isEqualTo(logs.getTotalAmount()); - assertThat((long) logs.getText().size()).isEqualTo(logs.getTotalAmount()); - }) - .get(); - } - - @Test - void getLogsUpto() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null).get(); - arangoDB.getLogs(new LogOptions().upto(LogLevel.WARNING)) - .whenComplete((logsUpto, ex) -> { - assertThat(logsUpto).isNotNull(); - assertThat(logs.getTotalAmount() >= logsUpto.getTotalAmount()).isTrue(); - assertThat(logsUpto.getLevel()).doesNotContain(LogLevel.INFO); - }) - .get(); - } - - @Test - void getLogsLevel() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null).get(); - arangoDB.getLogs(new LogOptions().level(LogLevel.INFO)) - .whenComplete((logsInfo, ex) -> { - assertThat(logsInfo).isNotNull(); - assertThat(logs.getTotalAmount() >= logsInfo.getTotalAmount()).isTrue(); - assertThat(logsInfo.getLevel()).containsOnly(LogLevel.INFO); - }) - .get(); - } - - @Test - void getLogsStart() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null).get(); - assertThat(logs.getLid()).isNotEmpty(); - arangoDB.getLogs(new LogOptions().start(logs.getLid().get(0) + 1)) - .whenComplete((logsStart, ex) -> { - assertThat(logsStart).isNotNull(); - assertThat(logsStart.getLid()).doesNotContain(logs.getLid().get(0)); - }) - .get(); - } - - @Test - void getLogsSize() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null).get(); - assertThat(logs.getLid()).isNotEmpty(); - arangoDB.getLogs(new LogOptions().size(logs.getLid().size() - 1)) - .whenComplete((logsSize, ex) -> { - assertThat(logsSize).isNotNull(); - assertThat(logsSize.getLid()).hasSize(logs.getLid().size() - 1); - }) - .get(); - } - - @Test - void getLogsOffset() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - assumeTrue(isLessThanVersion(3, 9)); // deprecated - final LogEntity logs = arangoDB.getLogs(null).get(); - assertThat(logs.getTotalAmount()).isPositive(); - arangoDB.getLogs(new LogOptions().offset((int) (logs.getTotalAmount() - 1))) - .whenComplete((logsOffset, ex) -> { - assertThat(logsOffset).isNotNull(); - assertThat(logsOffset.getLid()).hasSize(1); - }) - .get(); - } - - @Test - void getLogsSearch() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - final LogEntity logs = arangoDB.getLogs(null).get(); - arangoDB.getLogs(new LogOptions().search(BaseTest.TEST_DB.get())) - .whenComplete((logsSearch, ex) -> { - assertThat(logsSearch).isNotNull(); - assertThat(logs.getTotalAmount()).isGreaterThan(logsSearch.getTotalAmount()); - }) - .get(); - } - - @Test - void getLogsSortAsc() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - arangoDB.getLogs(new LogOptions().sort(SortOrder.asc)) - .whenComplete((logs, ex) -> { - assertThat(logs).isNotNull(); - long lastId = -1; - for (final Long id : logs.getLid()) { - assertThat(id).isGreaterThan(lastId); - lastId = id; - } - }) - .get(); - } - - @Test - void getLogsSortDesc() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) - arangoDB.getLogs(new LogOptions().sort(SortOrder.desc)) - .whenComplete((logs, ex) -> { - assertThat(logs).isNotNull(); - long lastId = Long.MAX_VALUE; - for (final Long id : logs.getLid()) { - assertThat(lastId).isGreaterThan(id); - lastId = id; - } + assertThat(SerdeUtils.INSTANCE.parseJson(response.getBody().getValue()).get("version").isTextual()).isTrue(); }) .get(); } @@ -595,18 +486,6 @@ void getLogEntries() throws InterruptedException, ExecutionException { .get(); } - @Test - void getLogEntriesSearch() throws InterruptedException, ExecutionException { - assumeTrue(isAtLeastVersion(3, 8)); - final LogEntriesEntity logs = arangoDB.getLogEntries(null).get(); - arangoDB.getLogs(new LogOptions().search(BaseTest.TEST_DB.get())) - .whenComplete((logsSearch, ex) -> { - assertThat(logsSearch).isNotNull(); - assertThat(logs.getTotal()).isGreaterThan(logsSearch.getTotalAmount()); - }) - .get(); - } - @Test void getLogLevel() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) @@ -637,6 +516,7 @@ void setLogLevel() throws InterruptedException, ExecutionException { } @Test + @Disabled("Manual execution only") void queueTime() throws InterruptedException, ExecutionException { List>> reqs = IntStream.range(0, 80) .mapToObj(__ -> arangoDB.db().query("RETURN SLEEP(1)", Void.class)) @@ -664,4 +544,23 @@ void queueTime() throws InterruptedException, ExecutionException { } } + @Test + void getQueryOptimizerRules() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + final Collection rules = arangoDB.getQueryOptimizerRules().get(); + assertThat(rules).isNotEmpty(); + for (QueryOptimizerRule rule : rules) { + assertThat(rule).isNotNull(); + assertThat(rule.getName()).isNotNull(); + QueryOptimizerRule.Flags flags = rule.getFlags(); + assertThat(flags.getHidden()).isNotNull(); + assertThat(flags.getClusterOnly()).isNotNull(); + assertThat(flags.getCanBeDisabled()).isNotNull(); + assertThat(flags.getCanCreateAdditionalPlans()).isNotNull(); + assertThat(flags.getDisabledByDefault()).isNotNull(); + assertThat(flags.getEnterpriseOnly()).isNotNull(); + } + } + + } diff --git a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java b/driver/src/test/java/com/arangodb/async/ArangoDatabaseTest.java similarity index 90% rename from src/test/java/com/arangodb/async/ArangoDatabaseTest.java rename to driver/src/test/java/com/arangodb/async/ArangoDatabaseTest.java index de76da620..be4d23a6a 100644 --- a/src/test/java/com/arangodb/async/ArangoDatabaseTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoDatabaseTest.java @@ -27,10 +27,9 @@ import com.arangodb.entity.AqlParseEntity.AstNode; import com.arangodb.entity.QueryCachePropertiesEntity.CacheMode; import com.arangodb.model.*; -import com.arangodb.model.TraversalOptions.Direction; -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.exception.VPackException; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -118,7 +117,7 @@ void createCollectionWithReplicationFactor() throws InterruptedException, Execut .createCollection(COLLECTION_NAME, new CollectionCreateOptions().replicationFactor(2)).get(); assertThat(result).isNotNull(); assertThat(result.getId()).isNotNull(); - assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor()).isEqualTo(2); + assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); db.collection(COLLECTION_NAME).drop().get(); } @@ -131,9 +130,8 @@ void createCollectionWithWriteConcern() throws ExecutionException, InterruptedEx new CollectionCreateOptions().replicationFactor(2).writeConcern(2)).get(); assertThat(result).isNotNull(); assertThat(result.getId()).isNotNull(); - assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor()).isEqualTo(2); + assertThat(db.collection(COLLECTION_NAME).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); assertThat(db.collection(COLLECTION_NAME).getProperties().get().getWriteConcern()).isEqualTo(2); - assertThat(db.collection(COLLECTION_NAME).getProperties().get().getSatellite()).isNull(); db.collection(COLLECTION_NAME).drop(); } @@ -495,7 +493,8 @@ void queryWithLimitAndFullCount() throws InterruptedException, ExecutionExceptio assertThat(cursor.hasNext()).isEqualTo(true); } assertThat(cursor.getStats()).isNotNull(); - assertThat(cursor.getStats().getFullCount()).isEqualTo(10L); + assertThat(((Number) cursor.getStats().get("executionTime")).doubleValue()).isPositive(); + assertThat((cursor.getStats().getFullCount())).isGreaterThanOrEqualTo(10); }) .get(); } finally { @@ -679,7 +678,7 @@ void queryWithBindVars() throws InterruptedException, ExecutionException { try { db.createCollection(COLLECTION_NAME, null).get(); for (int i = 0; i < 10; i++) { - final BaseDocument baseDocument = new BaseDocument(); + final BaseDocument baseDocument = new BaseDocument(UUID.randomUUID().toString()); baseDocument.addAttribute("age", 20 + i); db.collection(COLLECTION_NAME).insertDocument(baseDocument, null).get(); } @@ -877,8 +876,8 @@ void getGraphs() throws InterruptedException, ExecutionException { @Test void transactionString() throws InterruptedException, ExecutionException { final TransactionOptions options = new TransactionOptions().params("test"); - db.transaction("function (params) {return params;}", String.class, options) - .whenComplete((result, ex) -> assertThat(result).isEqualTo("test")) + db.transaction("function (params) {return params;}", RawJson.class, options) + .whenComplete((result, ex) -> assertThat(result.getValue()).isEqualTo("\"test\"")) .get(); } @@ -891,34 +890,35 @@ void transactionNumber() throws InterruptedException, ExecutionException { } @Test - void transactionVPack() throws VPackException, InterruptedException, ExecutionException { - final TransactionOptions options = new TransactionOptions().params(new VPackBuilder().add("test").slice()); - db.transaction("function (params) {return params;}", VPackSlice.class, options) + void transactionJsonNode() throws InterruptedException, ExecutionException { + final TransactionOptions options = new TransactionOptions().params(JsonNodeFactory.instance.textNode("test")); + db.transaction("function (params) {return params;}", JsonNode.class, options) .whenComplete((result, ex) -> { - assertThat(result.isString()).isEqualTo(true); - assertThat(result.getAsString()).isEqualTo("test"); + assertThat(result.isTextual()).isEqualTo(true); + assertThat(result.asText()).isEqualTo("test"); }) .get(); } @Test void transactionEmpty() throws InterruptedException, ExecutionException { - db.transaction("function () {}", null, null).get(); + db.transaction("function () {}", Void.class, null).get(); } @Test - void transactionallowImplicit() throws InterruptedException, ExecutionException { + void transactionAllowImplicit() throws InterruptedException, ExecutionException { try { db.createCollection("someCollection", null).get(); db.createCollection("someOtherCollection", null).get(); final String action = "function (params) {" + "var db = require('internal').db;" - + "return {'a':db.someCollection.all().toArray()[0], 'b':db.someOtherCollection.all().toArray()[0]};" + + "return {'a':db.someCollection.all().toArray()[0], 'b':db.someOtherCollection.all().toArray()" + + "[0]};" + "}"; final TransactionOptions options = new TransactionOptions().readCollections("someCollection"); - db.transaction(action, VPackSlice.class, options).get(); + db.transaction(action, Void.class, options).get(); try { options.allowImplicit(false); - db.transaction(action, VPackSlice.class, options).get(); + db.transaction(action, Void.class, options).get(); fail(); } catch (final ExecutionException e) { assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); @@ -966,63 +966,11 @@ void getInfo() throws InterruptedException, ExecutionException { f.get(); } - @Test - void executeTraversal() throws InterruptedException, ExecutionException { - try { - db.createCollection("person", null).get(); - db.createCollection("knows", new CollectionCreateOptions().type(CollectionType.EDGES)).get(); - for (final String e : new String[]{"Alice", "Bob", "Charlie", "Dave", "Eve"}) { - final BaseDocument doc = new BaseDocument(); - doc.setKey(e); - db.collection("person").insertDocument(doc, null).get(); - } - for (final String[] e : new String[][]{new String[]{"Alice", "Bob"}, new String[]{"Bob", "Charlie"}, - new String[]{"Bob", "Dave"}, new String[]{"Eve", "Alice"}, new String[]{"Eve", "Bob"}}) { - final BaseEdgeDocument edge = new BaseEdgeDocument(); - edge.setKey(e[0] + "_knows_" + e[1]); - edge.setFrom("person/" + e[0]); - edge.setTo("person/" + e[1]); - db.collection("knows").insertDocument(edge, null).get(); - } - final TraversalOptions options = new TraversalOptions().edgeCollection("knows").startVertex("person/Alice") - .direction(Direction.outbound); - db.executeTraversal(BaseDocument.class, BaseEdgeDocument.class, options) - .whenComplete((traversal, ex) -> { - assertThat(traversal).isNotNull(); - - final Collection vertices = traversal.getVertices(); - assertThat(vertices).isNotNull(); - assertThat(vertices.size()).isEqualTo(4); - - final Iterator verticesIterator = vertices.iterator(); - final Collection v = Arrays.asList("Alice", "Bob", "Charlie", "Dave"); - while (verticesIterator.hasNext()) { - assertThat(v.contains(verticesIterator.next().getKey())).isEqualTo(true); - } - - final Collection> paths = traversal.getPaths(); - assertThat(paths).isNotNull(); - assertThat(paths.size()).isEqualTo(4); - - assertThat(paths.iterator().hasNext()).isEqualTo(true); - final PathEntity first = paths.iterator().next(); - assertThat(first).isNotNull(); - assertThat(first.getEdges().size()).isEqualTo(0); - assertThat(first.getVertices().size()).isEqualTo(1); - assertThat(first.getVertices().iterator().next().getKey()).isEqualTo("Alice"); - }) - .get(); - } finally { - db.collection("person").drop().get(); - db.collection("knows").drop().get(); - } - } - @Test void getDocument() throws InterruptedException, ExecutionException { String collectionName = COLLECTION_NAME + "getDocument"; db.createCollection(collectionName).get(); - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.setKey("123"); db.collection(collectionName).insertDocument(value).get(); db.getDocument(collectionName + "/123", BaseDocument.class) @@ -1039,7 +987,7 @@ void shouldIncludeExceptionMessage() throws InterruptedException, ExecutionExcep final String exceptionMessage = "My error context"; final String action = "function (params) {" + "throw '" + exceptionMessage + "';" + "}"; try { - db.transaction(action, VPackSlice.class, null).get(); + db.transaction(action, Void.class, null).get(); fail(); } catch (final ExecutionException e) { assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); @@ -1062,12 +1010,15 @@ void reloadRouting() throws InterruptedException, ExecutionException { db.reloadRouting().get(); } - @SuppressWarnings({"WeakerAccess", "unused"}) - static class TransactionTestEntity { + public static class TransactionTestEntity { private String value; - TransactionTestEntity() { + public TransactionTestEntity() { super(); } + + public String getValue() { + return value; + } } } diff --git a/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java b/driver/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java similarity index 91% rename from src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java rename to driver/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java index 4424451e9..e1b106875 100644 --- a/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoEdgeCollectionTest.java @@ -27,12 +27,10 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; - import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.ExecutionException; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; @@ -114,14 +112,10 @@ void getEdgeIfMatch() throws InterruptedException, ExecutionException { void getEdgeIfMatchFail() throws InterruptedException, ExecutionException { final BaseEdgeDocument value = createEdgeValue(); final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no").catchException(false); - try { - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(edge.getKey(), BaseEdgeDocument.class, options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); + BaseEdgeDocument doc = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(edge.getKey(), BaseEdgeDocument.class, options).get(); + assertThat(doc).isNull(); } @Test @@ -139,14 +133,10 @@ void getEdgeIfNoneMatch() throws InterruptedException, ExecutionException { void getEdgeIfNoneMatchFail() throws InterruptedException, ExecutionException { final BaseEdgeDocument value = createEdgeValue(); final EdgeEntity edge = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(value, null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(edge.getRev()).catchException(false); - try { - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(edge.getKey(), BaseEdgeDocument.class, options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(edge.getRev()); + BaseEdgeDocument doc = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(edge.getKey(), BaseEdgeDocument.class, options).get(); + assertThat(doc).isNull(); } @Test @@ -155,7 +145,7 @@ void replaceEdge() throws InterruptedException, ExecutionException { doc.addAttribute("a", "test"); final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final EdgeUpdateEntity replaceResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) .replaceEdge(createResult.getKey(), doc, null).get(); @@ -179,7 +169,7 @@ void replaceEdgeIfMatch() throws InterruptedException, ExecutionException { doc.addAttribute("a", "test"); final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch(createResult.getRev()); final EdgeUpdateEntity replaceResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) @@ -204,7 +194,7 @@ void replaceEdgeIfMatchFail() throws InterruptedException, ExecutionException { doc.addAttribute("a", "test"); final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); try { final EdgeReplaceOptions options = new EdgeReplaceOptions().ifMatch("no"); @@ -311,7 +301,7 @@ void updateEdgeKeepNullTrue() throws InterruptedException, ExecutionException { final BaseEdgeDocument readResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) .getEdge(createResult.getKey(), BaseEdgeDocument.class, null).get(); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(1); + assertThat(readResult.getProperties().keySet()).hasSize(6); assertThat(readResult.getProperties()).containsKey("a"); } @@ -344,13 +334,9 @@ void deleteEdge() throws InterruptedException, ExecutionException { final EdgeEntity createResult = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(doc, null) .get(); db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).deleteEdge(createResult.getKey(), null).get(); - try { - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(createResult.getKey(), BaseEdgeDocument.class, new GraphDocumentReadOptions().catchException(false)).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + BaseEdgeDocument res = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(createResult.getKey(), BaseEdgeDocument.class, new GraphDocumentReadOptions()).get(); + assertThat(res).isNull(); } @Test @@ -360,13 +346,9 @@ void deleteEdgeIfMatch() throws InterruptedException, ExecutionException { .get(); final EdgeDeleteOptions options = new EdgeDeleteOptions().ifMatch(createResult.getRev()); db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).deleteEdge(createResult.getKey(), options).get(); - try { - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) - .getEdge(createResult.getKey(), BaseEdgeDocument.class, new GraphDocumentReadOptions().catchException(false)).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + BaseEdgeDocument res = db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME) + .getEdge(createResult.getKey(), BaseEdgeDocument.class, new GraphDocumentReadOptions()).get(); + assertThat(res).isNull(); } @Test diff --git a/src/test/java/com/arangodb/async/ArangoGraphTest.java b/driver/src/test/java/com/arangodb/async/ArangoGraphTest.java similarity index 93% rename from src/test/java/com/arangodb/async/ArangoGraphTest.java rename to driver/src/test/java/com/arangodb/async/ArangoGraphTest.java index 9513d4fec..beed0bf10 100644 --- a/src/test/java/com/arangodb/async/ArangoGraphTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoGraphTest.java @@ -20,10 +20,7 @@ package com.arangodb.async; -import com.arangodb.entity.CollectionPropertiesEntity; -import com.arangodb.entity.EdgeDefinition; -import com.arangodb.entity.GraphEntity; -import com.arangodb.entity.ServerRole; +import com.arangodb.entity.*; import com.arangodb.model.GraphCreateOptions; import com.arangodb.model.VertexCollectionCreateOptions; import org.junit.jupiter.api.AfterEach; @@ -98,11 +95,12 @@ void createWithReplicationAndWriteConcern() throws ExecutionException, Interrupt assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isCluster()); final Collection edgeDefinitions = new ArrayList<>(); - final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, new GraphCreateOptions().isSmart(true).replicationFactor(2).writeConcern(2)).get(); + final GraphEntity graph = db.createGraph(GRAPH_NAME + "_1", edgeDefinitions, + new GraphCreateOptions().isSmart(true).replicationFactor(2).writeConcern(2)).get(); assertThat(graph).isNotNull(); assertThat(graph.getName()).isEqualTo(GRAPH_NAME + "_1"); assertThat(graph.getWriteConcern()).isEqualTo(2); - assertThat(graph.getReplicationFactor()).isEqualTo(2); + assertThat(graph.getReplicationFactor().getValue()).isEqualTo(2); db.graph(GRAPH_NAME + "_1").drop(); } @@ -133,12 +131,12 @@ void getInfo() throws InterruptedException, ExecutionException { if (isCluster()) { for (final String collection : new String[]{VERTEX_COL_1, VERTEX_COL_2}) { final CollectionPropertiesEntity properties = db.collection(collection).getProperties().get(); - assertThat(properties.getReplicationFactor()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); } for (final String collection : new String[]{EDGE_COL_1, EDGE_COL_2}) { final CollectionPropertiesEntity properties = db.collection(collection).getProperties().get(); - assertThat(properties.getReplicationFactor()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); } } } @@ -169,12 +167,12 @@ void addSatelliteVertexCollection() throws ExecutionException, InterruptedExcept String v1Name = "vertex-" + rnd(); ArangoGraphAsync g = db.graph(GRAPH_NAME + rnd()); - g.createGraph(Collections.emptyList(), new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")).get(); + g.createGraph(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")).get(); g.addVertexCollection(v1Name, new VertexCollectionCreateOptions().satellites(v1Name)).get(); Collection vertexCollections = g.getVertexCollections().get(); assertThat(vertexCollections).contains(v1Name); - assertThat(db.collection(v1Name).getProperties().get().getSatellite()).isTrue(); + assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); // revert g.drop().get(); @@ -211,7 +209,7 @@ void addEdgeDefinition() throws InterruptedException, ExecutionException { } if (isCluster()) { final CollectionPropertiesEntity properties = db.collection(EDGE_COL_3).getProperties().get(); - assertThat(properties.getReplicationFactor()).isEqualTo(REPLICATION_FACTOR); + assertThat(properties.getReplicationFactor().getValue()).isEqualTo(REPLICATION_FACTOR); assertThat(properties.getNumberOfShards()).isEqualTo(NUMBER_OF_SHARDS); } setup(); @@ -229,7 +227,7 @@ void addSatelliteEdgeDefinition() throws ExecutionException, InterruptedExceptio EdgeDefinition ed = new EdgeDefinition().collection(eName).from(v1Name).to(v2Name).satellites(v1Name); ArangoGraphAsync g = db.graph(GRAPH_NAME + rnd()); - g.createGraph(Collections.emptyList(), new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")).get(); + g.createGraph(null, new GraphCreateOptions().isSmart(true).smartGraphAttribute("test")).get(); g.addEdgeDefinition(ed).get(); final GraphEntity ge = g.getInfo().get(); assertThat(ge).isNotNull(); @@ -240,7 +238,7 @@ void addSatelliteEdgeDefinition() throws ExecutionException, InterruptedExceptio assertThat(e.getFrom()).contains(v1Name); assertThat(e.getTo()).contains(v2Name); - assertThat(db.collection(v1Name).getProperties().get().getSatellite()).isTrue(); + assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); // revert g.drop().get(); @@ -327,9 +325,9 @@ void hybridSmartGraph() throws ExecutionException, InterruptedException { assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); assertThat(g.getNumberOfShards()).isEqualTo(2); - assertThat(db.collection(eName).getProperties().get().getSatellite()).isTrue(); - assertThat(db.collection(v1Name).getProperties().get().getSatellite()).isTrue(); - assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor()).isEqualTo(2); + assertThat(db.collection(eName).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); } @Test @@ -355,8 +353,8 @@ void hybridDisjointSmartGraph() throws ExecutionException, InterruptedException assertThat(g.getSmartGraphAttribute()).isEqualTo("test"); assertThat(g.getNumberOfShards()).isEqualTo(2); - assertThat(db.collection(v1Name).getProperties().get().getSatellite()).isTrue(); - assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor()).isEqualTo(2); + assertThat(db.collection(v1Name).getProperties().get().getReplicationFactor()).isEqualTo(ReplicationFactor.ofSatellite()); + assertThat(db.collection(v2Name).getProperties().get().getReplicationFactor().getValue()).isEqualTo(2); } @Test diff --git a/src/test/java/com/arangodb/async/ArangoRouteTest.java b/driver/src/test/java/com/arangodb/async/ArangoRouteTest.java similarity index 93% rename from src/test/java/com/arangodb/async/ArangoRouteTest.java rename to driver/src/test/java/com/arangodb/async/ArangoRouteTest.java index d01b3ad11..772e593f5 100644 --- a/src/test/java/com/arangodb/async/ArangoRouteTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoRouteTest.java @@ -25,10 +25,9 @@ import com.arangodb.internal.ArangoRequestParam; import org.junit.jupiter.api.Test; - +import java.util.UUID; import java.util.concurrent.ExecutionException; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; @@ -50,7 +49,7 @@ void withHeader() throws InterruptedException, ExecutionException { final ArangoCollectionAsync collection = db.collection("route-test-col"); try { collection.create(); - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); collection.insertDocument(doc).get(); db.route("/_api/document", doc.getId()).withHeader(ArangoRequestParam.IF_NONE_MATCH, doc.getRevision()) .get().get(); @@ -68,7 +67,7 @@ void withParentHeader() throws InterruptedException, ExecutionException { final ArangoCollectionAsync collection = db.collection("route-test-col"); try { collection.create().get(); - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); collection.insertDocument(doc).get(); db.route("/_api/document").withHeader(ArangoRequestParam.IF_NONE_MATCH, doc.getRevision()) .route(doc.getId()).get().get(); diff --git a/src/test/java/com/arangodb/async/ArangoSearchTest.java b/driver/src/test/java/com/arangodb/async/ArangoSearchTest.java similarity index 64% rename from src/test/java/com/arangodb/async/ArangoSearchTest.java rename to driver/src/test/java/com/arangodb/async/ArangoSearchTest.java index 47c183b54..84dc1ba01 100644 --- a/src/test/java/com/arangodb/async/ArangoSearchTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoSearchTest.java @@ -21,17 +21,20 @@ package com.arangodb.async; import com.arangodb.ArangoDBException; +import com.arangodb.entity.InvertedIndexField; import com.arangodb.entity.ViewEntity; import com.arangodb.entity.ViewType; import com.arangodb.entity.arangosearch.*; import com.arangodb.entity.arangosearch.analyzer.*; -import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; -import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; +import com.arangodb.model.InvertedIndexOptions; +import com.arangodb.model.arangosearch.*; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import java.util.*; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.ExecutionException; import static org.assertj.core.api.Assertions.assertThat; @@ -45,12 +48,16 @@ class ArangoSearchTest extends BaseTest { private static final String VIEW_NAME = "view_test"; + private static final String COLL_1 = "view_update_prop_test_collection"; + private static final String COLL_2 = "view_replace_prop_test_collection"; @BeforeAll static void setup() throws InterruptedException, ExecutionException { if (!isAtLeastVersion(arangoDB, 3, 4)) return; db.createArangoSearch(VIEW_NAME, new ArangoSearchCreateOptions()).get(); + db.createCollection(COLL_1).get(); + db.createCollection(COLL_2).get(); } @Test @@ -59,6 +66,14 @@ void exists() throws InterruptedException, ExecutionException { assertThat(db.arangoSearch(VIEW_NAME).exists().get()).isTrue(); } + @Test + void createAndExistsSearchAlias() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + db.createSearchAlias(viewName, new SearchAliasCreateOptions()).get(); + assertThat(db.arangoSearch(viewName).exists().get()).isTrue(); + } + @Test void getInfo() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); @@ -92,7 +107,7 @@ void rename() throws InterruptedException, ExecutionException { } @Test - void create() throws InterruptedException, ExecutionException { + void createArangoSearchView() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); final String name = VIEW_NAME + "_createtest"; final ViewEntity info = db.arangoSearch(name).create().get(); @@ -104,7 +119,19 @@ void create() throws InterruptedException, ExecutionException { } @Test - void createWithOptions() throws InterruptedException, ExecutionException { + void createSearchAliasView() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + final ViewEntity info = db.searchAlias(viewName).create().get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(db.searchAlias(viewName).exists().get()).isTrue(); + } + + @Test + void createArangoSearchViewWithOptions() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); final String name = VIEW_NAME + "_createtest_withotpions"; final ViewEntity info = db.arangoSearch(name).create(new ArangoSearchCreateOptions()).get(); @@ -116,7 +143,7 @@ void createWithOptions() throws InterruptedException, ExecutionException { } @Test - void createWithPrimarySort() throws ExecutionException, InterruptedException { + void createArangoSearchViewWithPrimarySort() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); final String name = "createWithPrimarySort"; final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); @@ -135,7 +162,7 @@ void createWithPrimarySort() throws ExecutionException, InterruptedException { } @Test - void createWithCommitIntervalMsec() throws ExecutionException, InterruptedException { + void createArangoSearchViewWithCommitIntervalMsec() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); final String name = "createWithCommitIntervalMsec"; final ArangoSearchCreateOptions options = new ArangoSearchCreateOptions(); @@ -155,7 +182,49 @@ void createWithCommitIntervalMsec() throws ExecutionException, InterruptedExcept } @Test - void getProperties() throws InterruptedException, ExecutionException { + void createSearchAliasViewWithOptions() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions(); + final ViewEntity info = db.searchAlias(viewName).create(options).get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(db.searchAlias(viewName).exists().get()).isTrue(); + } + + @Test + void createSearchAliasViewWithIndexesAndGetProperties() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollectionAsync col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options).get(); + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties().get(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)); + } + + @Test + void getArangoSearchViewProperties() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); final String name = VIEW_NAME + "_getpropertiestest"; final ArangoSearchAsync view = db.arangoSearch(name); @@ -174,9 +243,8 @@ void getProperties() throws InterruptedException, ExecutionException { } @Test - void updateProperties() throws InterruptedException, ExecutionException { + void updateArangoSearchViewProperties() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); - db.createCollection("view_update_prop_test_collection").get(); final String name = VIEW_NAME + "_updatepropertiestest"; final ArangoSearchAsync view = db.arangoSearch(name); view.create(new ArangoSearchCreateOptions()).get(); @@ -207,15 +275,56 @@ void updateProperties() throws InterruptedException, ExecutionException { } @Test - void replaceProperties() throws InterruptedException, ExecutionException { + void updateSearchAliasViewWithIndexesAndGetProperties() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollectionAsync col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + ArangoCollectionAsync col2 = db.collection(COLL_2); + String idxName2 = "idx-" + rnd(); + col2.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options).get(); + db.searchAlias(viewName).updateProperties(new SearchAliasPropertiesOptions() + .indexes(new SearchAliasIndex(COLL_2, idxName2))).get(); + + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties().get(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .hasSize(2) + .anyMatch(i -> i.getCollection().equals(COLL_1) && i.getIndex().equals(idxName)) + .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); + } + + @Test + void replaceArangoSearchViewProperties() throws InterruptedException, ExecutionException { assumeTrue(isAtLeastVersion(3, 4)); - db.createCollection("view_replace_prop_test_collection").get(); final String name = VIEW_NAME + "_replacepropertiestest"; final ArangoSearchAsync view = db.arangoSearch(name); view.create(new ArangoSearchCreateOptions()).get(); final ArangoSearchPropertiesOptions options = new ArangoSearchPropertiesOptions(); options.link( - CollectionLink.on("view_replace_prop_test_collection").fields(FieldLink.on("value").analyzers("identity"))); + CollectionLink.on("view_replace_prop_test_collection").fields(FieldLink.on("value").analyzers( + "identity"))); final ArangoSearchPropertiesEntity properties = view.replaceProperties(options).get(); assertThat(properties).isNotNull(); assertThat(properties.getLinks()).hasSize(1); @@ -225,7 +334,48 @@ void replaceProperties() throws InterruptedException, ExecutionException { assertThat(link.getFields().iterator().next().getName()).isEqualTo("value"); } - private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws ExecutionException, InterruptedException { + @Test + void replaceSearchAliasViewWithIndexesAndGetProperties() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + ArangoCollectionAsync col = db.collection(COLL_1); + String idxName = "idx-" + rnd(); + col.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + ArangoCollectionAsync col2 = db.collection(COLL_2); + String idxName2 = "idx-" + rnd(); + col2.ensureInvertedIndex(new InvertedIndexOptions() + .name(idxName2) + .fields(new InvertedIndexField().name("a" + rnd()))) + .get(); + + String viewName = "view-" + rnd(); + final SearchAliasCreateOptions options = new SearchAliasCreateOptions() + .indexes(new SearchAliasIndex(COLL_1, idxName)); + final ViewEntity info = db.searchAlias(viewName).create(options).get(); + db.searchAlias(viewName).replaceProperties(new SearchAliasPropertiesOptions() + .indexes(new SearchAliasIndex(COLL_2, idxName2))).get(); + + assertThat(info).isNotNull(); + assertThat(info.getId()).isNotNull(); + assertThat(info.getName()).isEqualTo(viewName); + assertThat(info.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + + final SearchAliasPropertiesEntity properties = db.searchAlias(viewName).getProperties().get(); + assertThat(properties).isNotNull(); + assertThat(properties.getId()).isNotNull(); + assertThat(properties.getName()).isEqualTo(viewName); + assertThat(properties.getType()).isEqualTo(ViewType.SEARCH_ALIAS); + assertThat(properties.getIndexes()) + .isNotNull() + .isNotEmpty() + .hasSize(1) + .anyMatch(i -> i.getCollection().equals(COLL_2) && i.getIndex().equals(idxName2)); + } + + private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws ExecutionException, + InterruptedException { String fullyQualifiedName = db.dbName().get() + "::" + analyzer.getName(); analyzer.setName(fullyQualifiedName); @@ -239,8 +389,8 @@ private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws Exe assertThat(gotAnalyzer).isEqualTo(analyzer); // getAnalyzers - @SuppressWarnings("OptionalGetWithoutIsPresent") - SearchAnalyzer foundAnalyzer = db.getSearchAnalyzers().get().stream().filter(it -> it.getName().equals(fullyQualifiedName)) + SearchAnalyzer foundAnalyzer = + db.getSearchAnalyzers().get().stream().filter(it -> it.getName().equals(fullyQualifiedName)) .findFirst().get(); assertThat(foundAnalyzer).isEqualTo(analyzer); @@ -251,7 +401,7 @@ private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws Exe db.deleteSearchAnalyzer(analyzer.getName(), deleteOptions).get(); try { - db.getAnalyzer(analyzer.getName()).get(); + db.getSearchAnalyzer(analyzer.getName()).get(); fail("deleted analyzer should not be found!"); } catch (ExecutionException e) { assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); @@ -261,84 +411,6 @@ private void createGetAndDeleteTypedAnalyzer(SearchAnalyzer analyzer) throws Exe } - private void createGetAndDeleteAnalyzer(AnalyzerEntity options) throws ExecutionException, InterruptedException { - - String fullyQualifiedName = db.dbName().get() + "::" + options.getName(); - - // createAnalyzer - AnalyzerEntity createdAnalyzer = db.createAnalyzer(options).get(); - - assertThat(createdAnalyzer.getName()).isEqualTo(fullyQualifiedName); - assertThat(createdAnalyzer.getType()).isEqualTo(options.getType()); - assertThat(createdAnalyzer.getFeatures()).isEqualTo(options.getFeatures()); - compareProperties(createdAnalyzer.getProperties(), options.getProperties()); - - // getAnalyzer - AnalyzerEntity gotAnalyzer = db.getAnalyzer(options.getName()).get(); - assertThat(gotAnalyzer.getName()).isEqualTo(fullyQualifiedName); - assertThat(gotAnalyzer.getType()).isEqualTo(options.getType()); - assertThat(gotAnalyzer.getFeatures()).isEqualTo(options.getFeatures()); - compareProperties(gotAnalyzer.getProperties(), options.getProperties()); - - // getAnalyzers - @SuppressWarnings("OptionalGetWithoutIsPresent") - AnalyzerEntity foundAnalyzer = db.getAnalyzers().get().stream().filter(it -> it.getName().equals(fullyQualifiedName)) - .findFirst().get(); - - assertThat(foundAnalyzer.getName()).isEqualTo(fullyQualifiedName); - assertThat(foundAnalyzer.getType()).isEqualTo(options.getType()); - assertThat(foundAnalyzer.getFeatures()).isEqualTo(options.getFeatures()); - compareProperties(foundAnalyzer.getProperties(), options.getProperties()); - - AnalyzerDeleteOptions deleteOptions = new AnalyzerDeleteOptions(); - deleteOptions.setForce(true); - - // deleteAnalyzer - db.deleteAnalyzer(options.getName(), deleteOptions).get(); - - try { - db.getAnalyzer(options.getName()).get(); - fail(); - } catch (ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - assertThat(((ArangoDBException) e.getCause()).getResponseCode()).isEqualTo(404); - } - } - - private void compareProperties(Map actualProperties, Map expectedProperties) { - expectedProperties.forEach((key, expectedValue) -> { - Object actualValue = actualProperties.get(key); - if (expectedValue instanceof Map) { - assertThat(actualValue).isNotNull(); - assertThat(actualValue).isInstanceOf(Map.class); - compareProperties((Map) actualValue, (Map) expectedValue); - } else if (expectedValue instanceof Number) { - assertThat(Double.valueOf(actualValue.toString())).isEqualTo(Double.valueOf(expectedValue.toString())); - } else { - assertThat(actualValue).isEqualTo(expectedValue); - } - }); - } - - @Test - void identityAnalyzer() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.identity); - options.setProperties(Collections.emptyMap()); - - createGetAndDeleteAnalyzer(options); - } - @Test void identityAnalyzerTyped() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); @@ -357,25 +429,6 @@ void identityAnalyzerTyped() throws ExecutionException, InterruptedException { createGetAndDeleteTypedAnalyzer(analyzer); } - @Test - void delimiterAnalyzer() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.delimiter); - options.setProperties(Collections.singletonMap("delimiter", "-")); - - createGetAndDeleteAnalyzer(options); - } - @Test void delimiterAnalyzerTyped() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); @@ -398,25 +451,6 @@ void delimiterAnalyzerTyped() throws ExecutionException, InterruptedException { createGetAndDeleteTypedAnalyzer(analyzer); } - @Test - void stemAnalyzer() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.stem); - options.setProperties(Collections.singletonMap("locale", "ru")); - - createGetAndDeleteAnalyzer(options); - } - @Test void stemAnalyzerTyped() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); @@ -439,30 +473,6 @@ void stemAnalyzerTyped() throws ExecutionException, InterruptedException { createGetAndDeleteTypedAnalyzer(options); } - @Test - void normAnalyzer() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("locale", "ru"); - properties.put("case", "lower"); - properties.put("accent", true); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.norm); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(options); - } - @Test void normAnalyzerTyped() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); @@ -487,31 +497,6 @@ void normAnalyzerTyped() throws ExecutionException, InterruptedException { createGetAndDeleteTypedAnalyzer(options); } - @Test - void ngramAnalyzer() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("max", 6L); - properties.put("min", 3L); - properties.put("preserveOriginal", true); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.ngram); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(options); - } - @Test void ngramAnalyzerTyped() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); @@ -537,33 +522,6 @@ void ngramAnalyzerTyped() throws ExecutionException, InterruptedException { createGetAndDeleteTypedAnalyzer(analyzer); } - @Test - void textAnalyzer() throws ExecutionException, InterruptedException { - assumeTrue(isAtLeastVersion(3, 5)); - - String name = "test-" + UUID.randomUUID(); - - Set features = new HashSet<>(); - features.add(AnalyzerFeature.frequency); - features.add(AnalyzerFeature.norm); - features.add(AnalyzerFeature.position); - - Map properties = new HashMap<>(); - properties.put("locale", "ru"); - properties.put("case", "lower"); - properties.put("stopwords", Collections.emptyList()); - properties.put("accent", true); - properties.put("stemming", true); - - AnalyzerEntity options = new AnalyzerEntity(); - options.setFeatures(features); - options.setName(name); - options.setType(AnalyzerType.text); - options.setProperties(properties); - - createGetAndDeleteAnalyzer(options); - } - @Test void textAnalyzerTyped() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); diff --git a/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java b/driver/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java similarity index 88% rename from src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java rename to driver/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java index cdaa860c8..4da5b6735 100644 --- a/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java +++ b/driver/src/test/java/com/arangodb/async/ArangoVertexCollectionTest.java @@ -29,11 +29,10 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; - import java.util.Collection; +import java.util.UUID; import java.util.concurrent.ExecutionException; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; @@ -102,14 +101,10 @@ void getVertexIfMatch() throws InterruptedException, ExecutionException { void getVertexIfMatchFail() throws InterruptedException, ExecutionException { final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) .insertVertex(new BaseDocument(), null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no").catchException(false); - try { - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(vertex.getKey(), BaseDocument.class, options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifMatch("no"); + BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(vertex.getKey(), BaseDocument.class, options).get(); + assertThat(res).isNull(); } @Test @@ -127,23 +122,19 @@ void getVertexIfNoneMatch() throws InterruptedException, ExecutionException { void getVertexIfNoneMatchFail() throws InterruptedException, ExecutionException { final VertexEntity vertex = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) .insertVertex(new BaseDocument(), null).get(); - final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(vertex.getRev()).catchException(false); - try { - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(vertex.getKey(), BaseDocument.class, options).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + final GraphDocumentReadOptions options = new GraphDocumentReadOptions().ifNoneMatch(vertex.getRev()); + BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(vertex.getKey(), BaseDocument.class, options).get(); + assertThat(res).isNull(); } @Test void replaceVertex() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final VertexUpdateEntity replaceResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) .replaceVertex(createResult.getKey(), doc, null).get(); @@ -163,11 +154,11 @@ void replaceVertex() throws InterruptedException, ExecutionException { @Test void replaceVertexIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch(createResult.getRev()); final VertexUpdateEntity replaceResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) @@ -188,11 +179,11 @@ void replaceVertexIfMatch() throws InterruptedException, ExecutionException { @Test void replaceVertexIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); - doc.getProperties().clear(); + doc.removeAttribute("a"); doc.addAttribute("b", "test"); try { final VertexReplaceOptions options = new VertexReplaceOptions().ifMatch("no"); @@ -206,7 +197,7 @@ void replaceVertexIfMatchFail() throws InterruptedException, ExecutionException @Test void updateVertex() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) @@ -234,7 +225,7 @@ void updateVertex() throws InterruptedException, ExecutionException { @Test void updateVertexIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) @@ -263,7 +254,7 @@ void updateVertexIfMatch() throws InterruptedException, ExecutionException { @Test void updateVertexIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); doc.addAttribute("c", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) @@ -283,7 +274,7 @@ void updateVertexIfMatchFail() throws InterruptedException, ExecutionException { @Test void updateVertexKeepNullTrue() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); @@ -299,13 +290,13 @@ void updateVertexKeepNullTrue() throws InterruptedException, ExecutionException final BaseDocument readResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) .getVertex(createResult.getKey(), BaseDocument.class, null).get(); assertThat(readResult.getKey()).isEqualTo(createResult.getKey()); - assertThat(readResult.getProperties().keySet()).hasSize(1); + assertThat(readResult.getProperties().keySet()).hasSize(4); assertThat(readResult.getProperties()).containsKey("a"); } @Test void updateVertexKeepNullFalse() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("a", "test"); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); @@ -328,38 +319,30 @@ void updateVertexKeepNullFalse() throws InterruptedException, ExecutionException @Test void deleteVertex() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).deleteVertex(createResult.getKey(), null).get(); - try { - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(createResult.getKey(), BaseDocument.class, new GraphDocumentReadOptions().catchException(false)).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(createResult.getKey(), BaseDocument.class, new GraphDocumentReadOptions()).get(); + assertThat(res).isNull(); } @Test void deleteVertexIfMatch() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch(createResult.getRev()); db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).deleteVertex(createResult.getKey(), options).get(); - try { - db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) - .getVertex(createResult.getKey(), BaseDocument.class, new GraphDocumentReadOptions().catchException(false)).get(); - fail(); - } catch (final ExecutionException e) { - assertThat(e.getCause()).isInstanceOf(ArangoDBException.class); - } + BaseDocument res = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME) + .getVertex(createResult.getKey(), BaseDocument.class, new GraphDocumentReadOptions()).get(); + assertThat(res).isNull(); } @Test void deleteVertexIfMatchFail() throws InterruptedException, ExecutionException { - final BaseDocument doc = new BaseDocument(); + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); final VertexEntity createResult = db.graph(GRAPH_NAME).vertexCollection(COLLECTION_NAME).insertVertex(doc, null) .get(); final VertexDeleteOptions options = new VertexDeleteOptions().ifMatch("no"); diff --git a/src/test/java/com/arangodb/async/ArangoViewTest.java b/driver/src/test/java/com/arangodb/async/ArangoViewTest.java similarity index 100% rename from src/test/java/com/arangodb/async/ArangoViewTest.java rename to driver/src/test/java/com/arangodb/async/ArangoViewTest.java diff --git a/src/test/java/com/arangodb/async/BaseTest.java b/driver/src/test/java/com/arangodb/async/BaseTest.java similarity index 74% rename from src/test/java/com/arangodb/async/BaseTest.java rename to driver/src/test/java/com/arangodb/async/BaseTest.java index db4f312aa..261996ab9 100644 --- a/src/test/java/com/arangodb/async/BaseTest.java +++ b/driver/src/test/java/com/arangodb/async/BaseTest.java @@ -20,11 +20,13 @@ package com.arangodb.async; -import com.arangodb.entity.ArangoDBEngine; import com.arangodb.DbName; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.ConfigUtils; +import com.arangodb.entity.ArangoDBEngine; import com.arangodb.entity.License; import com.arangodb.entity.ServerRole; -import com.arangodb.mapping.ArangoJack; +import com.arangodb.util.TestUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -36,7 +38,7 @@ * @author Mark Vollmary */ public abstract class BaseTest { - + protected static final ArangoConfigProperties config = ConfigUtils.loadConfig(); static final DbName TEST_DB = DbName.of("java_driver_test_db"); static ArangoDBAsync arangoDB; static ArangoDatabaseAsync db; @@ -44,7 +46,9 @@ public abstract class BaseTest { @BeforeAll static void init() throws InterruptedException, ExecutionException { if (arangoDB == null) { - arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDBAsync.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); } if (arangoDB.db(TEST_DB).exists().get()) { @@ -66,9 +70,11 @@ static String rnd() { return UUID.randomUUID().toString(); } - protected static boolean isAtLeastVersion(final ArangoDBAsync arangoDB, final int major, final int minor, final int patch) + protected static boolean isAtLeastVersion(final ArangoDBAsync arangoDB, final int major, final int minor, + final int patch) throws InterruptedException, ExecutionException { - return com.arangodb.util.TestUtils.isAtLeastVersion(arangoDB.getVersion().get().getVersion(), major, minor, patch); + return com.arangodb.util.TestUtils.isAtLeastVersion(arangoDB.getVersion().get().getVersion(), major, minor, + patch); } protected static boolean isAtLeastVersion(final ArangoDBAsync arangoDB, final int major, final int minor) @@ -76,14 +82,24 @@ protected static boolean isAtLeastVersion(final ArangoDBAsync arangoDB, final in return isAtLeastVersion(arangoDB, major, minor, 0); } - protected boolean isAtLeastVersion(final int major, final int minor, final int patch) throws InterruptedException, ExecutionException { + protected boolean isAtLeastVersion(final int major, final int minor, final int patch) throws InterruptedException + , ExecutionException { return isAtLeastVersion(arangoDB, major, minor, patch); } - protected boolean isAtLeastVersion(final int major, final int minor) throws InterruptedException, ExecutionException { + protected boolean isAtLeastVersion(final int major, final int minor) throws InterruptedException, + ExecutionException { return isAtLeastVersion(major, minor, 0); } + boolean isLessThanVersion(final int major, final int minor) throws ExecutionException, InterruptedException { + return isLessThanVersion(major, minor, 0); + } + + boolean isLessThanVersion(final int major, final int minor, final int patch) throws ExecutionException, InterruptedException { + return TestUtils.isLessThanVersion(db.getVersion().get().getVersion(), major, minor, patch); + } + boolean isStorageEngine(ArangoDBEngine.StorageEngineName name) throws ExecutionException, InterruptedException { return name.equals(db.getEngine().get().getName()); } diff --git a/src/test/java/com/arangodb/async/CommunicationTest.java b/driver/src/test/java/com/arangodb/async/CommunicationTest.java similarity index 94% rename from src/test/java/com/arangodb/async/CommunicationTest.java rename to driver/src/test/java/com/arangodb/async/CommunicationTest.java index 744aa0087..0b2b6c962 100644 --- a/src/test/java/com/arangodb/async/CommunicationTest.java +++ b/driver/src/test/java/com/arangodb/async/CommunicationTest.java @@ -20,11 +20,9 @@ package com.arangodb.async; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; - import java.util.concurrent.CompletableFuture; import static org.assertj.core.api.Assertions.assertThat; @@ -38,7 +36,7 @@ class CommunicationTest { @Test @Disabled void disconnect() { - final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); final CompletableFuture> result = arangoDB.db().query("return sleep(1)", null, null, null); arangoDB.shutdown(); diff --git a/src/test/java/com/arangodb/async/ConcurrencyTest.java b/driver/src/test/java/com/arangodb/async/ConcurrencyTest.java similarity index 95% rename from src/test/java/com/arangodb/async/ConcurrencyTest.java rename to driver/src/test/java/com/arangodb/async/ConcurrencyTest.java index 46c6bd552..f0643c2ca 100644 --- a/src/test/java/com/arangodb/async/ConcurrencyTest.java +++ b/driver/src/test/java/com/arangodb/async/ConcurrencyTest.java @@ -23,7 +23,6 @@ import com.arangodb.async.internal.ArangoExecutorAsync; import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -47,7 +46,7 @@ class ConcurrencyTest { @BeforeEach void initialize() { - arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDBAsync.Builder().build(); } /** diff --git a/src/test/java/com/arangodb/async/ConcurrencyTests.java b/driver/src/test/java/com/arangodb/async/ConcurrencyTests.java similarity index 80% rename from src/test/java/com/arangodb/async/ConcurrencyTests.java rename to driver/src/test/java/com/arangodb/async/ConcurrencyTests.java index edbad7c81..278486efc 100644 --- a/src/test/java/com/arangodb/async/ConcurrencyTests.java +++ b/driver/src/test/java/com/arangodb/async/ConcurrencyTests.java @@ -1,8 +1,7 @@ package com.arangodb.async; - -import com.arangodb.mapping.ArangoJack; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.Test; import java.util.List; @@ -15,7 +14,9 @@ class ConcurrencyTests { @Test void concurrentPendingRequests() throws ExecutionException, InterruptedException { - ArangoDBAsync adb = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + ArangoDBAsync adb = new ArangoDBAsync.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); List>> reqs = IntStream.range(0, 10) .mapToObj(__ -> adb.db().query("RETURN SLEEP(1)", Void.class)) .collect(Collectors.toList()); diff --git a/driver/src/test/java/com/arangodb/async/InvertedIndexTest.java b/driver/src/test/java/com/arangodb/async/InvertedIndexTest.java new file mode 100644 index 000000000..e4451f77c --- /dev/null +++ b/driver/src/test/java/com/arangodb/async/InvertedIndexTest.java @@ -0,0 +1,199 @@ +package com.arangodb.async; + +import com.arangodb.entity.*; +import com.arangodb.entity.arangosearch.*; +import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer; +import com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties; +import com.arangodb.model.InvertedIndexOptions; +import com.arangodb.model.PersistentIndexOptions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.*; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +public class InvertedIndexTest extends BaseTest { + + private static final String COLLECTION_NAME = "InvertedIndexTestAsync_collection"; + + InvertedIndexTest() throws ExecutionException, InterruptedException { + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + if (!collection.exists().get()) { + collection.create().get(); + } + } + + @BeforeAll + static void setup() throws InterruptedException, ExecutionException { + db.createCollection(COLLECTION_NAME, null).get(); + } + + @AfterEach + void teardown() throws InterruptedException, ExecutionException { + db.collection(COLLECTION_NAME).drop().get(); + } + + + private void createAnalyzer(String analyzerName, ArangoDatabaseAsync db) throws ExecutionException, InterruptedException { + Set features = new HashSet<>(); + features.add(AnalyzerFeature.frequency); + features.add(AnalyzerFeature.norm); + features.add(AnalyzerFeature.position); + + DelimiterAnalyzer da = new DelimiterAnalyzer(); + da.setName(analyzerName); + da.setFeatures(features); + DelimiterAnalyzerProperties props = new DelimiterAnalyzerProperties(); + props.setDelimiter("-"); + da.setProperties(props); + + db.createSearchAnalyzer(da).get(); + } + + private InvertedIndexOptions createOptions(String analyzerName) throws ExecutionException, InterruptedException { + InvertedIndexField field = new InvertedIndexField() + .name("foo") + .analyzer(AnalyzerType.identity.toString()) + .includeAllFields(true) + .searchField(false) + .trackListPositions(false) + .features( + AnalyzerFeature.position, + AnalyzerFeature.frequency, + AnalyzerFeature.norm, + AnalyzerFeature.offset + ); + + if (isEnterprise()) { + field.nested( + new InvertedIndexField() + .name("bar") + .analyzer(analyzerName) + .searchField(true) + .features(AnalyzerFeature.position, AnalyzerFeature.frequency) + .nested( + new InvertedIndexField() + .name("baz") + .analyzer(AnalyzerType.identity.toString()) + .searchField(false) + .features(AnalyzerFeature.frequency) + ) + ); + } + + return new InvertedIndexOptions() + .name("invertedIndex-" + UUID.randomUUID()) + .inBackground(true) + .parallelism(5) + .primarySort(new InvertedIndexPrimarySort() + .fields( + new InvertedIndexPrimarySort.Field("f1", InvertedIndexPrimarySort.Field.Direction.asc), + new InvertedIndexPrimarySort.Field("f2", InvertedIndexPrimarySort.Field.Direction.desc) + ) + .compression(ArangoSearchCompression.lz4) + ) + .storedValues(new StoredValue(Arrays.asList("f3", "f4"), ArangoSearchCompression.none)) + .analyzer(analyzerName) + .features(AnalyzerFeature.position, AnalyzerFeature.frequency) + .includeAllFields(false) + .trackListPositions(true) + .searchField(true) + .fields(field) + .consolidationIntervalMsec(11L) + .commitIntervalMsec(22L) + .cleanupIntervalStep(33L) + .consolidationPolicy(ConsolidationPolicy.of(ConsolidationType.BYTES_ACCUM).threshold(1.)) + .writebufferIdle(44L) + .writebufferActive(55L) + .writebufferSizeMax(66L); + } + + private void assertCorrectIndexEntity(InvertedIndexEntity indexResult, InvertedIndexOptions options) { + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getId()).isNotNull().isNotEmpty(); + // FIXME: in single server this is null + // assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getVersion()).isNotNull(); + assertThat(indexResult.getCode()).isNotNull(); + assertThat(indexResult.getType()).isEqualTo(IndexType.inverted); + assertThat(indexResult.getName()).isEqualTo(options.getName()); + assertThat(indexResult.getFields()).containsExactlyElementsOf(options.getFields()); + assertThat(indexResult.getSearchField()).isEqualTo(options.getSearchField()); + assertThat(indexResult.getStoredValues()).containsExactlyElementsOf(options.getStoredValues()); + assertThat(indexResult.getPrimarySort()).isEqualTo(options.getPrimarySort()); + assertThat(indexResult.getAnalyzer()).isEqualTo(options.getAnalyzer()); + assertThat(indexResult.getFeatures()).hasSameElementsAs(options.getFeatures()); + assertThat(indexResult.getIncludeAllFields()).isEqualTo(options.getIncludeAllFields()); + assertThat(indexResult.getTrackListPositions()).isEqualTo(options.getTrackListPositions()); + assertThat(indexResult.getCleanupIntervalStep()).isEqualTo(options.getCleanupIntervalStep()); + assertThat(indexResult.getCommitIntervalMsec()).isEqualTo(options.getCommitIntervalMsec()); + assertThat(indexResult.getConsolidationIntervalMsec()).isEqualTo(options.getConsolidationIntervalMsec()); + assertThat(indexResult.getConsolidationPolicy()).isEqualTo(options.getConsolidationPolicy()); + assertThat(indexResult.getWritebufferIdle()).isEqualTo(options.getWritebufferIdle()); + assertThat(indexResult.getWritebufferActive()).isEqualTo(options.getWritebufferActive()); + assertThat(indexResult.getWritebufferSizeMax()).isEqualTo(options.getWritebufferSizeMax()); + } + + @Test + void createAndGetInvertedIndex() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options).get(); + assertCorrectIndexEntity(created, options); + InvertedIndexEntity loadedIndex = collection.getInvertedIndex(created.getName()).get(); + assertCorrectIndexEntity(loadedIndex, options); + } + + @Test + void getInvertedIndexesShouldNotReturnOtherIndexTypes() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + + // create persistent index + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")); + + // create inverted index + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options).get(); + + Collection loadedIndexes = collection.getInvertedIndexes().get(); + assertThat(loadedIndexes).map(InvertedIndexEntity::getName) + .doesNotContain("persistentIndex") + .contains(created.getName()); + } + + @Test + void getIndexesShouldNotReturnInvertedIndexes() throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 10)); + + ArangoCollectionAsync collection = db.collection(COLLECTION_NAME); + + // create persistent index + collection.ensurePersistentIndex(Collections.singletonList("foo"), new PersistentIndexOptions().name("persistentIndex")).get(); + + // create inverted index + String analyzerName = "delimiter-" + UUID.randomUUID(); + createAnalyzer(analyzerName, collection.db()); + InvertedIndexOptions options = createOptions(analyzerName); + InvertedIndexEntity created = collection.ensureInvertedIndex(options).get(); + + Collection loadedIndexes = collection.getIndexes().get(); + assertThat(loadedIndexes).map(IndexEntity::getName) + .doesNotContain(created.getName()) + .contains("persistentIndex"); + } + +} diff --git a/src/test/java/com/arangodb/async/JwtAuthTest.java b/driver/src/test/java/com/arangodb/async/JwtAuthTest.java similarity index 75% rename from src/test/java/com/arangodb/async/JwtAuthTest.java rename to driver/src/test/java/com/arangodb/async/JwtAuthTest.java index c9d0f40d1..04bbfc98d 100644 --- a/src/test/java/com/arangodb/async/JwtAuthTest.java +++ b/driver/src/test/java/com/arangodb/async/JwtAuthTest.java @@ -1,23 +1,16 @@ package com.arangodb.async; -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDBException; -import com.arangodb.DbName; -import com.arangodb.mapping.ArangoJack; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; -import com.arangodb.velocystream.Response; +import com.arangodb.*; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; - import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutionException; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; @@ -28,11 +21,29 @@ class JwtAuthTest { @BeforeAll static void init() { - ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); jwt = getJwt(arangoDB); arangoDB.shutdown(); } + private static String getJwt(ArangoDB arangoDB) { + Map reqBody = new HashMap<>(); + reqBody.put("username", "root"); + reqBody.put("password", "test"); + + Request req = Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.POST) + .path("/_open/auth") + .body(reqBody) + .build(); + + Response resp = arangoDB.execute(req, Map.class); + return (String) resp.getBody().get("jwt"); + } + @AfterEach void after() { if (arangoDB != null) @@ -62,6 +73,7 @@ void authenticated() throws ExecutionException, InterruptedException { } @Test + @Disabled("DE-423") void updateJwt() throws ExecutionException, InterruptedException { arangoDB = getBuilder() .jwt(jwt) @@ -83,23 +95,9 @@ void updateJwt() throws ExecutionException, InterruptedException { private ArangoDBAsync.Builder getBuilder() { return new ArangoDBAsync.Builder() - .serializer(new ArangoJack()) + .loadProperties(ConfigUtils.loadConfig()) .jwt(null) // unset credentials from properties file .user(null) // unset credentials from properties file .password(null); // unset credentials from properties file } - - private static String getJwt(ArangoDB arangoDB) { - ArangoSerialization serde = arangoDB.util(); - Map reqBody = new HashMap<>(); - reqBody.put("username", "root"); - reqBody.put("password", "test"); - - Request req = new Request(DbName.SYSTEM, RequestType.POST, "/_open/auth"); - req.setBody(serde.serialize(reqBody)); - - Response resp = arangoDB.execute(req); - Map respBody = serde.deserialize(resp.getBody(), Map.class); - return respBody.get("jwt"); - } } diff --git a/src/test/java/com/arangodb/async/StreamTransactionConflictsTest.java b/driver/src/test/java/com/arangodb/async/StreamTransactionConflictsTest.java similarity index 100% rename from src/test/java/com/arangodb/async/StreamTransactionConflictsTest.java rename to driver/src/test/java/com/arangodb/async/StreamTransactionConflictsTest.java diff --git a/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java b/driver/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java similarity index 89% rename from src/test/java/com/arangodb/async/StreamTransactionGraphTest.java rename to driver/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java index cb62b8f8f..60ee6ea11 100644 --- a/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java +++ b/driver/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java @@ -21,27 +21,13 @@ package com.arangodb.async; -import com.arangodb.entity.ArangoDBEngine; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.entity.EdgeDefinition; -import com.arangodb.entity.EdgeEntity; -import com.arangodb.entity.StreamTransactionEntity; -import com.arangodb.entity.VertexEntity; -import com.arangodb.model.EdgeCreateOptions; -import com.arangodb.model.EdgeDeleteOptions; -import com.arangodb.model.EdgeReplaceOptions; -import com.arangodb.model.EdgeUpdateOptions; -import com.arangodb.model.GraphDocumentReadOptions; -import com.arangodb.model.StreamTransactionOptions; -import com.arangodb.model.VertexCreateOptions; -import com.arangodb.model.VertexDeleteOptions; -import com.arangodb.model.VertexReplaceOptions; -import com.arangodb.model.VertexUpdateOptions; +import com.arangodb.entity.*; +import com.arangodb.model.*; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import java.util.Collections; +import java.util.UUID; import java.util.concurrent.ExecutionException; import static org.assertj.core.api.Assertions.assertThat; @@ -89,9 +75,12 @@ void teardown() throws ExecutionException, InterruptedException { db.collection(VERTEX_COLLECTION_2).drop().get(); } - private BaseEdgeDocument createEdgeValue(String streamTransactionId) throws ExecutionException, InterruptedException { - final VertexEntity v1 = vertexCollection1.insertVertex(new BaseDocument(), new VertexCreateOptions().streamTransactionId(streamTransactionId)).get(); - final VertexEntity v2 = vertexCollection2.insertVertex(new BaseDocument(), new VertexCreateOptions().streamTransactionId(streamTransactionId)).get(); + private BaseEdgeDocument createEdgeValue(String streamTransactionId) throws ExecutionException, + InterruptedException { + final VertexEntity v1 = vertexCollection1.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(streamTransactionId)).get(); + final VertexEntity v2 = vertexCollection2.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(streamTransactionId)).get(); final BaseEdgeDocument value = new BaseEdgeDocument(); value.setFrom(v1.getId()); value.setTo(v2.getId()); @@ -132,7 +121,8 @@ void createVertex() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // insert a vertex from within the tx - VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument(), new VertexCreateOptions().streamTransactionId(tx.getId())).get(); + VertexEntity createdVertex = vertexCollection1.insertVertex(new BaseDocument(), + new VertexCreateOptions().streamTransactionId(tx.getId())).get(); // assert that the vertex is not found from outside the tx assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null).get()).isNull(); @@ -153,7 +143,7 @@ void replaceVertex() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("test", "foo"); VertexEntity createdVertex = vertexCollection1.insertVertex(doc, null).get(); @@ -164,8 +154,7 @@ void replaceVertex() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // replace vertex from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); vertexCollection1.replaceVertex(createdVertex.getKey(), doc, new VertexReplaceOptions().streamTransactionId(tx.getId())).get(); @@ -175,7 +164,8 @@ void replaceVertex() throws ExecutionException, InterruptedException { // assert that the vertex has been replaced from within the tx assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( + "test", "bar"); db.commitStreamTransaction(tx.getId()).get(); @@ -190,7 +180,7 @@ void updateVertex() throws ExecutionException, InterruptedException { assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); - BaseDocument doc = new BaseDocument(); + BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); doc.addAttribute("test", "foo"); VertexEntity createdDoc = vertexCollection1.insertVertex(doc, null).get(); @@ -201,9 +191,9 @@ void updateVertex() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // update vertex from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); - vertexCollection1.updateVertex(createdDoc.getKey(), doc, new VertexUpdateOptions().streamTransactionId(tx.getId())).get(); + doc.updateAttribute("test", "bar"); + vertexCollection1.updateVertex(createdDoc.getKey(), doc, + new VertexUpdateOptions().streamTransactionId(tx.getId())).get(); // assert that the vertex has not been updated from outside the tx assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null).get() @@ -211,7 +201,8 @@ void updateVertex() throws ExecutionException, InterruptedException { // assert that the vertex has been updated from within the tx assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( + "test", "bar"); db.commitStreamTransaction(tx.getId()).get(); @@ -234,7 +225,8 @@ void deleteVertex() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // delete vertex from within the tx - vertexCollection1.deleteVertex(createdDoc.getKey(), new VertexDeleteOptions().streamTransactionId(tx.getId())).get(); + vertexCollection1.deleteVertex(createdDoc.getKey(), + new VertexDeleteOptions().streamTransactionId(tx.getId())).get(); // assert that the vertex has not been deleted from outside the tx assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null).get()).isNotNull(); @@ -284,7 +276,8 @@ void createEdge() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // insert an edge from within the tx - EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(tx.getId()), new EdgeCreateOptions().streamTransactionId(tx.getId())).get(); + EdgeEntity createdEdge = edgeCollection.insertEdge(createEdgeValue(tx.getId()), + new EdgeCreateOptions().streamTransactionId(tx.getId())).get(); // assert that the edge is not found from outside the tx assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null).get()).isNull(); @@ -316,8 +309,7 @@ void replaceEdge() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // replace edge from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); edgeCollection.replaceEdge(createdEdge.getKey(), doc, new EdgeReplaceOptions().streamTransactionId(tx.getId())).get(); @@ -327,7 +319,8 @@ void replaceEdge() throws ExecutionException, InterruptedException { // assert that the edge has been replaced from within the tx assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( + "test", "bar"); db.commitStreamTransaction(tx.getId()).get(); @@ -353,8 +346,7 @@ void updateEdge() throws ExecutionException, InterruptedException { .writeCollections(VERTEX_COLLECTION_1, VERTEX_COLLECTION_2, EDGE_COLLECTION)).get(); // update edge from within the tx - doc.getProperties().clear(); - doc.addAttribute("test", "bar"); + doc.updateAttribute("test", "bar"); edgeCollection.updateEdge(createdDoc.getKey(), doc, new EdgeUpdateOptions().streamTransactionId(tx.getId())) .get(); @@ -364,7 +356,8 @@ void updateEdge() throws ExecutionException, InterruptedException { // assert that the edge has been updated from within the tx assertThat(edgeCollection.getEdge(createdDoc.getKey(), BaseEdgeDocument.class, - new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry("test", "bar"); + new GraphDocumentReadOptions().streamTransactionId(tx.getId())).get().getProperties()).containsEntry( + "test", "bar"); db.commitStreamTransaction(tx.getId()).get(); diff --git a/src/test/java/com/arangodb/async/StreamTransactionTest.java b/driver/src/test/java/com/arangodb/async/StreamTransactionTest.java similarity index 97% rename from src/test/java/com/arangodb/async/StreamTransactionTest.java rename to driver/src/test/java/com/arangodb/async/StreamTransactionTest.java index 9925a110e..658bab18b 100644 --- a/src/test/java/com/arangodb/async/StreamTransactionTest.java +++ b/driver/src/test/java/com/arangodb/async/StreamTransactionTest.java @@ -110,7 +110,8 @@ void abortStreamTransactionTwice() throws ExecutionException, InterruptedExcepti } @Test - void abortStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, InterruptedException { + void abortStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, + InterruptedException { assumeTrue(isSingleServer()); assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); @@ -171,7 +172,8 @@ void getStreamTransaction() throws ExecutionException, InterruptedException { } @Test - void getStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, InterruptedException { + void getStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, + InterruptedException { assumeTrue(isSingleServer()); assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); @@ -224,7 +226,8 @@ void commitStreamTransactionTwice() throws ExecutionException, InterruptedExcept } @Test - void commitStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, InterruptedException { + void commitStreamTransactionWhenTransactionIdDoesNotExistsShouldThrow() throws ExecutionException, + InterruptedException { assumeTrue(isSingleServer()); assumeTrue(isAtLeastVersion(3, 5)); assumeTrue(isStorageEngine(ArangoDBEngine.StorageEngineName.rocksdb)); @@ -350,7 +353,7 @@ void getStreamTransactions() throws ExecutionException, InterruptedException { assertThat(gotTxs).hasSameSizeAs(createdIds); assertThat(gotTxs.stream() - .allMatch(it -> it.getStatus() == StreamTransactionStatus.running)).isTrue(); + .allMatch(it -> it.getState() == StreamTransactionStatus.running)).isTrue(); db.abortStreamTransaction(tx1.getId()).get(); db.abortStreamTransaction(tx2.getId()).get(); diff --git a/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java b/driver/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java similarity index 97% rename from src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java rename to driver/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java index 14f5b7ab3..330ce8eb9 100644 --- a/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java +++ b/driver/src/test/java/com/arangodb/async/debug/ConsolidationIntervalMsecTest.java @@ -29,7 +29,6 @@ import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; import com.arangodb.entity.arangosearch.CollectionLink; import com.arangodb.entity.arangosearch.FieldLink; -import com.arangodb.mapping.ArangoJack; import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; import org.junit.jupiter.api.Test; @@ -50,7 +49,7 @@ void consolidationIntervalMsec() throws ExecutionException, InterruptedException assumeTrue(isAtLeastVersion(3, 4)); ArangoDBAsync arango = new ArangoDBAsync.Builder() - .serializer(new ArangoJack()) + .loadProperties(config) .user("root") .password("test") .build(); diff --git a/src/test/java/com/arangodb/async/example/ExampleBase.java b/driver/src/test/java/com/arangodb/async/example/ExampleBase.java similarity index 91% rename from src/test/java/com/arangodb/async/example/ExampleBase.java rename to driver/src/test/java/com/arangodb/async/example/ExampleBase.java index 9ae6e510a..7881fd617 100644 --- a/src/test/java/com/arangodb/async/example/ExampleBase.java +++ b/driver/src/test/java/com/arangodb/async/example/ExampleBase.java @@ -24,7 +24,7 @@ import com.arangodb.async.ArangoCollectionAsync; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.mapping.ArangoJack; +import com.arangodb.config.ConfigUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -43,7 +43,9 @@ public class ExampleBase { @BeforeAll static void setUp() throws InterruptedException, ExecutionException { - arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDBAsync.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); if (arangoDB.db(DB_NAME).exists().get()) { arangoDB.db(DB_NAME).drop().get(); } diff --git a/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/driver/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java similarity index 69% rename from src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java index a5ab9ab14..9ab6624df 100644 --- a/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ b/driver/src/test/java/com/arangodb/async/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -22,13 +22,15 @@ import com.arangodb.async.example.ExampleBase; import com.arangodb.entity.BaseDocument; -import com.arangodb.util.MapBuilder; -import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.concurrent.ExecutionException; import static org.assertj.core.api.Assertions.assertThat; @@ -46,7 +48,7 @@ static void before() throws InterruptedException, ExecutionException { private static void createExamples() throws InterruptedException, ExecutionException { for (int i = 0; i < 100; i++) { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("name", "TestUser" + i); value.addAttribute("gender", (i % 2) == 0 ? Gender.MALE : Gender.FEMALE); value.addAttribute("age", i + 10); @@ -55,29 +57,31 @@ private static void createExamples() throws InterruptedException, ExecutionExcep } @Test - void aqlWithLimitQueryAsVPackObject() throws InterruptedException, ExecutionException { + void aqlWithLimitQueryAsJsonObject() throws InterruptedException, ExecutionException { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); - db.query(query, bindVars, null, VPackSlice.class) - .whenComplete((cursor, ex) -> cursor.forEachRemaining(vpack -> { - assertThat(vpack.get("name").getAsString()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); - assertThat(vpack.get("gender").getAsString()).isEqualTo(Gender.FEMALE.name()); - assertThat(vpack.get("age").getAsInt()).isIn(21, 23, 25, 27, 29); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); + db.query(query, bindVars, null, ObjectNode.class) + .whenComplete((cursor, ex) -> cursor.forEachRemaining(node -> { + assertThat(node.get("name").asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17" + , "TestUser19"); + assertThat(node.get("gender").asText()).isEqualTo(Gender.FEMALE.name()); + assertThat(node.get("age").asInt()).isIn(21, 23, 25, 27, 29); })) .get(); } @Test - void aqlWithLimitQueryAsVPackArray() throws InterruptedException, ExecutionException { + void aqlWithLimitQueryAsArrayNode() throws InterruptedException, ExecutionException { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); - db.query(query, bindVars, null, VPackSlice.class) - .whenComplete((cursor, ex) -> cursor.forEachRemaining(vpack -> { - assertThat(vpack.get(0).getAsString()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); - assertThat(vpack.get(1).getAsString()).isEqualTo(Gender.FEMALE.name()); - assertThat(vpack.get(2).getAsInt()).isIn(21, 23, 25, 27, 29); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); + db.query(query, bindVars, null, ArrayNode.class) + .whenComplete((cursor, ex) -> cursor.forEachRemaining(arrNode -> { + assertThat(arrNode.get(0).asText()).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", + "TestUser19"); + assertThat(arrNode.get(1).asText()).isEqualTo(Gender.FEMALE.name()); + assertThat(arrNode.get(2).asInt()).isIn(21, 23, 25, 27, 29); })) .get(); } @@ -86,11 +90,12 @@ void aqlWithLimitQueryAsVPackArray() throws InterruptedException, ExecutionExcep void aqlWithLimitQueryAsMap() throws InterruptedException, ExecutionException { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); db.query(query, bindVars, null, Map.class) .whenComplete((cursor, ex) -> cursor.forEachRemaining(map -> { assertThat(map.get("name")).isNotNull(); - assertThat(String.valueOf(map.get("name"))).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); + assertThat(String.valueOf(map.get("name"))).isIn("TestUser11", "TestUser13", "TestUser15", + "TestUser17", "TestUser19"); assertThat(map.get("gender")).isNotNull(); assertThat(String.valueOf(map.get("gender"))).isEqualTo(Gender.FEMALE.name()); assertThat(map.get("age")).isNotNull(); @@ -103,11 +108,12 @@ void aqlWithLimitQueryAsMap() throws InterruptedException, ExecutionException { void aqlWithLimitQueryAsList() throws InterruptedException, ExecutionException { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); db.query(query, bindVars, null, List.class) .whenComplete((cursor, ex) -> cursor.forEachRemaining(list -> { assertThat(list.get(0)).isNotNull(); - assertThat(String.valueOf(list.get(0))).isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); + assertThat(String.valueOf(list.get(0))).isIn("TestUser11", "TestUser13", "TestUser15", + "TestUser17", "TestUser19"); assertThat(list.get(1)).isNotNull(); assertThat(Gender.valueOf(String.valueOf(list.get(1)))).isEqualTo(Gender.FEMALE); assertThat(list.get(2)).isNotNull(); diff --git a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java b/driver/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java similarity index 75% rename from src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java index 0e7ae4c72..01a6c149d 100644 --- a/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java +++ b/driver/src/test/java/com/arangodb/async/example/document/GetDocumentExampleTest.java @@ -22,12 +22,12 @@ import com.arangodb.async.example.ExampleBase; import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.velocypack.VPackSlice; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; - +import java.util.UUID; import java.util.concurrent.ExecutionException; import static org.assertj.core.api.Assertions.assertThat; @@ -42,10 +42,9 @@ class GetDocumentExampleTest extends ExampleBase { @BeforeAll static void before() throws InterruptedException, ExecutionException { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("foo", "bar"); - final DocumentCreateEntity doc = collection.insertDocument(value).get(); - key = doc.getKey(); + key = collection.insertDocument(value).get().getKey(); } @Test @@ -70,23 +69,24 @@ void getAsBaseDocument() throws InterruptedException, ExecutionException { } @Test - void getAsVPack() throws InterruptedException, ExecutionException { - collection.getDocument(key, VPackSlice.class) + void getAsJsonNode() throws InterruptedException, ExecutionException { + collection.getDocument(key, JsonNode.class) .whenComplete((doc, ex) -> { assertThat(doc).isNotNull(); - assertThat(doc.get("foo").isString()).isEqualTo(true); - assertThat(doc.get("foo").getAsString()).isEqualTo("bar"); + assertThat(doc.get("foo").isTextual()).isEqualTo(true); + assertThat(doc.get("foo").asText()).isEqualTo("bar"); }) .get(); } @Test void getAsJson() throws InterruptedException, ExecutionException { - collection.getDocument(key, String.class) + collection.getDocument(key, RawJson.class) .whenComplete((doc, ex) -> { - assertThat(doc).isNotNull(); - assertThat(doc.contains("foo")).isEqualTo(true); - assertThat(doc.contains("bar")).isEqualTo(true); + assertThat(doc.getValue()) + .isNotNull() + .contains("foo") + .contains("bar"); }) .get(); } diff --git a/src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java b/driver/src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java similarity index 99% rename from src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java index d2df0678c..dacf1bd87 100644 --- a/src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java +++ b/driver/src/test/java/com/arangodb/async/example/document/ImportDocumentExampleTest.java @@ -25,7 +25,6 @@ import com.arangodb.model.DocumentImportOptions; import org.junit.jupiter.api.Test; - import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; diff --git a/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java b/driver/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java similarity index 77% rename from src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java index abaedab49..e55eda546 100644 --- a/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java +++ b/driver/src/test/java/com/arangodb/async/example/document/InsertDocumentExampleTest.java @@ -22,11 +22,12 @@ import com.arangodb.async.example.ExampleBase; import com.arangodb.entity.BaseDocument; -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.ValueType; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Test; - +import java.util.UUID; import java.util.concurrent.ExecutionException; import static org.assertj.core.api.Assertions.assertThat; @@ -46,7 +47,7 @@ void insertBean() throws ExecutionException, InterruptedException { @Test void insertBaseDocument() throws ExecutionException, InterruptedException { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("foo", "bar"); collection.insertDocument(value) .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) @@ -54,17 +55,18 @@ void insertBaseDocument() throws ExecutionException, InterruptedException { } @Test - void insertVPack() throws ExecutionException, InterruptedException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT).add("foo", "bar").close(); - collection.insertDocument(builder.slice()) + void insertJsonNode() throws ExecutionException, InterruptedException { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode node = mapper.createObjectNode(); + node.put("foo", "bar"); + collection.insertDocument(node) .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) .get(); } @Test void insertJson() throws ExecutionException, InterruptedException { - collection.insertDocument("{\"foo\":\"bar\"}") + collection.insertDocument(RawJson.of("{\"foo\":\"bar\"}")) .whenComplete((doc, ex) -> assertThat(doc.getKey()).isNotNull()) .get(); } diff --git a/src/test/java/com/arangodb/async/example/document/TestEntity.java b/driver/src/test/java/com/arangodb/async/example/document/TestEntity.java similarity index 95% rename from src/test/java/com/arangodb/async/example/document/TestEntity.java rename to driver/src/test/java/com/arangodb/async/example/document/TestEntity.java index d33126814..2ef89c19f 100644 --- a/src/test/java/com/arangodb/async/example/document/TestEntity.java +++ b/driver/src/test/java/com/arangodb/async/example/document/TestEntity.java @@ -23,7 +23,6 @@ /** * @author Mark Vollmary */ -@SuppressWarnings({"WeakerAccess", "unused"}) public class TestEntity { private String foo; diff --git a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java b/driver/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java similarity index 88% rename from src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java index d0e293a62..d21f78f02 100644 --- a/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/driver/src/test/java/com/arangodb/async/example/graph/AQLActorsAndMoviesExampleTest.java @@ -25,16 +25,19 @@ import com.arangodb.async.ArangoCursorAsync; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.BaseDocument; import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.entity.CollectionType; import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.mapping.ArangoJack; import com.arangodb.model.CollectionCreateOptions; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -43,10 +46,10 @@ /** * @author Mark Vollmary - * @see AQL Example Queries on an + * @see + * AQL Example Queries on an * Actors and Movies Database */ -@SuppressWarnings("JavaDoc") class AQLActorsAndMoviesExampleTest { private static final DbName TEST_DB = DbName.of("actors_movies_test_db"); @@ -55,7 +58,9 @@ class AQLActorsAndMoviesExampleTest { @BeforeAll static void setUp() throws InterruptedException, ExecutionException { - arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDBAsync.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); if (arangoDB.db(TEST_DB).exists().get()) { arangoDB.db(TEST_DB).drop().get(); } @@ -70,13 +75,13 @@ static void tearDown() throws InterruptedException, ExecutionException { arangoDB.shutdown(); } - private static DocumentCreateEntity saveMovie( + private static DocumentCreateEntity saveMovie( final ArangoCollectionAsync movies, final String key, final String title, final int released, final String tagline) throws InterruptedException, ExecutionException { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.setKey(key); value.addAttribute("title", title); value.addAttribute("released", released); @@ -84,12 +89,12 @@ private static DocumentCreateEntity saveMovie( return movies.insertDocument(value).get(); } - private static DocumentCreateEntity saveActor( + private static DocumentCreateEntity saveActor( final ArangoCollectionAsync actors, final String key, final String name, final int born) throws InterruptedException, ExecutionException { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.setKey(key); value.addAttribute("name", name); value.addAttribute("born", born); @@ -155,7 +160,8 @@ private static void createData() throws InterruptedException, ExecutionException saveActsIn(actsIn, al, theDevilsAdvocate, new String[]{"John Milton"}, 1997); final String AFewGoodMen = saveMovie(movies, "AFewGoodMen", "A Few Good Men", 1992, - "In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at nothing to keep his honor, and one will stop at nothing to find the truth.") + "In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at " + + "nothing to keep his honor, and one will stop at nothing to find the truth.") .getId(); final String tomC = saveActor(actors, "TomC", "Tom Cruise", 1962).getId(); final String jackN = saveActor(actors, "JackN", "Jack Nicholson", 1937).getId(); @@ -214,7 +220,8 @@ private static void createData() throws InterruptedException, ExecutionException saveActsIn(actsIn, jonathanL, jerryMaguire, new String[]{"Ray Boyd"}, 2000); final String standByMe = saveMovie(movies, "StandByMe", "Stand By Me", 1986, - "For some, it's the last real taste of innocence, and the first real taste of life. But for everyone, it's the time that memories are made of.") + "For some, it's the last real taste of innocence, and the first real taste of life. But for everyone," + + " it's the time that memories are made of.") .getId(); final String riverP = saveActor(actors, "RiverP", "River Phoenix", 1970).getId(); final String coreyF = saveActor(actors, "CoreyF", "Corey Feldman", 1971).getId(); @@ -274,7 +281,8 @@ private static void createData() throws InterruptedException, ExecutionException saveActsIn(actsIn, steveZ, youveGotMail, new String[]{"George Pappas"}, 1998); final String sleeplessInSeattle = saveMovie(movies, "SleeplessInSeattle", "Sleepless in Seattle", 1993, - "What if someone you never met, someone you never saw, someone you never knew was the only someone for you?") + "What if someone you never met, someone you never saw, someone you never knew was the only someone " + + "for you?") .getId(); final String ritaW = saveActor(actors, "RitaW", "Rita Wilson", 1956).getId(); final String billPull = saveActor(actors, "BillPull", "Bill Pullman", 1953).getId(); @@ -310,28 +318,34 @@ private static void createData() throws InterruptedException, ExecutionException * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#all-actors-who-acted-in-movie1-or-movie2">AQL * Example Queries on an Actors and Movies Database */ @Test void allActorsActsInMovie1or2() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "WITH actors, movies FOR x IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN x._id", + "WITH actors, movies FOR x IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: " + + "'global'} RETURN x._id", null, null, String.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("actors/Keanu", "actors/Hugo", "actors/Emil", "actors/Carrie", "actors/Laurence")).get(); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("actors/Keanu", "actors/Hugo", + "actors/Emil", "actors/Carrie", "actors/Laurence")).get(); } /** * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#all-actors-who-acted-in-movie1-or-movie2">AQL * Example Queries on an Actors and Movies Database */ @Test void allActorsActsInMovie1or2UnionDistinct() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "WITH actors, movies FOR x IN UNION_DISTINCT ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + "WITH actors, movies FOR x IN UNION_DISTINCT ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + + "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", null, null, String.class); f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( "actors/Emil", "actors/Hugo", "actors/Carrie", @@ -342,13 +356,16 @@ void allActorsActsInMovie1or2UnionDistinct() throws InterruptedException, Execut * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#all-actors-who-acted-in-both-movie1-and-movie2-">AQL * Example Queries on an Actors and Movies Database */ @Test void allActorsActsInMovie1and2() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + + "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", null, null, String.class); f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("actors/Keanu")).get(); } @@ -357,28 +374,34 @@ void allActorsActsInMovie1and2() throws InterruptedException, ExecutionException * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#all-common-movies-between-actor1-and-actor2-">AQL * Example Queries on an Actors and Movies Database */ @Test void allMoviesBetweenActor1andActor2() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'actors/Hugo' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'actors/Keanu' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'actors/Hugo' actsIn OPTIONS {bfs: true, " + + "uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'actors/Keanu' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", null, null, String.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("movies/TheMatrixRevolutions", "movies/TheMatrixReloaded", "movies/TheMatrix")).get(); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("movies/TheMatrixRevolutions", + "movies/TheMatrixReloaded", "movies/TheMatrix")).get(); } /** * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#all-actors-who-acted-in-3-or-more-movies-">AQL * Example Queries on an Actors and Movies Database */ @Test void allActorsWhoActedIn3orMoreMovies() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter FILTER counter >= 3 RETURN {actor: actor, movies: counter}", + "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter FILTER counter >= 3 RETURN {actor: " + + "actor, movies: counter}", null, null, Actor.class); f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( new Actor("actors/Carrie", 3), new Actor("actors/CubaG", 4), new Actor("actors/Hugo", 3), @@ -390,7 +413,8 @@ void allActorsWhoActedIn3orMoreMovies() throws InterruptedException, ExecutionEx * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#all-movies-where-exactly-6-actors-acted-in-">AQL * Example Queries on an Actors and Movies Database */ @Test @@ -398,14 +422,16 @@ void allMoviesWhereExactly6ActorsActedIn() throws InterruptedException, Executio final CompletableFuture> f = db.query( "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter FILTER counter == 6 RETURN movie", null, null, String.class); - f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("movies/SleeplessInSeattle", "movies/TopGun", "movies/YouveGotMail")).get(); + f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains("movies/SleeplessInSeattle", + "movies/TopGun", "movies/YouveGotMail")).get(); } /** * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#the-number-of-actors-by-movie-">AQL * Example Queries on an Actors and Movies Database */ @Test @@ -428,13 +454,15 @@ void theNumberOfActorsByMovie() throws InterruptedException, ExecutionException * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#the-number-of-movies-by-actor-">AQL * Example Queries on an Actors and Movies Database */ @Test void theNumberOfMoviesByActor() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: counter}", + "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: " + + "counter}", null, null, Actor.class); f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( new Actor("actors/Al", 1), new Actor("actors/AnnabellaS", 1), new Actor("actors/AnthonyE", 1), @@ -462,13 +490,15 @@ void theNumberOfMoviesByActor() throws InterruptedException, ExecutionException * @throws ExecutionException * @throws InterruptedException * @see AQL + * "https://www.arangodb.com/docs/stable/cookbook/graph-example-actors-and-movies + * .html#the-number-of-movies-acted-in-between-2005-and-2010-by-actor-">AQL * Example Queries on an Actors and Movies Database */ @Test void theNumberOfMoviesActedInBetween2005and2010byActor() throws InterruptedException, ExecutionException { final CompletableFuture> f = db.query( - "FOR x IN actsIn FILTER x.year >= 1990 && x.year <= 1995 COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: counter}", + "FOR x IN actsIn FILTER x.year >= 1990 && x.year <= 1995 COLLECT actor = x._from WITH COUNT INTO " + + "counter RETURN {actor: actor, movies: counter}", null, null, Actor.class); f.whenComplete((cursor, ex) -> assertThat(cursor.asListRemaining()).contains( new Actor("actors/BillPull", 1), new Actor("actors/ChristopherG", 1), @@ -479,16 +509,13 @@ void theNumberOfMoviesActedInBetween2005and2010byActor() throws InterruptedExcep new Actor("actors/TomC", 1), new Actor("actors/TomH", 2), new Actor("actors/VictorG", 1))).get(); } - @SuppressWarnings("WeakerAccess") public static class Actor { - private String actor; - private Integer movies; + private final String actor; + private final Integer movies; - public Actor() { - super(); - } - public Actor(final String actor, final Integer movies) { + @JsonCreator + public Actor(@JsonProperty("actor") final String actor, @JsonProperty("movies") final Integer movies) { super(); this.actor = actor; this.movies = movies; @@ -529,16 +556,12 @@ public boolean equals(final Object obj) { } - @SuppressWarnings("WeakerAccess") public static class Movie { - private String movie; - private Integer actors; - - public Movie() { - super(); - } + private final String movie; + private final Integer actors; - public Movie(final String movie, final Integer actors) { + @JsonCreator + public Movie(@JsonProperty("movie") final String movie, @JsonProperty("actors") final Integer actors) { super(); this.movie = movie; this.actors = actors; diff --git a/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java b/driver/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java similarity index 96% rename from src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java rename to driver/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java index 5496496f5..41a4e6edf 100644 --- a/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java +++ b/driver/src/test/java/com/arangodb/async/example/graph/BaseGraphTest.java @@ -23,9 +23,9 @@ import com.arangodb.DbName; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.EdgeDefinition; import com.arangodb.entity.VertexEntity; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -48,7 +48,9 @@ public abstract class BaseGraphTest { @BeforeAll static void init() throws InterruptedException, ExecutionException { if (arangoDB == null) { - arangoDB = new ArangoDBAsync.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDBAsync.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); } if (arangoDB.db(TEST_DB).exists().get()) { arangoDB.db(TEST_DB).drop().get(); diff --git a/src/test/java/com/arangodb/async/example/graph/Circle.java b/driver/src/test/java/com/arangodb/async/example/graph/Circle.java similarity index 91% rename from src/test/java/com/arangodb/async/example/graph/Circle.java rename to driver/src/test/java/com/arangodb/async/example/graph/Circle.java index 4eeea5ff5..e828aaeb3 100644 --- a/src/test/java/com/arangodb/async/example/graph/Circle.java +++ b/driver/src/test/java/com/arangodb/async/example/graph/Circle.java @@ -20,14 +20,13 @@ package com.arangodb.async.example.graph; -import com.arangodb.entity.Id; -import com.arangodb.entity.Key; -import com.arangodb.entity.Rev; +import com.arangodb.serde.jackson.Id; +import com.arangodb.serde.jackson.Key; +import com.arangodb.serde.jackson.Rev; /** * @author a-brandt */ -@SuppressWarnings({"WeakerAccess", "unused"}) class Circle { @Id diff --git a/src/test/java/com/arangodb/async/example/graph/CircleEdge.java b/driver/src/test/java/com/arangodb/async/example/graph/CircleEdge.java similarity index 96% rename from src/test/java/com/arangodb/async/example/graph/CircleEdge.java rename to driver/src/test/java/com/arangodb/async/example/graph/CircleEdge.java index b3b0ca62a..bfaa65210 100644 --- a/src/test/java/com/arangodb/async/example/graph/CircleEdge.java +++ b/driver/src/test/java/com/arangodb/async/example/graph/CircleEdge.java @@ -20,12 +20,11 @@ package com.arangodb.async.example.graph; -import com.arangodb.entity.*; +import com.arangodb.serde.jackson.*; /** * @author a-brandt */ -@SuppressWarnings({"WeakerAccess", "unused"}) class CircleEdge { @Id diff --git a/src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java b/driver/src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java similarity index 91% rename from src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java index f6b46cbd2..b3628f572 100644 --- a/src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java +++ b/driver/src/test/java/com/arangodb/async/example/graph/GraphTraversalsInAQLExampleTest.java @@ -23,7 +23,6 @@ import com.arangodb.async.ArangoCursorAsync; import org.junit.jupiter.api.Test; - import java.util.Collection; import java.util.concurrent.ExecutionException; @@ -68,26 +67,30 @@ void queryDepthTwo() throws InterruptedException, ExecutionException { @Test void queryWithFilter() throws InterruptedException, ExecutionException { - String queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G' RETURN v._key"; + String queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]" + + "._key != 'G' RETURN v._key"; ArangoCursorAsync cursor = db.query(queryString, null, null, String.class).get(); Collection result = cursor.asListRemaining(); assertThat(result).hasSize(5); assertThat(result).contains("B", "C", "D", "E", "F"); - queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label != 'right_foo' RETURN v._key"; + queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label != " + + "'right_foo' RETURN v._key"; cursor = db.query(queryString, null, null, String.class).get(); result = cursor.asListRemaining(); assertThat(result).hasSize(5); assertThat(result).contains("B", "C", "D", "E", "F"); - queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G' FILTER p.edges[1].label != 'left_blub' return v._key"; + queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + + " FILTER p.edges[1].label != 'left_blub' return v._key"; cursor = db.query(queryString, null, null, String.class).get(); result = cursor.asListRemaining(); assertThat(result).hasSize(3); assertThat(result).contains("B", "C", "D"); - queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G' AND p.edges[1].label != 'left_blub' return v._key"; + queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + + " AND p.edges[1].label != 'left_blub' return v._key"; cursor = db.query(queryString, null, null, String.class).get(); result = cursor.asListRemaining(); assertThat(result).hasSize(3); diff --git a/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java b/driver/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java similarity index 85% rename from src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java index 4d1edf9b4..515f8e13f 100644 --- a/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java +++ b/driver/src/test/java/com/arangodb/async/example/graph/ShortestPathInAQLExampleTest.java @@ -23,7 +23,6 @@ import com.arangodb.async.ArangoCursorAsync; import org.junit.jupiter.api.Test; - import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -42,13 +41,15 @@ class ShortestPathInAQLExampleTest extends BaseGraphTest { @Test void queryShortestPathFromAToD() throws InterruptedException, ExecutionException { - String queryString = "FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' GRAPH 'traversalGraph' RETURN {'vertex': v._key, 'edge': e._key}"; + String queryString = "FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' GRAPH 'traversalGraph' " + + "RETURN {'vertex': v._key, 'edge': e._key}"; ArangoCursorAsync cursor = db.query(queryString, null, null, Pair.class).get(); final Collection collection = toVertexCollection(cursor); assertThat(collection).hasSize(4); assertThat(collection).contains("A", "B", "C", "D"); - queryString = "WITH circles FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' edges RETURN {'vertex': v._key, 'edge': e._key}"; + queryString = "WITH circles FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' edges RETURN " + + "{'vertex': v._key, 'edge': e._key}"; db.query(queryString, null, null, Pair.class).get(); assertThat(collection).hasSize(4); assertThat(collection).contains("A", "B", "C", "D"); @@ -56,13 +57,15 @@ void queryShortestPathFromAToD() throws InterruptedException, ExecutionException @Test void queryShortestPathByFilter() throws InterruptedException, ExecutionException { - String queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN OUTBOUND SHORTEST_PATH a TO d GRAPH 'traversalGraph' RETURN {'vertex':v._key, 'edge':e._key}"; + String queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN" + + " OUTBOUND SHORTEST_PATH a TO d GRAPH 'traversalGraph' RETURN {'vertex':v._key, 'edge':e._key}"; ArangoCursorAsync cursor = db.query(queryString, null, null, Pair.class).get(); final Collection collection = toVertexCollection(cursor); assertThat(collection).hasSize(4); assertThat(collection).contains("A", "B", "C", "D"); - queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN OUTBOUND SHORTEST_PATH a TO d edges RETURN {'vertex': v._key, 'edge': e._key}"; + queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN " + + "OUTBOUND SHORTEST_PATH a TO d edges RETURN {'vertex': v._key, 'edge': e._key}"; db.query(queryString, null, null, Pair.class).get(); assertThat(collection).hasSize(4); assertThat(collection).contains("A", "B", "C", "D"); @@ -77,7 +80,6 @@ private Collection toVertexCollection(final ArangoCursorAsync curs return result; } - @SuppressWarnings({"WeakerAccess", "unused"}) public static class Pair { private String vertex; diff --git a/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java b/driver/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java similarity index 92% rename from src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java rename to driver/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java index 68d19f0d6..c90175310 100644 --- a/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java +++ b/driver/src/test/java/com/arangodb/async/example/ssl/SslExampleTest.java @@ -22,11 +22,10 @@ import com.arangodb.async.ArangoDBAsync; import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.mapping.ArangoJack; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; - import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; @@ -38,6 +37,7 @@ /** * @author Mark Vollmary */ +@Tag("ssl") @EnabledIfSystemProperty(named = "SslTest", matches = "true") class SslExampleTest { @@ -68,8 +68,10 @@ void connect() throws Exception { sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() - .loadProperties(SslExampleTest.class.getResourceAsStream("/arangodb-ssl.properties")).useSsl(true) - .sslContext(sc).serializer(new ArangoJack()).build(); + .host("localhost", 8529) + .password("test") + .useSsl(true) + .sslContext(sc).build(); final ArangoDBVersion version = arangoDB.getVersion().get(); assertThat(version).isNotNull(); } diff --git a/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java b/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java similarity index 56% rename from src/test/java/com/arangodb/async/serde/CustomSerdeTest.java rename to driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java index 90022a845..6756ef847 100644 --- a/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java +++ b/driver/src/test/java/com/arangodb/async/serde/CustomSerdeTest.java @@ -25,17 +25,19 @@ import com.arangodb.async.ArangoCollectionAsync; import com.arangodb.async.ArangoDBAsync; import com.arangodb.async.ArangoDatabaseAsync; -import com.arangodb.entity.BaseDocument; -import com.arangodb.mapping.ArangoJack; +import com.arangodb.config.ConfigUtils; import com.arangodb.model.DocumentCreateOptions; +import com.arangodb.ContentType; +import com.arangodb.serde.jackson.JacksonSerde; +import com.arangodb.serde.jackson.JacksonSerdeProvider; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - import java.math.BigInteger; import java.util.Collections; import java.util.HashMap; +import java.util.Map; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -56,12 +58,14 @@ class CustomSerdeTest { @BeforeEach void init() throws ExecutionException, InterruptedException { - ArangoJack arangoJack = new ArangoJack(); - arangoJack.configure((mapper) -> { + JacksonSerde serde = new JacksonSerdeProvider().of(ContentType.VPACK); + serde.configure((mapper) -> { mapper.configure(WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true); mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); }); - ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().serializer(arangoJack).build(); + ArangoDBAsync arangoDB = new ArangoDBAsync.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .serde(serde).build(); DbName TEST_DB = DbName.of("custom-serde-test"); db = arangoDB.db(TEST_DB); @@ -84,86 +88,90 @@ void shutdown() throws ExecutionException, InterruptedException { void aqlSerialization() throws ExecutionException, InterruptedException { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); HashMap params = new HashMap<>(); params.put("doc", doc); params.put("@collection", COLLECTION_NAME); - BaseDocument result = db.query( + Map result = db.query( "INSERT @doc INTO @@collection RETURN NEW", params, - BaseDocument.class + Map.class ).get().next(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test void aqlDeserialization() throws ExecutionException, InterruptedException { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); - collection.insertDocument(doc, null).get(); + collection.insertDocument(doc).get(); - final BaseDocument result = db.query( + final Map result = db.query( "RETURN DOCUMENT(@docId)", Collections.singletonMap("docId", COLLECTION_NAME + "/" + key), - BaseDocument.class + Map.class ).get().next(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test void insertDocument() throws ExecutionException, InterruptedException { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); - BaseDocument result = collection.insertDocument( + Map result = collection.insertDocument( doc, new DocumentCreateOptions().returnNew(true) ).get().getNew(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test void getDocument() throws ExecutionException, InterruptedException { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); - collection.insertDocument(doc, null).get(); + collection.insertDocument(doc).get(); - final BaseDocument result = db.collection(COLLECTION_NAME).getDocument( + final Map result = db.collection(COLLECTION_NAME).getDocument( key, - BaseDocument.class, + Map.class, null).get(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } } diff --git a/driver/src/test/java/com/arangodb/config/ConfigUtils.java b/driver/src/test/java/com/arangodb/config/ConfigUtils.java new file mode 100644 index 000000000..0b7dca677 --- /dev/null +++ b/driver/src/test/java/com/arangodb/config/ConfigUtils.java @@ -0,0 +1,17 @@ +package com.arangodb.config; + +public class ConfigUtils { + + public static ArangoConfigProperties loadConfig() { + return ArangoConfigProperties.fromFile(); + } + + public static ArangoConfigProperties loadConfig(final String location) { + return ArangoConfigProperties.fromFile(location); + } + + public static ArangoConfigProperties loadConfig(final String location, final String prefix) { + return ArangoConfigProperties.fromFile(location, prefix); + } + +} diff --git a/src/test/java/com/arangodb/example/ExampleBase.java b/driver/src/test/java/com/arangodb/example/ExampleBase.java similarity index 78% rename from src/test/java/com/arangodb/example/ExampleBase.java rename to driver/src/test/java/com/arangodb/example/ExampleBase.java index c378c789c..01399b1cb 100644 --- a/src/test/java/com/arangodb/example/ExampleBase.java +++ b/driver/src/test/java/com/arangodb/example/ExampleBase.java @@ -1,59 +1,62 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example; - -import com.arangodb.ArangoCollection; -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDatabase; -import com.arangodb.mapping.ArangoJack; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; - -/** - * @author Mark Vollmary - */ -public class ExampleBase { - - private static final String DB_NAME = "json_example_db"; - protected static final String COLLECTION_NAME = "json_example_collection"; - - private static ArangoDB arangoDB; - protected static ArangoDatabase db; - protected static ArangoCollection collection; - - @BeforeAll - static void setUp() { - arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); - if (arangoDB.db(DB_NAME).exists()) - arangoDB.db(DB_NAME).drop(); - arangoDB.createDatabase(DB_NAME); - db = arangoDB.db(DB_NAME); - db.createCollection(COLLECTION_NAME); - collection = db.collection(COLLECTION_NAME); - } - - @AfterAll - static void tearDown() { - db.drop(); - arangoDB.shutdown(); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example; + +import com.arangodb.ArangoCollection; +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDatabase; +import com.arangodb.DbName; +import com.arangodb.config.ConfigUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; + +/** + * @author Mark Vollmary + */ +public class ExampleBase { + + protected static final String COLLECTION_NAME = "json_example_collection"; + private static final String DB_NAME = "json_example_db"; + protected static ArangoDatabase db; + protected static ArangoCollection collection; + private static ArangoDB arangoDB; + + @BeforeAll + static void setUp() { + arangoDB = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); + DbName dbName = DbName.of(DB_NAME); + if (arangoDB.db(dbName).exists()) + arangoDB.db(dbName).drop(); + arangoDB.createDatabase(dbName); + db = arangoDB.db(dbName); + db.createCollection(COLLECTION_NAME); + collection = db.collection(COLLECTION_NAME); + } + + @AfterAll + static void tearDown() { + db.drop(); + arangoDB.shutdown(); + } + +} diff --git a/src/test/java/com/arangodb/example/FirstProject.java b/driver/src/test/java/com/arangodb/example/FirstProject.java similarity index 82% rename from src/test/java/com/arangodb/example/FirstProject.java rename to driver/src/test/java/com/arangodb/example/FirstProject.java index db14e3741..454bfabc7 100644 --- a/src/test/java/com/arangodb/example/FirstProject.java +++ b/driver/src/test/java/com/arangodb/example/FirstProject.java @@ -1,137 +1,134 @@ -package com.arangodb.example; - -import com.arangodb.ArangoCollection; -import com.arangodb.ArangoCursor; -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDBException; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.CollectionEntity; -import com.arangodb.mapping.ArangoJack; -import com.arangodb.util.MapBuilder; -import com.arangodb.velocypack.VPackSlice; - -import java.util.Map; - -public class FirstProject { - - public static void main(final String[] args) { - final ArangoDB arangoDB = new ArangoDB.Builder().user("root").serializer(new ArangoJack()).build(); - - // create database - final String dbName = "mydb"; - try { - arangoDB.createDatabase(dbName); - System.out.println("Database created: " + dbName); - } catch (final ArangoDBException e) { - System.err.println("Failed to create database: " + dbName + "; " + e.getMessage()); - } - - // create collection - final String collectionName = "firstCollection"; - try { - final CollectionEntity myArangoCollection = arangoDB.db(dbName).createCollection(collectionName); - System.out.println("Collection created: " + myArangoCollection.getName()); - } catch (final ArangoDBException e) { - System.err.println("Failed to create collection: " + collectionName + "; " + e.getMessage()); - } - - // creating a document - final BaseDocument myObject = new BaseDocument(); - myObject.setKey("myKey"); - myObject.addAttribute("a", "Foo"); - myObject.addAttribute("b", 42); - try { - arangoDB.db(dbName).collection(collectionName).insertDocument(myObject); - System.out.println("Document created"); - } catch (final ArangoDBException e) { - System.err.println("Failed to create document. " + e.getMessage()); - } - - // read a document - try { - final BaseDocument myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", - BaseDocument.class); - System.out.println("Key: " + myDocument.getKey()); - System.out.println("Attribute a: " + myDocument.getAttribute("a")); - System.out.println("Attribute b: " + myDocument.getAttribute("b")); - } catch (final ArangoDBException e) { - System.err.println("Failed to get document: myKey; " + e.getMessage()); - } - - // read a document as VPack - try { - final VPackSlice myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", - VPackSlice.class); - System.out.println("Key: " + myDocument.get("_key").getAsString()); - System.out.println("Attribute a: " + myDocument.get("a").getAsString()); - System.out.println("Attribute b: " + myDocument.get("b").getAsInt()); - } catch (final ArangoDBException e) { - System.err.println("Failed to get document: myKey; " + e.getMessage()); - } - - // update a document - myObject.addAttribute("c", "Bar"); - try { - arangoDB.db(dbName).collection(collectionName).updateDocument("myKey", myObject); - } catch (final ArangoDBException e) { - System.err.println("Failed to update document. " + e.getMessage()); - } - - // read the document again - try { - final BaseDocument myUpdatedDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", - BaseDocument.class); - System.out.println("Key: " + myUpdatedDocument.getKey()); - System.out.println("Attribute a: " + myUpdatedDocument.getAttribute("a")); - System.out.println("Attribute b: " + myUpdatedDocument.getAttribute("b")); - System.out.println("Attribute c: " + myUpdatedDocument.getAttribute("c")); - } catch (final ArangoDBException e) { - System.err.println("Failed to get document: myKey; " + e.getMessage()); - } - - // delete a document - try { - arangoDB.db(dbName).collection(collectionName).deleteDocument("myKey"); - } catch (final ArangoDBException e) { - System.err.println("Failed to delete document. " + e.getMessage()); - } - - // create some documents for the next step - final ArangoCollection collection = arangoDB.db(dbName).collection(collectionName); - for (int i = 0; i < 10; i++) { - final BaseDocument value = new BaseDocument(); - value.setKey(String.valueOf(i)); - value.addAttribute("name", "Homer"); - collection.insertDocument(value); - } - - // execute AQL queries - try { - final String query = "FOR t IN firstCollection FILTER t.name == @name RETURN t"; - final Map bindVars = new MapBuilder().put("name", "Homer").get(); - final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, - BaseDocument.class); - for (; cursor.hasNext(); ) { - System.out.println("Key: " + cursor.next().getKey()); - } - } catch (final ArangoDBException e) { - System.err.println("Failed to execute query. " + e.getMessage()); - } - - // delete a document with AQL - try { - final String query = "FOR t IN firstCollection FILTER t.name == @name " - + "REMOVE t IN firstCollection LET removed = OLD RETURN removed"; - final Map bindVars = new MapBuilder().put("name", "Homer").get(); - final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, - BaseDocument.class); - for (; cursor.hasNext(); ) { - System.out.println("Removed document " + cursor.next().getKey()); - } - } catch (final ArangoDBException e) { - System.err.println("Failed to execute query. " + e.getMessage()); - } - - } - -} +package com.arangodb.example; + +import com.arangodb.*; +import com.arangodb.entity.BaseDocument; +import com.arangodb.entity.CollectionEntity; +import com.fasterxml.jackson.databind.JsonNode; + +import java.util.Collections; +import java.util.Map; +import java.util.UUID; + +public class FirstProject { + + public static void main(final String[] args) { + final ArangoDB arangoDB = new ArangoDB.Builder().user("root").build(); + + // create database + final DbName dbName = DbName.of("mydb"); + try { + arangoDB.createDatabase(dbName); + System.out.println("Database created: " + dbName); + } catch (final ArangoDBException e) { + System.err.println("Failed to create database: " + dbName + "; " + e.getMessage()); + } + + // create collection + final String collectionName = "firstCollection"; + try { + final CollectionEntity myArangoCollection = arangoDB.db(dbName).createCollection(collectionName); + System.out.println("Collection created: " + myArangoCollection.getName()); + } catch (final ArangoDBException e) { + System.err.println("Failed to create collection: " + collectionName + "; " + e.getMessage()); + } + + // creating a document + final BaseDocument myObject = new BaseDocument(UUID.randomUUID().toString()); + myObject.setKey("myKey"); + myObject.addAttribute("a", "Foo"); + myObject.addAttribute("b", 42); + try { + arangoDB.db(dbName).collection(collectionName).insertDocument(myObject); + System.out.println("Document created"); + } catch (final ArangoDBException e) { + System.err.println("Failed to create document. " + e.getMessage()); + } + + // read a document + try { + final BaseDocument myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", + BaseDocument.class); + System.out.println("Key: " + myDocument.getKey()); + System.out.println("Attribute a: " + myDocument.getAttribute("a")); + System.out.println("Attribute b: " + myDocument.getAttribute("b")); + } catch (final ArangoDBException e) { + System.err.println("Failed to get document: myKey; " + e.getMessage()); + } + + // read a document as JsonNode + try { + final JsonNode myDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", + JsonNode.class); + System.out.println("Key: " + myDocument.get("_key").textValue()); + System.out.println("Attribute a: " + myDocument.get("a").textValue()); + System.out.println("Attribute b: " + myDocument.get("b").textValue()); + } catch (final ArangoDBException e) { + System.err.println("Failed to get document: myKey; " + e.getMessage()); + } + + // update a document + myObject.addAttribute("c", "Bar"); + try { + arangoDB.db(dbName).collection(collectionName).updateDocument("myKey", myObject); + } catch (final ArangoDBException e) { + System.err.println("Failed to update document. " + e.getMessage()); + } + + // read the document again + try { + final BaseDocument myUpdatedDocument = arangoDB.db(dbName).collection(collectionName).getDocument("myKey", + BaseDocument.class); + System.out.println("Key: " + myUpdatedDocument.getKey()); + System.out.println("Attribute a: " + myUpdatedDocument.getAttribute("a")); + System.out.println("Attribute b: " + myUpdatedDocument.getAttribute("b")); + System.out.println("Attribute c: " + myUpdatedDocument.getAttribute("c")); + } catch (final ArangoDBException e) { + System.err.println("Failed to get document: myKey; " + e.getMessage()); + } + + // delete a document + try { + arangoDB.db(dbName).collection(collectionName).deleteDocument("myKey"); + } catch (final ArangoDBException e) { + System.err.println("Failed to delete document. " + e.getMessage()); + } + + // create some documents for the next step + final ArangoCollection collection = arangoDB.db(dbName).collection(collectionName); + for (int i = 0; i < 10; i++) { + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); + value.setKey(String.valueOf(i)); + value.addAttribute("name", "Homer"); + collection.insertDocument(value); + } + + // execute AQL queries + try { + final String query = "FOR t IN firstCollection FILTER t.name == @name RETURN t"; + final Map bindVars = Collections.singletonMap("name", "Homer"); + final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, + BaseDocument.class); + while (cursor.hasNext()) { + System.out.println("Key: " + cursor.next().getKey()); + } + } catch (final ArangoDBException e) { + System.err.println("Failed to execute query. " + e.getMessage()); + } + + // delete a document with AQL + try { + final String query = "FOR t IN firstCollection FILTER t.name == @name " + + "REMOVE t IN firstCollection LET removed = OLD RETURN removed"; + final Map bindVars = Collections.singletonMap("name", "Homer"); + final ArangoCursor cursor = arangoDB.db(dbName).query(query, bindVars, null, + BaseDocument.class); + while (cursor.hasNext()) { + System.out.println("Removed document " + cursor.next().getKey()); + } + } catch (final ArangoDBException e) { + System.err.println("Failed to execute query. " + e.getMessage()); + } + + } + +} diff --git a/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java b/driver/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java similarity index 74% rename from src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java rename to driver/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java index 1a46d3a15..69d213ac4 100644 --- a/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java +++ b/driver/src/test/java/com/arangodb/example/document/AqlQueryWithSpecialReturnTypesExampleTest.java @@ -23,13 +23,15 @@ import com.arangodb.ArangoCursor; import com.arangodb.entity.BaseDocument; import com.arangodb.example.ExampleBase; -import com.arangodb.util.MapBuilder; -import com.arangodb.velocypack.VPackSlice; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; @@ -44,13 +46,9 @@ static void before() { createExamples(); } - enum Gender { - MALE, FEMALE - } - private static void createExamples() { for (int i = 0; i < 100; i++) { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("name", "TestUser" + i); value.addAttribute("gender", (i % 2) == 0 ? Gender.MALE : Gender.FEMALE); value.addAttribute("age", i + 10); @@ -59,43 +57,42 @@ private static void createExamples() { } @Test - void aqlWithLimitQueryAsVPackObject() { + void aqlWithLimitQueryAsJsonObject() { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); - final ArangoCursor cursor = db.query(query, bindVars, null, VPackSlice.class); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); + final ArangoCursor cursor = db.query(query, bindVars, null, ObjectNode.class); assertThat((Object) cursor).isNotNull(); while (cursor.hasNext()) { - final VPackSlice vpack = cursor.next(); - assertThat(vpack.get("name").getAsString()) + final ObjectNode node = cursor.next(); + assertThat(node.get("name").asText()) .isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); - assertThat(vpack.get("gender").getAsString()).isEqualTo(Gender.FEMALE.name()); - assertThat(vpack.get("age").getAsInt()).isIn(21, 23, 25, 27, 29); + assertThat(node.get("gender").asText()).isEqualTo(Gender.FEMALE.name()); + assertThat(node.get("age").asInt()).isIn(21, 23, 25, 27, 29); } } @Test - void aqlWithLimitQueryAsVPackArray() { + void aqlWithLimitQueryAsJsonArray() { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); - final ArangoCursor cursor = db.query(query, bindVars, null, VPackSlice.class); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); + final ArangoCursor cursor = db.query(query, bindVars, null, ArrayNode.class); assertThat((Object) cursor).isNotNull(); while (cursor.hasNext()) { - final VPackSlice vpack = cursor.next(); - assertThat(vpack.get(0).getAsString()) + final ArrayNode arrNode = cursor.next(); + assertThat(arrNode.get(0).asText()) .isIn("TestUser11", "TestUser13", "TestUser15", "TestUser17", "TestUser19"); - assertThat(vpack.get(1).getAsString()).isEqualTo(Gender.FEMALE.name()); - assertThat(vpack.get(2).getAsInt()).isIn(21, 23, 25, 27, 29); + assertThat(arrNode.get(1).asText()).isEqualTo(Gender.FEMALE.name()); + assertThat(arrNode.get(2).asInt()).isIn(21, 23, 25, 27, 29); } } @Test - @SuppressWarnings("rawtypes") void aqlWithLimitQueryAsMap() { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN t"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); final ArangoCursor cursor = db.query(query, bindVars, null, Map.class); assertThat((Object) cursor).isNotNull(); while (cursor.hasNext()) { @@ -111,11 +108,10 @@ void aqlWithLimitQueryAsMap() { } @Test - @SuppressWarnings("rawtypes") void aqlWithLimitQueryAsList() { final String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.age >= 20 && t.age < 30 && t.gender == @gender RETURN [t.name, t.gender, t.age]"; - final Map bindVars = new MapBuilder().put("gender", Gender.FEMALE).get(); + final Map bindVars = Collections.singletonMap("gender", Gender.FEMALE); final ArangoCursor cursor = db.query(query, bindVars, null, List.class); assertThat((Object) cursor).isNotNull(); while (cursor.hasNext()) { @@ -129,4 +125,8 @@ void aqlWithLimitQueryAsList() { assertThat(Long.valueOf(String.valueOf(list.get(2)))).isIn(21L, 23L, 25L, 27L, 29L); } } + + enum Gender { + MALE, FEMALE + } } diff --git a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java b/driver/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java similarity index 67% rename from src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java rename to driver/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java index 10df2972e..dc7318139 100644 --- a/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java +++ b/driver/src/test/java/com/arangodb/example/document/GetDocumentExampleTest.java @@ -21,13 +21,15 @@ package com.arangodb.example.document; import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.DocumentCreateEntity; import com.arangodb.example.ExampleBase; -import com.arangodb.velocypack.VPackSlice; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import java.util.Map; +import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; @@ -41,10 +43,9 @@ class GetDocumentExampleTest extends ExampleBase { @BeforeAll static void before() { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("foo", "bar"); - final DocumentCreateEntity doc = collection.insertDocument(value); - key = doc.getKey(); + key = collection.insertDocument(value).getKey(); } @Test @@ -62,7 +63,6 @@ void getAsBaseDocument() { assertThat(String.valueOf(doc.getAttribute("foo"))).isEqualTo("bar"); } - @SuppressWarnings("unchecked") @Test void getAsMap() { final Map doc = collection.getDocument(key, Map.class); @@ -72,19 +72,27 @@ void getAsMap() { } @Test - void getAsVPack() { - final VPackSlice doc = collection.getDocument(key, VPackSlice.class); + void getAsJsonNode() { + final JsonNode doc = collection.getDocument(key, JsonNode.class); assertThat(doc).isNotNull(); - assertThat(doc.get("foo").isString()).isTrue(); - assertThat(doc.get("foo").getAsString()).isEqualTo("bar"); + assertThat(doc.get("foo").isTextual()).isTrue(); + assertThat(doc.get("foo").asText()).isEqualTo("bar"); } @Test void getAsJson() { - final String doc = collection.getDocument(key, String.class); - assertThat(doc).isNotNull(); - assertThat(doc).contains("foo"); - assertThat(doc).contains("bar"); + final RawJson doc = collection.getDocument(key, RawJson.class); + assertThat(doc.getValue()).isNotNull() + .contains("foo") + .contains("bar"); + } + + @Test + void getAsBytes() { + final RawBytes doc = collection.getDocument(key, RawBytes.class); + assertThat(doc.getValue()).isNotNull(); + Map mapDoc = collection.getSerde().deserializeUserData(doc.getValue(), Map.class); + assertThat(mapDoc).containsEntry("foo", "bar"); } } diff --git a/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java b/driver/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java similarity index 65% rename from src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java rename to driver/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java index 016d7f2c3..000b6ddd6 100644 --- a/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java +++ b/driver/src/test/java/com/arangodb/example/document/InsertDocumentExampleTest.java @@ -23,11 +23,13 @@ import com.arangodb.entity.BaseDocument; import com.arangodb.entity.DocumentCreateEntity; import com.arangodb.example.ExampleBase; -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.ValueType; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Test; +import java.util.UUID; + import static org.assertj.core.api.Assertions.assertThat; @@ -38,29 +40,30 @@ class InsertDocumentExampleTest extends ExampleBase { @Test void insertBean() { - final DocumentCreateEntity doc = collection.insertDocument(new TestEntity("bar")); + final DocumentCreateEntity doc = collection.insertDocument(new TestEntity("bar")); assertThat(doc.getKey()).isNotNull(); } @Test void insertBaseDocument() { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.addAttribute("foo", "bar"); - final DocumentCreateEntity doc = collection.insertDocument(value); + final DocumentCreateEntity doc = collection.insertDocument(value); assertThat(doc.getKey()).isNotNull(); } @Test - void insertVPack() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT).add("foo", "bar").close(); - final DocumentCreateEntity doc = collection.insertDocument(builder.slice()); + void insertJsonNode() { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode node = mapper.createObjectNode(); + node.put("foo", "bar"); + final DocumentCreateEntity doc = collection.insertDocument(node); assertThat(doc.getKey()).isNotNull(); } @Test void insertJson() { - final DocumentCreateEntity doc = collection.insertDocument("{\"foo\":\"bar\"}"); + final DocumentCreateEntity doc = collection.insertDocument(RawJson.of("{\"foo\":\"bar\"}")); assertThat(doc.getKey()).isNotNull(); } diff --git a/src/test/java/com/arangodb/example/document/TestEntity.java b/driver/src/test/java/com/arangodb/example/document/TestEntity.java similarity index 92% rename from src/test/java/com/arangodb/example/document/TestEntity.java rename to driver/src/test/java/com/arangodb/example/document/TestEntity.java index a5c9aaf31..8a59c2b60 100644 --- a/src/test/java/com/arangodb/example/document/TestEntity.java +++ b/driver/src/test/java/com/arangodb/example/document/TestEntity.java @@ -1,48 +1,47 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.document; - -/** - * @author Mark Vollmary - */ -@SuppressWarnings({"WeakerAccess", "unused"}) -public class TestEntity { - - private String foo; - - public TestEntity() { - super(); - } - - public TestEntity(final String foo) { - super(); - this.foo = foo; - } - - public String getFoo() { - return foo; - } - - public void setFoo(final String foo) { - this.foo = foo; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.document; + +/** + * @author Mark Vollmary + */ +public class TestEntity { + + private String foo; + + public TestEntity() { + super(); + } + + public TestEntity(final String foo) { + super(); + this.foo = foo; + } + + public String getFoo() { + return foo; + } + + public void setFoo(final String foo) { + this.foo = foo; + } + +} diff --git a/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java b/driver/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java similarity index 88% rename from src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java rename to driver/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java index f5283c5aa..c23b4097d 100644 --- a/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java +++ b/driver/src/test/java/com/arangodb/example/graph/AQLActorsAndMoviesExampleTest.java @@ -21,22 +21,27 @@ package com.arangodb.example.graph; import com.arangodb.*; +import com.arangodb.config.ConfigUtils; import com.arangodb.entity.BaseDocument; import com.arangodb.entity.BaseEdgeDocument; import com.arangodb.entity.CollectionType; import com.arangodb.entity.DocumentCreateEntity; -import com.arangodb.mapping.ArangoJack; import com.arangodb.model.CollectionCreateOptions; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import java.util.UUID; + import static org.assertj.core.api.Assertions.assertThat; /** * @author Mark Vollmary - * @see AQL Example Queries on an + * @see + * AQL Example Queries on an * Actors and Movies Database */ class AQLActorsAndMoviesExampleTest { @@ -47,7 +52,9 @@ class AQLActorsAndMoviesExampleTest { @BeforeAll static void setUp() { - arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); + arangoDB = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); if (arangoDB.db(TEST_DB).exists()) arangoDB.db(TEST_DB).drop(); arangoDB.createDatabase(TEST_DB); @@ -61,268 +68,13 @@ static void tearDown() { arangoDB.shutdown(); } - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsActsInMovie1or2() { - final ArangoCursor cursor = db.query( - "WITH actors, movies FOR x IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN x._id", - null, null, String.class); - assertThat(cursor.asListRemaining()) - .contains("actors/Keanu", "actors/Hugo", "actors/Emil", "actors/Carrie", "actors/Laurence"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsActsInMovie1or2UnionDistinct() { - final ArangoCursor cursor = db.query( - "WITH actors, movies FOR x IN UNION_DISTINCT ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", - null, null, String.class); - assertThat(cursor.asListRemaining()).contains("actors/Emil", "actors/Hugo", "actors/Carrie", "actors/Laurence", - "actors/Keanu", "actors/Al", "actors/Charlize"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsActsInMovie1and2() { - final ArangoCursor cursor = db.query( - "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", - null, null, String.class); - assertThat(cursor.asListRemaining()).contains("actors/Keanu"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allMoviesBetweenActor1andActor2() { - final ArangoCursor cursor = db.query( - "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'actors/Hugo' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'actors/Keanu' actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", - null, null, String.class); - assertThat(cursor.asListRemaining()) - .contains("movies/TheMatrixRevolutions", "movies/TheMatrixReloaded", "movies/TheMatrix"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allActorsWhoActedIn3orMoreMovies() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter FILTER counter >= 3 RETURN {actor: actor, movies: counter}", - null, null, Actor.class); - assertThat(cursor.asListRemaining()) - .contains(new Actor("actors/Carrie", 3), new Actor("actors/CubaG", 4), new Actor("actors/Hugo", 3), - new Actor("actors/Keanu", 4), new Actor("actors/Laurence", 3), new Actor("actors/MegR", 5), - new Actor("actors/TomC", 3), new Actor("actors/TomH", 3)); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void allMoviesWhereExactly6ActorsActedIn() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter FILTER counter == 6 RETURN movie", null, - null, String.class); - assertThat(cursor.asListRemaining()) - .contains("movies/SleeplessInSeattle", "movies/TopGun", "movies/YouveGotMail"); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void theNumberOfActorsByMovie() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter RETURN {movie: movie, actors: counter}", - null, null, Movie.class); - assertThat(cursor.asListRemaining()) - .contains(new Movie("movies/AFewGoodMen", 11), new Movie("movies/AsGoodAsItGets", 4), - new Movie("movies/JerryMaguire", 9), new Movie("movies/JoeVersustheVolcano", 3), - new Movie("movies/SleeplessInSeattle", 6), new Movie("movies/SnowFallingonCedars", 4), - new Movie("movies/StandByMe", 7), new Movie("movies/TheDevilsAdvocate", 3), - new Movie("movies/TheMatrix", 5), new Movie("movies/TheMatrixReloaded", 4), - new Movie("movies/TheMatrixRevolutions", 4), new Movie("movies/TopGun", 6), - new Movie("movies/WhatDreamsMayCome", 5), new Movie("movies/WhenHarryMetSally", 4), - new Movie("movies/YouveGotMail", 6)); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void theNumberOfMoviesByActor() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: counter}", - null, null, Actor.class); - assertThat(cursor.asListRemaining()) - .contains(new Actor("actors/Al", 1), new Actor("actors/AnnabellaS", 1), new Actor("actors/AnthonyE", 1), - new Actor("actors/BillPull", 1), new Actor("actors/BillyC", 1), new Actor("actors/BonnieH", 1), - new Actor("actors/BrunoK", 1), new Actor("actors/Carrie", 3), new Actor("actors/CarrieF", 1), - new Actor("actors/Charlize", 1), new Actor("actors/ChristopherG", 1), new Actor("actors/CoreyF", 1), - new Actor("actors/CubaG", 4), new Actor("actors/DaveC", 1), new Actor("actors/DemiM", 1), - new Actor("actors/Emil", 1), new Actor("actors/EthanH", 1), new Actor("actors/GregK", 2), - new Actor("actors/HelenH", 1), new Actor("actors/Hugo", 3), new Actor("actors/JackN", 2), - new Actor("actors/JamesC", 1), new Actor("actors/JamesM", 1), new Actor("actors/JayM", 1), - new Actor("actors/JerryO", 2), new Actor("actors/JohnC", 1), new Actor("actors/JonathanL", 1), - new Actor("actors/JTW", 1), new Actor("actors/Keanu", 4), new Actor("actors/KellyM", 1), - new Actor("actors/KellyP", 1), new Actor("actors/KevinB", 1), new Actor("actors/KevinP", 1), - new Actor("actors/KieferS", 2), new Actor("actors/Laurence", 3), new Actor("actors/MarshallB", 1), - new Actor("actors/MaxS", 2), new Actor("actors/MegR", 5), new Actor("actors/Nathan", 1), - new Actor("actors/NoahW", 1), new Actor("actors/ParkerP", 1), new Actor("actors/ReginaK", 1), - new Actor("actors/ReneeZ", 1), new Actor("actors/RickY", 1), new Actor("actors/RitaW", 1), - new Actor("actors/RiverP", 1), new Actor("actors/Robin", 1), new Actor("actors/RosieO", 1), - new Actor("actors/SteveZ", 1), new Actor("actors/TomC", 3), new Actor("actors/TomH", 3), - new Actor("actors/TomS", 1), new Actor("actors/ValK", 1), new Actor("actors/VictorG", 1), - new Actor("actors/WernerH", 1), new Actor("actors/WilW", 1)); - } - - /** - * @see AQL - * Example Queries on an Actors and Movies Database - */ - @Test - void theNumberOfMoviesActedInBetween2005and2010byActor() { - final ArangoCursor cursor = db.query( - "FOR x IN actsIn FILTER x.year >= 1990 && x.year <= 1995 COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: counter}", - null, null, Actor.class); - assertThat(cursor.asListRemaining()) - .contains(new Actor("actors/BillPull", 1), new Actor("actors/ChristopherG", 1), new Actor("actors/CubaG", 1), - new Actor("actors/DemiM", 1), new Actor("actors/JackN", 1), new Actor("actors/JamesM", 1), - new Actor("actors/JTW", 1), new Actor("actors/KevinB", 1), new Actor("actors/KieferS", 1), - new Actor("actors/MegR", 2), new Actor("actors/Nathan", 1), new Actor("actors/NoahW", 1), - new Actor("actors/RitaW", 1), new Actor("actors/RosieO", 1), new Actor("actors/TomC", 1), - new Actor("actors/TomH", 2), new Actor("actors/VictorG", 1)); - } - - public static class Actor { - private String actor; - private Integer movies; - - public Actor() { - super(); - } - - Actor(final String actor, final Integer movies) { - super(); - this.actor = actor; - this.movies = movies; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((actor == null) ? 0 : actor.hashCode()); - result = prime * result + ((movies == null) ? 0 : movies.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Actor other = (Actor) obj; - if (actor == null) { - if (other.actor != null) { - return false; - } - } else if (!actor.equals(other.actor)) { - return false; - } - if (movies == null) { - return other.movies == null; - } else return movies.equals(other.movies); - } - - } - - public static class Movie { - private String movie; - private Integer actors; - - public Movie() { - super(); - } - - Movie(final String movie, final Integer actors) { - super(); - this.movie = movie; - this.actors = actors; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((actors == null) ? 0 : actors.hashCode()); - result = prime * result + ((movie == null) ? 0 : movie.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Movie other = (Movie) obj; - if (actors == null) { - if (other.actors != null) { - return false; - } - } else if (!actors.equals(other.actors)) { - return false; - } - if (movie == null) { - return other.movie == null; - } else return movie.equals(other.movie); - } - - } - - private static DocumentCreateEntity saveMovie( + private static DocumentCreateEntity saveMovie( final ArangoCollection movies, final String key, final String title, final int released, final String tagline) { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.setKey(key); value.addAttribute("title", title); value.addAttribute("released", released); @@ -330,12 +82,12 @@ private static DocumentCreateEntity saveMovie( return movies.insertDocument(value); } - private static DocumentCreateEntity saveActor( + private static DocumentCreateEntity saveActor( final ArangoCollection actors, final String key, final String name, final int born) { - final BaseDocument value = new BaseDocument(); + final BaseDocument value = new BaseDocument(UUID.randomUUID().toString()); value.setKey(key); value.addAttribute("name", name); value.addAttribute("born", born); @@ -401,7 +153,8 @@ private static void createData() { saveActsIn(actsIn, al, theDevilsAdvocate, new String[]{"John Milton"}, 1997); final String AFewGoodMen = saveMovie(movies, "AFewGoodMen", "A Few Good Men", 1992, - "In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at nothing to keep his honor, and one will stop at nothing to find the truth.") + "In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at " + + "nothing to keep his honor, and one will stop at nothing to find the truth.") .getId(); final String tomC = saveActor(actors, "TomC", "Tom Cruise", 1962).getId(); final String jackN = saveActor(actors, "JackN", "Jack Nicholson", 1937).getId(); @@ -460,7 +213,8 @@ private static void createData() { saveActsIn(actsIn, jonathanL, jerryMaguire, new String[]{"Ray Boyd"}, 2000); final String standByMe = saveMovie(movies, "StandByMe", "Stand By Me", 1986, - "For some, it's the last real taste of innocence, and the first real taste of life. But for everyone, it's the time that memories are made of.") + "For some, it's the last real taste of innocence, and the first real taste of life. But for everyone," + + " it's the time that memories are made of.") .getId(); final String riverP = saveActor(actors, "RiverP", "River Phoenix", 1970).getId(); final String coreyF = saveActor(actors, "CoreyF", "Corey Feldman", 1971).getId(); @@ -520,7 +274,8 @@ private static void createData() { saveActsIn(actsIn, steveZ, youveGotMail, new String[]{"George Pappas"}, 1998); final String sleeplessInSeattle = saveMovie(movies, "SleeplessInSeattle", "Sleepless in Seattle", 1993, - "What if someone you never met, someone you never saw, someone you never knew was the only someone for you?") + "What if someone you never met, someone you never saw, someone you never knew was the only someone " + + "for you?") .getId(); final String ritaW = saveActor(actors, "RitaW", "Rita Wilson", 1956).getId(); final String billPull = saveActor(actors, "BillPull", "Bill Pullman", 1953).getId(); @@ -552,4 +307,275 @@ private static void createData() { saveActsIn(actsIn, brunoK, whenHarryMetSally, new String[]{"Jess"}, 1998); } + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsActsInMovie1or2() { + final ArangoCursor cursor = db.query( + "WITH actors, movies FOR x IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: true, uniqueVertices: " + + "'global'} RETURN x._id", + null, null, String.class); + assertThat(cursor.asListRemaining()) + .contains("actors/Keanu", "actors/Hugo", "actors/Emil", "actors/Carrie", "actors/Laurence"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsActsInMovie1or2UnionDistinct() { + final ArangoCursor cursor = db.query( + "WITH actors, movies FOR x IN UNION_DISTINCT ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + + "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + null, null, String.class); + assertThat(cursor.asListRemaining()).contains("actors/Emil", "actors/Hugo", "actors/Carrie", "actors/Laurence", + "actors/Keanu", "actors/Al", "actors/Charlize"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsActsInMovie1and2() { + final ArangoCursor cursor = db.query( + "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'movies/TheMatrix' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'movies/TheDevilsAdvocate' " + + "actsIn OPTIONS {bfs: true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + null, null, String.class); + assertThat(cursor.asListRemaining()).contains("actors/Keanu"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allMoviesBetweenActor1andActor2() { + final ArangoCursor cursor = db.query( + "WITH actors, movies FOR x IN INTERSECTION ((FOR y IN ANY 'actors/Hugo' actsIn OPTIONS {bfs: true, " + + "uniqueVertices: 'global'} RETURN y._id), (FOR y IN ANY 'actors/Keanu' actsIn OPTIONS {bfs: " + + "true, uniqueVertices: 'global'} RETURN y._id)) RETURN x", + null, null, String.class); + assertThat(cursor.asListRemaining()) + .contains("movies/TheMatrixRevolutions", "movies/TheMatrixReloaded", "movies/TheMatrix"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allActorsWhoActedIn3orMoreMovies() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter FILTER counter >= 3 RETURN {actor: " + + "actor, movies: counter}", + null, null, Actor.class); + assertThat(cursor.asListRemaining()) + .contains(new Actor("actors/Carrie", 3), new Actor("actors/CubaG", 4), new Actor("actors/Hugo", 3), + new Actor("actors/Keanu", 4), new Actor("actors/Laurence", 3), new Actor("actors/MegR", 5), + new Actor("actors/TomC", 3), new Actor("actors/TomH", 3)); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void allMoviesWhereExactly6ActorsActedIn() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter FILTER counter == 6 RETURN movie", null, + null, String.class); + assertThat(cursor.asListRemaining()) + .contains("movies/SleeplessInSeattle", "movies/TopGun", "movies/YouveGotMail"); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void theNumberOfActorsByMovie() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn COLLECT movie = x._to WITH COUNT INTO counter RETURN {movie: movie, actors: counter}", + null, null, Movie.class); + assertThat(cursor.asListRemaining()) + .contains(new Movie("movies/AFewGoodMen", 11), new Movie("movies/AsGoodAsItGets", 4), + new Movie("movies/JerryMaguire", 9), new Movie("movies/JoeVersustheVolcano", 3), + new Movie("movies/SleeplessInSeattle", 6), new Movie("movies/SnowFallingonCedars", 4), + new Movie("movies/StandByMe", 7), new Movie("movies/TheDevilsAdvocate", 3), + new Movie("movies/TheMatrix", 5), new Movie("movies/TheMatrixReloaded", 4), + new Movie("movies/TheMatrixRevolutions", 4), new Movie("movies/TopGun", 6), + new Movie("movies/WhatDreamsMayCome", 5), new Movie("movies/WhenHarryMetSally", 4), + new Movie("movies/YouveGotMail", 6)); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void theNumberOfMoviesByActor() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn COLLECT actor = x._from WITH COUNT INTO counter RETURN {actor: actor, movies: " + + "counter}", + null, null, Actor.class); + assertThat(cursor.asListRemaining()) + .contains(new Actor("actors/Al", 1), new Actor("actors/AnnabellaS", 1), new Actor("actors/AnthonyE", 1), + new Actor("actors/BillPull", 1), new Actor("actors/BillyC", 1), new Actor("actors/BonnieH", 1), + new Actor("actors/BrunoK", 1), new Actor("actors/Carrie", 3), new Actor("actors/CarrieF", 1), + new Actor("actors/Charlize", 1), new Actor("actors/ChristopherG", 1), new Actor("actors" + + "/CoreyF", 1), + new Actor("actors/CubaG", 4), new Actor("actors/DaveC", 1), new Actor("actors/DemiM", 1), + new Actor("actors/Emil", 1), new Actor("actors/EthanH", 1), new Actor("actors/GregK", 2), + new Actor("actors/HelenH", 1), new Actor("actors/Hugo", 3), new Actor("actors/JackN", 2), + new Actor("actors/JamesC", 1), new Actor("actors/JamesM", 1), new Actor("actors/JayM", 1), + new Actor("actors/JerryO", 2), new Actor("actors/JohnC", 1), new Actor("actors/JonathanL", 1), + new Actor("actors/JTW", 1), new Actor("actors/Keanu", 4), new Actor("actors/KellyM", 1), + new Actor("actors/KellyP", 1), new Actor("actors/KevinB", 1), new Actor("actors/KevinP", 1), + new Actor("actors/KieferS", 2), new Actor("actors/Laurence", 3), new Actor("actors/MarshallB" + , 1), + new Actor("actors/MaxS", 2), new Actor("actors/MegR", 5), new Actor("actors/Nathan", 1), + new Actor("actors/NoahW", 1), new Actor("actors/ParkerP", 1), new Actor("actors/ReginaK", 1), + new Actor("actors/ReneeZ", 1), new Actor("actors/RickY", 1), new Actor("actors/RitaW", 1), + new Actor("actors/RiverP", 1), new Actor("actors/Robin", 1), new Actor("actors/RosieO", 1), + new Actor("actors/SteveZ", 1), new Actor("actors/TomC", 3), new Actor("actors/TomH", 3), + new Actor("actors/TomS", 1), new Actor("actors/ValK", 1), new Actor("actors/VictorG", 1), + new Actor("actors/WernerH", 1), new Actor("actors/WilW", 1)); + } + + /** + * @see AQL + * Example Queries on an Actors and Movies Database + */ + @Test + void theNumberOfMoviesActedInBetween2005and2010byActor() { + final ArangoCursor cursor = db.query( + "FOR x IN actsIn FILTER x.year >= 1990 && x.year <= 1995 COLLECT actor = x._from WITH COUNT INTO " + + "counter RETURN {actor: actor, movies: counter}", + null, null, Actor.class); + assertThat(cursor.asListRemaining()) + .contains(new Actor("actors/BillPull", 1), new Actor("actors/ChristopherG", 1), new Actor("actors" + + "/CubaG", 1), + new Actor("actors/DemiM", 1), new Actor("actors/JackN", 1), new Actor("actors/JamesM", 1), + new Actor("actors/JTW", 1), new Actor("actors/KevinB", 1), new Actor("actors/KieferS", 1), + new Actor("actors/MegR", 2), new Actor("actors/Nathan", 1), new Actor("actors/NoahW", 1), + new Actor("actors/RitaW", 1), new Actor("actors/RosieO", 1), new Actor("actors/TomC", 1), + new Actor("actors/TomH", 2), new Actor("actors/VictorG", 1)); + } + + public static class Actor { + private final String actor; + private final Integer movies; + + @JsonCreator + Actor(@JsonProperty("actor") final String actor, @JsonProperty("movies") final Integer movies) { + super(); + this.actor = actor; + this.movies = movies; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((actor == null) ? 0 : actor.hashCode()); + result = prime * result + ((movies == null) ? 0 : movies.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Actor other = (Actor) obj; + if (actor == null) { + if (other.actor != null) { + return false; + } + } else if (!actor.equals(other.actor)) { + return false; + } + if (movies == null) { + return other.movies == null; + } else return movies.equals(other.movies); + } + + } + + public static class Movie { + private final String movie; + private final Integer actors; + + @JsonCreator + public Movie(@JsonProperty("movie") final String movie, @JsonProperty("actors") final Integer actors) { + super(); + this.movie = movie; + this.actors = actors; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((actors == null) ? 0 : actors.hashCode()); + result = prime * result + ((movie == null) ? 0 : movie.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Movie other = (Movie) obj; + if (actors == null) { + if (other.actors != null) { + return false; + } + } else if (!actors.equals(other.actors)) { + return false; + } + if (movie == null) { + return other.movie == null; + } else return movie.equals(other.movie); + } + + } + } diff --git a/src/test/java/com/arangodb/example/graph/BaseGraphTest.java b/driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java similarity index 95% rename from src/test/java/com/arangodb/example/graph/BaseGraphTest.java rename to driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java index f74c4ed42..8b742e52d 100644 --- a/src/test/java/com/arangodb/example/graph/BaseGraphTest.java +++ b/driver/src/test/java/com/arangodb/example/graph/BaseGraphTest.java @@ -1,112 +1,114 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.graph; - -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDBException; -import com.arangodb.ArangoDatabase; -import com.arangodb.DbName; -import com.arangodb.entity.EdgeDefinition; -import com.arangodb.entity.VertexEntity; -import com.arangodb.mapping.ArangoJack; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * @author Mark Vollmary - */ -abstract class BaseGraphTest { - - private static final DbName TEST_DB = DbName.of("java_driver_graph_test_db"); - private static ArangoDB arangoDB; - static ArangoDatabase db; - private static final String GRAPH_NAME = "traversalGraph"; - private static final String EDGE_COLLECTION_NAME = "edges"; - private static final String VERTEX_COLLECTION_NAME = "circles"; - - @BeforeAll - static void init() { - if (arangoDB == null) { - arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); - } - if (arangoDB.db(TEST_DB).exists()) - arangoDB.db(TEST_DB).drop(); - arangoDB.createDatabase(TEST_DB); - BaseGraphTest.db = arangoDB.db(TEST_DB); - - final Collection edgeDefinitions = new ArrayList<>(); - final EdgeDefinition edgeDefinition = new EdgeDefinition().collection(EDGE_COLLECTION_NAME) - .from(VERTEX_COLLECTION_NAME).to(VERTEX_COLLECTION_NAME); - edgeDefinitions.add(edgeDefinition); - if (!db.graph(GRAPH_NAME).exists()) - db.createGraph(GRAPH_NAME, edgeDefinitions, null); - addExampleElements(); - } - - @AfterAll - static void shutdown() { - arangoDB.db(TEST_DB).drop(); - arangoDB.shutdown(); - arangoDB = null; - } - - private static void addExampleElements() throws ArangoDBException { - - // Add circle circles - final VertexEntity vA = createVertex(new Circle("A", "1")); - final VertexEntity vB = createVertex(new Circle("B", "2")); - final VertexEntity vC = createVertex(new Circle("C", "3")); - final VertexEntity vD = createVertex(new Circle("D", "4")); - final VertexEntity vE = createVertex(new Circle("E", "5")); - final VertexEntity vF = createVertex(new Circle("F", "6")); - final VertexEntity vG = createVertex(new Circle("G", "7")); - final VertexEntity vH = createVertex(new Circle("H", "8")); - final VertexEntity vI = createVertex(new Circle("I", "9")); - final VertexEntity vJ = createVertex(new Circle("J", "10")); - final VertexEntity vK = createVertex(new Circle("K", "11")); - - // Add relevant edges - left branch: - saveEdge(new CircleEdge(vA.getId(), vB.getId(), false, true, "left_bar")); - saveEdge(new CircleEdge(vB.getId(), vC.getId(), false, true, "left_blarg")); - saveEdge(new CircleEdge(vC.getId(), vD.getId(), false, true, "left_blorg")); - saveEdge(new CircleEdge(vB.getId(), vE.getId(), false, true, "left_blub")); - saveEdge(new CircleEdge(vE.getId(), vF.getId(), false, true, "left_schubi")); - - // Add relevant edges - right branch: - saveEdge(new CircleEdge(vA.getId(), vG.getId(), false, true, "right_foo")); - saveEdge(new CircleEdge(vG.getId(), vH.getId(), false, true, "right_blob")); - saveEdge(new CircleEdge(vH.getId(), vI.getId(), false, true, "right_blub")); - saveEdge(new CircleEdge(vG.getId(), vJ.getId(), false, true, "right_zip")); - saveEdge(new CircleEdge(vJ.getId(), vK.getId(), false, true, "right_zup")); - } - - private static void saveEdge(final CircleEdge edge) throws ArangoDBException { - db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(edge); - } - - private static VertexEntity createVertex(final Circle vertex) throws ArangoDBException { - return db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME).insertVertex(vertex); - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.example.graph; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.ArangoDatabase; +import com.arangodb.DbName; +import com.arangodb.config.ConfigUtils; +import com.arangodb.entity.EdgeDefinition; +import com.arangodb.entity.VertexEntity; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * @author Mark Vollmary + */ +abstract class BaseGraphTest { + + private static final DbName TEST_DB = DbName.of("java_driver_graph_test_db"); + private static final String GRAPH_NAME = "traversalGraph"; + private static final String EDGE_COLLECTION_NAME = "edges"; + private static final String VERTEX_COLLECTION_NAME = "circles"; + static ArangoDatabase db; + private static ArangoDB arangoDB; + + @BeforeAll + static void init() { + if (arangoDB == null) { + arangoDB = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); + } + if (arangoDB.db(TEST_DB).exists()) + arangoDB.db(TEST_DB).drop(); + arangoDB.createDatabase(TEST_DB); + BaseGraphTest.db = arangoDB.db(TEST_DB); + + final Collection edgeDefinitions = new ArrayList<>(); + final EdgeDefinition edgeDefinition = new EdgeDefinition().collection(EDGE_COLLECTION_NAME) + .from(VERTEX_COLLECTION_NAME).to(VERTEX_COLLECTION_NAME); + edgeDefinitions.add(edgeDefinition); + if (!db.graph(GRAPH_NAME).exists()) + db.createGraph(GRAPH_NAME, edgeDefinitions, null); + addExampleElements(); + } + + @AfterAll + static void shutdown() { + arangoDB.db(TEST_DB).drop(); + arangoDB.shutdown(); + arangoDB = null; + } + + private static void addExampleElements() throws ArangoDBException { + + // Add circle circles + final VertexEntity vA = createVertex(new Circle("A", "1")); + final VertexEntity vB = createVertex(new Circle("B", "2")); + final VertexEntity vC = createVertex(new Circle("C", "3")); + final VertexEntity vD = createVertex(new Circle("D", "4")); + final VertexEntity vE = createVertex(new Circle("E", "5")); + final VertexEntity vF = createVertex(new Circle("F", "6")); + final VertexEntity vG = createVertex(new Circle("G", "7")); + final VertexEntity vH = createVertex(new Circle("H", "8")); + final VertexEntity vI = createVertex(new Circle("I", "9")); + final VertexEntity vJ = createVertex(new Circle("J", "10")); + final VertexEntity vK = createVertex(new Circle("K", "11")); + + // Add relevant edges - left branch: + saveEdge(new CircleEdge(vA.getId(), vB.getId(), false, true, "left_bar")); + saveEdge(new CircleEdge(vB.getId(), vC.getId(), false, true, "left_blarg")); + saveEdge(new CircleEdge(vC.getId(), vD.getId(), false, true, "left_blorg")); + saveEdge(new CircleEdge(vB.getId(), vE.getId(), false, true, "left_blub")); + saveEdge(new CircleEdge(vE.getId(), vF.getId(), false, true, "left_schubi")); + + // Add relevant edges - right branch: + saveEdge(new CircleEdge(vA.getId(), vG.getId(), false, true, "right_foo")); + saveEdge(new CircleEdge(vG.getId(), vH.getId(), false, true, "right_blob")); + saveEdge(new CircleEdge(vH.getId(), vI.getId(), false, true, "right_blub")); + saveEdge(new CircleEdge(vG.getId(), vJ.getId(), false, true, "right_zip")); + saveEdge(new CircleEdge(vJ.getId(), vK.getId(), false, true, "right_zup")); + } + + private static void saveEdge(final CircleEdge edge) throws ArangoDBException { + db.graph(GRAPH_NAME).edgeCollection(EDGE_COLLECTION_NAME).insertEdge(edge); + } + + private static VertexEntity createVertex(final Circle vertex) throws ArangoDBException { + return db.graph(GRAPH_NAME).vertexCollection(VERTEX_COLLECTION_NAME).insertVertex(vertex); + } + +} diff --git a/src/test/java/com/arangodb/example/graph/Circle.java b/driver/src/test/java/com/arangodb/example/graph/Circle.java similarity index 92% rename from src/test/java/com/arangodb/example/graph/Circle.java rename to driver/src/test/java/com/arangodb/example/graph/Circle.java index c603983c9..f40783bdd 100644 --- a/src/test/java/com/arangodb/example/graph/Circle.java +++ b/driver/src/test/java/com/arangodb/example/graph/Circle.java @@ -20,14 +20,13 @@ package com.arangodb.example.graph; -import com.arangodb.entity.Id; -import com.arangodb.entity.Key; -import com.arangodb.entity.Rev; +import com.arangodb.serde.jackson.Id; +import com.arangodb.serde.jackson.Key; +import com.arangodb.serde.jackson.Rev; /** * @author a-brandt */ -@SuppressWarnings("unused") class Circle { @Id diff --git a/src/test/java/com/arangodb/example/graph/CircleEdge.java b/driver/src/test/java/com/arangodb/example/graph/CircleEdge.java similarity index 97% rename from src/test/java/com/arangodb/example/graph/CircleEdge.java rename to driver/src/test/java/com/arangodb/example/graph/CircleEdge.java index 6ba211c56..96afa9f00 100644 --- a/src/test/java/com/arangodb/example/graph/CircleEdge.java +++ b/driver/src/test/java/com/arangodb/example/graph/CircleEdge.java @@ -20,12 +20,11 @@ package com.arangodb.example.graph; -import com.arangodb.entity.*; +import com.arangodb.serde.jackson.*; /** * @author a-brandt */ -@SuppressWarnings("unused") class CircleEdge { @Id diff --git a/src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java b/driver/src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java similarity index 90% rename from src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java rename to driver/src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java index 35330c490..94e48a307 100644 --- a/src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java +++ b/driver/src/test/java/com/arangodb/example/graph/GraphTraversalsInAQLExampleTest.java @@ -65,23 +65,27 @@ void queryDepthTwo() throws ArangoDBException { @Test void queryWithFilter() throws ArangoDBException { - String queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G' RETURN v._key"; + String queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]" + + "._key != 'G' RETURN v._key"; ArangoCursor cursor = db.query(queryString, null, null, String.class); Collection result = cursor.asListRemaining(); assertThat(result).containsExactlyInAnyOrder("B", "C", "D", "E", "F"); - queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label != 'right_foo' RETURN v._key"; + queryString = "FOR v, e, p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.edges[0].label != " + + "'right_foo' RETURN v._key"; cursor = db.query(queryString, null, null, String.class); result = cursor.asListRemaining(); assertThat(result).containsExactlyInAnyOrder("B", "C", "D", "E", "F"); - queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G' FILTER p.edges[1].label != 'left_blub' return v._key"; + queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + + " FILTER p.edges[1].label != 'left_blub' return v._key"; cursor = db.query(queryString, null, null, String.class); result = cursor.asListRemaining(); assertThat(result).containsExactlyInAnyOrder("B", "C", "D"); - queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G' AND p.edges[1].label != 'left_blub' return v._key"; + queryString = "FOR v,e,p IN 1..3 OUTBOUND 'circles/A' GRAPH 'traversalGraph' FILTER p.vertices[1]._key != 'G'" + + " AND p.edges[1].label != 'left_blub' return v._key"; cursor = db.query(queryString, null, null, String.class); result = cursor.asListRemaining(); assertThat(result).containsExactlyInAnyOrder("B", "C", "D"); diff --git a/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java b/driver/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java similarity index 85% rename from src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java rename to driver/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java index 7eb87fcb3..aecf7321a 100644 --- a/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java +++ b/driver/src/test/java/com/arangodb/example/graph/ShortestPathInAQLExampleTest.java @@ -38,39 +38,17 @@ */ class ShortestPathInAQLExampleTest extends BaseGraphTest { - @SuppressWarnings({"WeakerAccess", "unused"}) - public static class Pair { - - private String vertex; - private String edge; - - String getVertex() { - return vertex; - } - - void setVertex(final String vertex) { - this.vertex = vertex; - } - - String getEdge() { - return edge; - } - - void setEdge(final String edge) { - this.edge = edge; - } - - } - @Test void queryShortestPathFromAToD() throws ArangoDBException { - String queryString = "FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' GRAPH 'traversalGraph' RETURN {'vertex': v._key, 'edge': e._key}"; + String queryString = "FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' GRAPH 'traversalGraph' " + + "RETURN {'vertex': v._key, 'edge': e._key}"; ArangoCursor cursor = db.query(queryString, null, null, Pair.class); final Collection collection = toVertexCollection(cursor); assertThat(collection.size()).isEqualTo(4); assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); - queryString = "WITH circles FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' edges RETURN {'vertex': v._key, 'edge': e._key}"; + queryString = "WITH circles FOR v, e IN OUTBOUND SHORTEST_PATH 'circles/A' TO 'circles/D' edges RETURN " + + "{'vertex': v._key, 'edge': e._key}"; db.query(queryString, null, null, Pair.class); assertThat(collection.size()).isEqualTo(4); assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); @@ -78,13 +56,15 @@ void queryShortestPathFromAToD() throws ArangoDBException { @Test void queryShortestPathByFilter() throws ArangoDBException { - String queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN OUTBOUND SHORTEST_PATH a TO d GRAPH 'traversalGraph' RETURN {'vertex':v._key, 'edge':e._key}"; + String queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN" + + " OUTBOUND SHORTEST_PATH a TO d GRAPH 'traversalGraph' RETURN {'vertex':v._key, 'edge':e._key}"; ArangoCursor cursor = db.query(queryString, null, null, Pair.class); final Collection collection = toVertexCollection(cursor); assertThat(collection.size()).isEqualTo(4); assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); - queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN OUTBOUND SHORTEST_PATH a TO d edges RETURN {'vertex': v._key, 'edge': e._key}"; + queryString = "FOR a IN circles FILTER a._key == 'A' FOR d IN circles FILTER d._key == 'D' FOR v, e IN " + + "OUTBOUND SHORTEST_PATH a TO d edges RETURN {'vertex': v._key, 'edge': e._key}"; db.query(queryString, null, null, Pair.class); assertThat(collection.size()).isEqualTo(4); assertThat(collection).containsExactlyInAnyOrder("A", "B", "C", "D"); @@ -99,4 +79,27 @@ private Collection toVertexCollection(final ArangoCursor cursor) { return result; } + public static class Pair { + + private String vertex; + private String edge; + + String getVertex() { + return vertex; + } + + void setVertex(final String vertex) { + this.vertex = vertex; + } + + String getEdge() { + return edge; + } + + void setEdge(final String edge) { + this.edge = edge; + } + + } + } diff --git a/src/test/java/com/arangodb/example/ssl/SslExampleTest.java b/driver/src/test/java/com/arangodb/example/ssl/SslExampleTest.java similarity index 64% rename from src/test/java/com/arangodb/example/ssl/SslExampleTest.java rename to driver/src/test/java/com/arangodb/example/ssl/SslExampleTest.java index a21384bdd..b3f97ff16 100644 --- a/src/test/java/com/arangodb/example/ssl/SslExampleTest.java +++ b/driver/src/test/java/com/arangodb/example/ssl/SslExampleTest.java @@ -21,24 +21,28 @@ package com.arangodb.example.ssl; import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.ArangoDBMultipleException; import com.arangodb.Protocol; import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.mapping.ArangoJack; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.*; import java.security.KeyStore; +import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; /** * @author Mark Vollmary * @author Michele Rastelli */ +@Tag("ssl") @EnabledIfSystemProperty(named = "SslTest", matches = "true") class SslExampleTest { @@ -54,37 +58,57 @@ class SslExampleTest { private static final String SSL_TRUSTSTORE = "/example.truststore"; private static final String SSL_TRUSTSTORE_PASSWORD = "12345678"; - @Test - void connect() throws Exception { + @ParameterizedTest + @EnumSource(Protocol.class) + void connect(Protocol protocol) throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() - .serializer(new ArangoJack()) .host("localhost", 8529) .password("test") .useSsl(true) .sslContext(createSslContext()) - .useProtocol(Protocol.HTTP_JSON) + .useProtocol(protocol) .build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); System.out.println(version.getVersion()); } - @Test - void noopHostnameVerifier() throws Exception { + @ParameterizedTest + @EnumSource(Protocol.class) + void noopHostnameVerifier(Protocol protocol) throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder() - .serializer(new ArangoJack()) .host("127.0.0.1", 8529) .password("test") .useSsl(true) .sslContext(createSslContext()) - .hostnameVerifier(NoopHostnameVerifier.INSTANCE) - .useProtocol(Protocol.HTTP_JSON) + .verifyHost(false) + .useProtocol(protocol) .build(); final ArangoDBVersion version = arangoDB.getVersion(); assertThat(version).isNotNull(); System.out.println(version.getVersion()); } + @ParameterizedTest + @EnumSource(Protocol.class) + void hostnameVerifierFailure(Protocol protocol) throws Exception { + assumeTrue(protocol != Protocol.VST, "VST does not support hostname verification"); + final ArangoDB arangoDB = new ArangoDB.Builder() + .host("127.0.0.1", 8529) + .password("test") + .useSsl(true) + .sslContext(createSslContext()) + .verifyHost(true) + .useProtocol(protocol) + .build(); + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + ArangoDBException ex = (ArangoDBException) thrown; + assertThat(ex.getCause()).isInstanceOf(ArangoDBMultipleException.class); + List exceptions = ((ArangoDBMultipleException) ex.getCause()).getExceptions(); + exceptions.forEach(e -> assertThat(e).isInstanceOf(SSLHandshakeException.class)); + } + private SSLContext createSslContext() throws Exception { final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(this.getClass().getResourceAsStream(SSL_TRUSTSTORE), SSL_TRUSTSTORE_PASSWORD.toCharArray()); diff --git a/src/test/java/com/arangodb/internal/HostHandlerTest.java b/driver/src/test/java/com/arangodb/internal/HostHandlerTest.java similarity index 95% rename from src/test/java/com/arangodb/internal/HostHandlerTest.java rename to driver/src/test/java/com/arangodb/internal/HostHandlerTest.java index 56b09ca5d..973d3a7c1 100644 --- a/src/test/java/com/arangodb/internal/HostHandlerTest.java +++ b/driver/src/test/java/com/arangodb/internal/HostHandlerTest.java @@ -22,8 +22,9 @@ import com.arangodb.ArangoDBException; import com.arangodb.ArangoDBMultipleException; +import com.arangodb.config.HostDescription; import com.arangodb.internal.net.*; -import com.arangodb.util.ArangoSerialization; +import com.arangodb.internal.serde.InternalSerde; import org.junit.jupiter.api.Test; import java.util.List; @@ -59,9 +60,6 @@ public void close() { }; private static final Host HOST_0 = new HostImpl(mockCP, new HostDescription("127.0.0.1", 8529)); - private static final Host HOST_1 = new HostImpl(mockCP, new HostDescription("127.0.0.2", 8529)); - private static final Host HOST_2 = new HostImpl(mockCP, new HostDescription("127.0.0.3", 8529)); - private static final HostResolver SINGLE_HOST = new HostResolver() { @Override @@ -73,12 +71,13 @@ public HostSet resolve(final boolean initial, final boolean closeConnections) { } @Override - public void init(ArangoExecutorSync executor, ArangoSerialization arangoSerialization) { + public void init(ArangoExecutorSync executor, InternalSerde arangoSerialization) { } }; - + private static final Host HOST_1 = new HostImpl(mockCP, new HostDescription("127.0.0.2", 8529)); + private static final Host HOST_2 = new HostImpl(mockCP, new HostDescription("127.0.0.3", 8529)); private static final HostResolver MULTIPLE_HOSTS = new HostResolver() { @Override @@ -92,7 +91,7 @@ public HostSet resolve(final boolean initial, final boolean closeConnections) { } @Override - public void init(ArangoExecutorSync executor, ArangoSerialization arangoSerialization) { + public void init(ArangoExecutorSync executor, InternalSerde arangoSerialization) { } diff --git a/src/test/java/com/arangodb/internal/QueueTimeMetricsImplTest.java b/driver/src/test/java/com/arangodb/internal/QueueTimeMetricsImplTest.java similarity index 100% rename from src/test/java/com/arangodb/internal/QueueTimeMetricsImplTest.java rename to driver/src/test/java/com/arangodb/internal/QueueTimeMetricsImplTest.java diff --git a/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java b/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java similarity index 78% rename from src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java rename to driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java index 0778c58ed..58a87bd71 100644 --- a/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java +++ b/driver/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java @@ -1,112 +1,113 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream; - -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDatabase; -import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.mapping.ArangoJack; -import org.junit.jupiter.api.Test; - -import java.util.Collection; -import java.util.Iterator; -import java.util.concurrent.ConcurrentLinkedQueue; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Mark Vollmary - */ -class CommunicationTest { - - private static final String FAST = "fast"; - private static final String SLOW = "slow"; - - @Test - void chunkSizeSmall() { - final ArangoDB arangoDB = new ArangoDB.Builder().chunksize(20).serializer(new ArangoJack()).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } - - @Test - void multiThread() throws Exception { - final ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); - arangoDB.getUsers(); // authentication and active-failover connection redirect to master - - final Collection result = new ConcurrentLinkedQueue<>(); - final Thread fast = new Thread(() -> { - arangoDB.db().query("return sleep(0.1)", null, null, null); - result.add(FAST); - }); - final Thread slow = new Thread(() -> { - arangoDB.db().query("return sleep(0.5)", null, null, null); - result.add(SLOW); - }); - slow.start(); - fast.start(); - - slow.join(); - fast.join(); - - assertThat(result.size()).isEqualTo(2); - final Iterator iterator = result.iterator(); - assertThat(iterator.next()).isEqualTo(FAST); - assertThat(iterator.next()).isEqualTo(SLOW); - } - - @Test - void multiThreadSameDatabases() throws Exception { - final ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); - arangoDB.getUsers(); // authentication and active-failover connection redirect to master - - final ArangoDatabase db = arangoDB.db(); - - final Collection result = new ConcurrentLinkedQueue<>(); - final Thread t1 = new Thread(() -> { - db.query("return sleep(0.1)", null, null, null); - result.add("1"); - }); - final Thread t2 = new Thread(() -> { - db.query("return sleep(0.1)", null, null, null); - result.add("1"); - }); - t2.start(); - t1.start(); - t2.join(); - t1.join(); - assertThat(result.size()).isEqualTo(2); - } - - @Test - void minOneConnection() { - final ArangoDB arangoDB = new ArangoDB.Builder().maxConnections(0).serializer(new ArangoJack()).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } - - @Test - void defaultMaxConnection() { - final ArangoDB arangoDB = new ArangoDB.Builder().maxConnections(null).serializer(new ArangoJack()).build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.internal.velocystream; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDatabase; +import com.arangodb.config.ConfigUtils; +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.Iterator; +import java.util.concurrent.ConcurrentLinkedQueue; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Mark Vollmary + */ +class CommunicationTest { + + private static final String FAST = "fast"; + private static final String SLOW = "slow"; + + @Test + void chunkSizeSmall() { + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .chunksize(20).build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } + + @Test + void multiThread() throws Exception { + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); + arangoDB.getUsers(); // authentication and active-failover connection redirect to master + + final Collection result = new ConcurrentLinkedQueue<>(); + final Thread fast = new Thread(() -> { + arangoDB.db().query("return sleep(0.1)", null, null, null); + result.add(FAST); + }); + final Thread slow = new Thread(() -> { + arangoDB.db().query("return sleep(0.5)", null, null, null); + result.add(SLOW); + }); + slow.start(); + fast.start(); + + slow.join(); + fast.join(); + + assertThat(result.size()).isEqualTo(2); + final Iterator iterator = result.iterator(); + assertThat(iterator.next()).isEqualTo(FAST); + assertThat(iterator.next()).isEqualTo(SLOW); + } + + @Test + void multiThreadSameDatabases() throws Exception { + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .build(); + arangoDB.getUsers(); // authentication and active-failover connection redirect to master + + final ArangoDatabase db = arangoDB.db(); + + final Collection result = new ConcurrentLinkedQueue<>(); + final Thread t1 = new Thread(() -> { + db.query("return sleep(0.1)", null, null, null); + result.add("1"); + }); + final Thread t2 = new Thread(() -> { + db.query("return sleep(0.1)", null, null, null); + result.add("1"); + }); + t2.start(); + t1.start(); + t2.join(); + t1.join(); + assertThat(result.size()).isEqualTo(2); + } + + @Test + void defaultMaxConnection() { + final ArangoDB arangoDB = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .maxConnections(null).build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } +} diff --git a/src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java b/driver/src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java similarity index 97% rename from src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java rename to driver/src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java index e3ce6ea78..f26fb6f25 100644 --- a/src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java +++ b/driver/src/test/java/com/arangodb/mapping/annotations/AnnotatedEntity.java @@ -1,6 +1,6 @@ package com.arangodb.mapping.annotations; -import com.arangodb.entity.*; +import com.arangodb.serde.jackson.*; import java.util.Objects; diff --git a/driver/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java b/driver/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java new file mode 100644 index 000000000..084f67ba9 --- /dev/null +++ b/driver/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java @@ -0,0 +1,64 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.mapping.annotations; + +import com.arangodb.ContentType; +import com.arangodb.serde.ArangoSerde; +import com.arangodb.serde.jackson.JacksonSerdeProvider; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Michele Rastelli + */ +class ArangoAnnotationsTest { + + @ParameterizedTest + @EnumSource(ContentType.class) + void documentFieldAnnotations(ContentType contentType) { + ArangoSerde mapper = new JacksonSerdeProvider().of(contentType); + + AnnotatedEntity e = new AnnotatedEntity(); + e.setId("Id"); + e.setKey("Key"); + e.setRev("Rev"); + e.setFrom("From"); + e.setTo("To"); + + byte[] serialized = mapper.serialize(e); + Map deserialized = mapper.deserialize(serialized, Map.class); + assertThat(deserialized) + .containsEntry("_id", e.getId()) + .containsEntry("_key", e.getKey()) + .containsEntry("_rev", e.getRev()) + .containsEntry("_from", e.getFrom()) + .containsEntry("_to", e.getTo()) + .hasSize(5); + + AnnotatedEntity deserializedEntity = mapper.deserialize(serialized, AnnotatedEntity.class); + assertThat(deserializedEntity).isEqualTo(e); + } + +} diff --git a/src/test/java/com/arangodb/serde/CustomSerdeTest.java b/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java similarity index 60% rename from src/test/java/com/arangodb/serde/CustomSerdeTest.java rename to driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java index 834d1cd56..4e42730ba 100644 --- a/src/test/java/com/arangodb/serde/CustomSerdeTest.java +++ b/driver/src/test/java/com/arangodb/serde/CustomSerdeTest.java @@ -21,23 +21,15 @@ package com.arangodb.serde; -import com.arangodb.ArangoCollection; -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDatabase; -import com.arangodb.DbName; -import com.arangodb.entity.BaseDocument; -import com.arangodb.mapping.ArangoJack; +import com.arangodb.*; +import com.arangodb.config.ConfigUtils; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.model.DocumentCreateOptions; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; +import com.arangodb.serde.jackson.JacksonSerde; +import com.arangodb.serde.jackson.JacksonSerdeProvider; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.module.SimpleModule; import org.junit.jupiter.api.AfterAll; @@ -48,12 +40,11 @@ import java.math.BigInteger; import java.util.Collections; import java.util.HashMap; +import java.util.Map; import java.util.UUID; -import static com.arangodb.internal.util.ArangoSerializationFactory.Serializer.CUSTOM; import static com.fasterxml.jackson.databind.DeserializationFeature.USE_BIG_INTEGER_FOR_INTS; import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED; - import static org.assertj.core.api.Assertions.assertThat; @@ -70,45 +61,20 @@ class CustomSerdeTest { private static ArangoDatabase db; private static ArangoCollection collection; - static class PersonSerializer extends JsonSerializer { - @Override - public void serialize(Person value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeStartObject(); - gen.writeFieldName("name"); - gen.writeString(PERSON_SERIALIZER_ADDED_PREFIX + value.name); - gen.writeEndObject(); - } - } - - static class PersonDeserializer extends JsonDeserializer { - @Override - public Person deserialize(JsonParser parser, DeserializationContext ctx) throws IOException { - Person person = new Person(); - JsonNode rootNode = parser.getCodec().readTree(parser); - JsonNode nameNode = rootNode.get("name"); - if (nameNode != null && nameNode.isTextual()) { - person.name = PERSON_DESERIALIZER_ADDED_PREFIX + nameNode.asText(); - } - return person; - } - } - - @JsonSerialize(using = PersonSerializer.class) - static class Person { - String name; - } - @BeforeAll static void init() { - ArangoJack arangoJack = new ArangoJack(); - arangoJack.configure((mapper) -> { + JacksonSerde serde = new JacksonSerdeProvider().of(ContentType.VPACK); + serde.configure((mapper) -> { mapper.configure(WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true); mapper.configure(USE_BIG_INTEGER_FOR_INTS, true); SimpleModule module = new SimpleModule("PersonModule"); module.addDeserializer(Person.class, new PersonDeserializer()); mapper.registerModule(module); }); - arangoDB = new ArangoDB.Builder().serializer(arangoJack).build(); + arangoDB = new ArangoDB.Builder() + .loadProperties(ConfigUtils.loadConfig()) + .useProtocol(Protocol.VST) + .serde(serde).build(); db = arangoDB.db(DbName.of("custom-serde-test")); if (!db.exists()) { @@ -142,9 +108,9 @@ void customPersonDeserializer() { void manualCustomPersonDeserializer() { Person person = new Person(); person.name = "Joe"; - ArangoSerialization serialization = arangoDB.util(CUSTOM); - VPackSlice serializedPerson = serialization.serialize(person); - Person deserializedPerson = serialization.deserialize(serializedPerson, Person.class); + InternalSerde serialization = arangoDB.getSerde(); + byte[] serialized = serialization.serializeUserData(person); + Person deserializedPerson = serialization.deserializeUserData(serialized, Person.class); assertThat(deserializedPerson.name).isEqualTo(PERSON_DESERIALIZER_ADDED_PREFIX + PERSON_SERIALIZER_ADDED_PREFIX + person.name); } @@ -152,92 +118,125 @@ void manualCustomPersonDeserializer() { void aqlSerialization() { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); HashMap params = new HashMap<>(); params.put("doc", doc); params.put("@collection", COLLECTION_NAME); - BaseDocument result = db.query( + Map result = db.query( "INSERT @doc INTO @@collection RETURN NEW", params, - BaseDocument.class + Map.class ).next(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test void aqlDeserialization() { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); - collection.insertDocument(doc, null); + collection.insertDocument(doc); - final BaseDocument result = db.query( + final Map result = db.query( "RETURN DOCUMENT(@docId)", Collections.singletonMap("docId", COLLECTION_NAME + "/" + key), - BaseDocument.class + Map.class ).next(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test void insertDocument() { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); - BaseDocument result = collection.insertDocument( + Map result = collection.insertDocument( doc, new DocumentCreateOptions().returnNew(true) ).getNew(); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test void getDocument() { String key = "test-" + UUID.randomUUID(); - BaseDocument doc = new BaseDocument(key); - doc.addAttribute("arr", Collections.singletonList("hello")); - doc.addAttribute("int", 10); + Map doc = new HashMap<>(); + doc.put("_key", key); + doc.put("arr", Collections.singletonList("hello")); + doc.put("int", 10); - collection.insertDocument(doc, null); + collection.insertDocument(doc); - final BaseDocument result = db.collection(COLLECTION_NAME).getDocument( + final Map result = db.collection(COLLECTION_NAME).getDocument( key, - BaseDocument.class, + Map.class, null); - assertThat(result.getAttribute("arr")).isInstanceOf(String.class); - assertThat(result.getAttribute("arr")).isEqualTo("hello"); - assertThat(result.getAttribute("int")).isInstanceOf(BigInteger.class); - assertThat(result.getAttribute("int")).isEqualTo(BigInteger.valueOf(10)); + assertThat(result.get("arr")).isInstanceOf(String.class); + assertThat(result.get("arr")).isEqualTo("hello"); + assertThat(result.get("int")).isInstanceOf(BigInteger.class); + assertThat(result.get("int")).isEqualTo(BigInteger.valueOf(10)); } @Test void parseNullString() { - final String json = arangoDB.util(CUSTOM).deserialize(new VPackBuilder().add((String) null).slice(), String.class); + final String json = arangoDB.getSerde().deserializeUserData(arangoDB.getSerde().serializeUserData(null), + String.class); assertThat(json).isNull(); } + static class PersonSerializer extends JsonSerializer { + @Override + public void serialize(Person value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + gen.writeFieldName("name"); + gen.writeString(PERSON_SERIALIZER_ADDED_PREFIX + value.name); + gen.writeEndObject(); + } + } + + static class PersonDeserializer extends JsonDeserializer { + @Override + public Person deserialize(JsonParser parser, DeserializationContext ctx) throws IOException { + Person person = new Person(); + JsonNode rootNode = parser.getCodec().readTree(parser); + JsonNode nameNode = rootNode.get("name"); + if (nameNode != null && nameNode.isTextual()) { + person.name = PERSON_DESERIALIZER_ADDED_PREFIX + nameNode.asText(); + } + return person; + } + } + + @JsonSerialize(using = PersonSerializer.class) + static class Person { + String name; + } + } diff --git a/src/test/java/com/arangodb/serde/CustomTypeHintTest.java b/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java similarity index 95% rename from src/test/java/com/arangodb/serde/CustomTypeHintTest.java rename to driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java index a19eda063..f8f79f444 100644 --- a/src/test/java/com/arangodb/serde/CustomTypeHintTest.java +++ b/driver/src/test/java/com/arangodb/serde/CustomTypeHintTest.java @@ -25,9 +25,9 @@ import com.arangodb.ArangoDB; import com.arangodb.ArangoDatabase; import com.arangodb.DbName; -import com.arangodb.mapping.ArangoJack; +import com.arangodb.config.ConfigUtils; import com.arangodb.model.DocumentCreateOptions; -import com.fasterxml.jackson.annotation.JsonProperty; +import com.arangodb.serde.jackson.Key; import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -41,57 +41,14 @@ */ class CustomTypeHintTest { - @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") - public interface Animal { - String getName(); - } - - public static class Gorilla implements Animal { - private String name; - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - - public static class Zoo { - - @JsonProperty("_key") - private String key; - - private Animal animal; - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public Animal getAnimal() { - return animal; - } - - public void setAnimal(Animal animal) { - this.animal = animal; - } - } - private static final String COLLECTION_NAME = "collection"; - private ArangoDatabase db; private ArangoCollection collection; @BeforeEach void init() { ArangoDB arangoDB = new ArangoDB.Builder() - .serializer(new ArangoJack()) + .loadProperties(ConfigUtils.loadConfig()) .build(); db = arangoDB.db(DbName.of("custom-serde-test")); @@ -143,4 +100,46 @@ void insertDocument() { assertThat((readDoc.getAnimal().getName())).isEqualTo("kingKong"); } + + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "type") + public interface Animal { + String getName(); + } + + public static class Gorilla implements Animal { + private String name; + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static class Zoo { + + @Key + private String key; + + private Animal animal; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public Animal getAnimal() { + return animal; + } + + public void setAnimal(Animal animal) { + this.animal = animal; + } + } } diff --git a/driver/src/test/java/com/arangodb/serde/SerdeTest.java b/driver/src/test/java/com/arangodb/serde/SerdeTest.java new file mode 100644 index 000000000..d99b7e0a6 --- /dev/null +++ b/driver/src/test/java/com/arangodb/serde/SerdeTest.java @@ -0,0 +1,41 @@ +package com.arangodb.serde; + +import com.arangodb.ContentType; +import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.serde.InternalSerdeProvider; +import com.arangodb.internal.serde.SerdeUtils; +import com.arangodb.util.RawBytes; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import static org.assertj.core.api.Assertions.assertThat; + + +class SerdeTest { + + @ParameterizedTest + @EnumSource(ContentType.class) + void rawJsonSerde(ContentType type) { + InternalSerde s = new InternalSerdeProvider().of(type); + ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); + RawJson raw = RawJson.of(SerdeUtils.INSTANCE.writeJson(node)); + byte[] serialized = s.serialize(raw); + RawJson deserialized = s.deserialize(serialized, RawJson.class); + assertThat(deserialized).isEqualTo(raw); + } + + @ParameterizedTest + @EnumSource(ContentType.class) + void rawBytesSerde(ContentType type) { + InternalSerde s = new InternalSerdeProvider().of(type); + ObjectNode node = JsonNodeFactory.instance.objectNode().put("foo", "bar"); + RawBytes raw = RawBytes.of(s.serialize(node)); + byte[] serialized = s.serialize(raw); + RawBytes deserialized = s.deserialize(serialized, RawBytes.class); + assertThat(deserialized).isEqualTo(raw); + } + +} diff --git a/src/main/java/com/arangodb/util/MapBuilder.java b/driver/src/test/java/com/arangodb/util/MapBuilder.java similarity index 96% rename from src/main/java/com/arangodb/util/MapBuilder.java rename to driver/src/test/java/com/arangodb/util/MapBuilder.java index 955bbe24e..61d05865e 100644 --- a/src/main/java/com/arangodb/util/MapBuilder.java +++ b/driver/src/test/java/com/arangodb/util/MapBuilder.java @@ -1,46 +1,46 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class MapBuilder { - - private final Map map; - - public MapBuilder() { - super(); - map = new LinkedHashMap<>(); - } - - public MapBuilder put(final String key, final Object value) { - map.put(key, value); - return this; - } - - public Map get() { - return map; - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.util; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author Mark Vollmary + */ +public class MapBuilder { + + private final Map map; + + public MapBuilder() { + super(); + map = new LinkedHashMap<>(); + } + + public MapBuilder put(final String key, final Object value) { + map.put(key, value); + return this; + } + + public Map get() { + return map; + } +} diff --git a/src/test/java/com/arangodb/util/MapBuilderTest.java b/driver/src/test/java/com/arangodb/util/MapBuilderTest.java similarity index 96% rename from src/test/java/com/arangodb/util/MapBuilderTest.java rename to driver/src/test/java/com/arangodb/util/MapBuilderTest.java index 53633d646..0496a685a 100644 --- a/src/test/java/com/arangodb/util/MapBuilderTest.java +++ b/driver/src/test/java/com/arangodb/util/MapBuilderTest.java @@ -1,43 +1,43 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - - -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class MapBuilderTest { - - @Test - void build() { - final Map map = new MapBuilder().put("foo", "bar").get(); - assertThat(map).hasSize(1); - assertThat(map.get("foo")).isNotNull(); - assertThat(map).containsEntry("foo", "bar"); - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.util; + + +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * @author Mark Vollmary + */ +class MapBuilderTest { + + @Test + void build() { + final Map map = new MapBuilder().put("foo", "bar").get(); + assertThat(map).hasSize(1); + assertThat(map.get("foo")).isNotNull(); + assertThat(map).containsEntry("foo", "bar"); + } +} diff --git a/src/test/java/com/arangodb/util/TestUtils.java b/driver/src/test/java/com/arangodb/util/TestUtils.java similarity index 91% rename from src/test/java/com/arangodb/util/TestUtils.java rename to driver/src/test/java/com/arangodb/util/TestUtils.java index 836466429..a8faab73a 100644 --- a/src/test/java/com/arangodb/util/TestUtils.java +++ b/driver/src/test/java/com/arangodb/util/TestUtils.java @@ -43,7 +43,8 @@ private TestUtils() { * <{@param otherMajor}, {@param otherMinor}, {@param otherPatch}> * comparing the corresponding version components in lexicographical order. */ - public static boolean isAtLeastVersion(final String version, final int otherMajor, final int otherMinor, final int otherPatch) { + public static boolean isAtLeastVersion(final String version, final int otherMajor, final int otherMinor, + final int otherPatch) { return compareVersion(version, otherMajor, otherMinor, otherPatch) >= 0; } @@ -52,11 +53,13 @@ public static boolean isAtLeastVersion(final String version, final int otherMajo * <{@param otherMajor}, {@param otherMinor}, {@param otherPatch}> * comparing the corresponding version components in lexicographical order. */ - public static boolean isLessThanVersion(final String version, final int otherMajor, final int otherMinor, final int otherPatch) { + public static boolean isLessThanVersion(final String version, final int otherMajor, final int otherMinor, + final int otherPatch) { return compareVersion(version, otherMajor, otherMinor, otherPatch) < 0; } - private static int compareVersion(final String version, final int otherMajor, final int otherMinor, final int otherPatch) { + private static int compareVersion(final String version, final int otherMajor, final int otherMinor, + final int otherPatch) { String[] parts = version.split("-")[0].split("\\."); int major = Integer.parseInt(parts[0]); diff --git a/src/test/java/com/arangodb/util/UnicodeUtilsTest.java b/driver/src/test/java/graalvm/UnicodeUtilsTest.java similarity index 95% rename from src/test/java/com/arangodb/util/UnicodeUtilsTest.java rename to driver/src/test/java/graalvm/UnicodeUtilsTest.java index c4b21b6de..66cbbff39 100644 --- a/src/test/java/com/arangodb/util/UnicodeUtilsTest.java +++ b/driver/src/test/java/graalvm/UnicodeUtilsTest.java @@ -1,6 +1,8 @@ -package com.arangodb.util; +package graalvm; import com.arangodb.internal.util.EncodeUtils; +import com.arangodb.util.TestUtils; +import com.arangodb.util.UnicodeUtils; import org.graalvm.home.Version; import org.graalvm.nativeimage.ImageInfo; import org.graalvm.polyglot.Context; @@ -16,11 +18,11 @@ class UnicodeUtilsTest { + private static final String encodeFn = "(function encode(x){return encodeURIComponent(x);})"; + private static final String normalizeFn = "(function normalize(x){return x.normalize('NFC');})"; private static Context context; private static Value jsEncoder; private static Value jsNormalizer; - private static final String encodeFn = "(function encode(x){return encodeURIComponent(x);})"; - private static final String normalizeFn = "(function normalize(x){return x.normalize('NFC');})"; @BeforeAll static void beforeClass() { diff --git a/driver/src/test/java/helper/NativeImageHelper.java b/driver/src/test/java/helper/NativeImageHelper.java new file mode 100644 index 000000000..0b3b51c64 --- /dev/null +++ b/driver/src/test/java/helper/NativeImageHelper.java @@ -0,0 +1,92 @@ +package helper; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.reflections.Reflections; +import org.reflections.scanners.SubTypesScanner; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; +import org.reflections.util.FilterBuilder; + +import java.net.URL; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Stream; + +/** + * Helper scripts to generate GraalVM native image configuration + * + * @author Michele Rastelli + */ +public class NativeImageHelper { + public static void main(String[] args) throws JsonProcessingException { + generateReflectConfig(); + } + + private static void generateReflectConfig() throws JsonProcessingException { + System.out.println("---------------------------"); + System.out.println("--- reflect-config.json ---"); + System.out.println("---------------------------"); + + List packages = Arrays.asList( + "com.arangodb.entity", + "com.arangodb.model", + "com.arangodb.internal.cursor.entity" + ); + + ObjectMapper mapper = new ObjectMapper(); + ArrayNode rootNode = mapper.createArrayNode(); + + String internalSerdePackage = "com.arangodb.internal.serde"; + Collection serdeUrls = ClasspathHelper.forPackage(internalSerdePackage); + Reflections r = new Reflections(new ConfigurationBuilder() + .setScanners(new SubTypesScanner(false)) + .setUrls(serdeUrls) + .filterInputsBy(new FilterBuilder().includePackage(internalSerdePackage))); + Stream serializers = r.getSubTypesOf(JsonSerializer.class).stream() + .filter(it -> !it.isAnonymousClass()) + .map(Class::getName); + Stream deserializers = r.getSubTypesOf(JsonDeserializer.class).stream() + .filter(it -> !it.isAnonymousClass()) + .map(Class::getName); + Stream serdeClasses = Stream.concat(serializers, deserializers) + .filter(it -> it.contains("InternalSerializers") || it.contains("InternalDeserializers")); + + Stream entityClasses = packages.stream() + .flatMap(p -> { + final ConfigurationBuilder config = new ConfigurationBuilder() + .setScanners(new SubTypesScanner(false)) + .setUrls(ClasspathHelper.forPackage(p)) + .filterInputsBy(new FilterBuilder().includePackage(p)); + + Reflections reflections = new Reflections(config); + return Stream.concat( + reflections.getAllTypes().stream(), + reflections + .getSubTypesOf(Enum.class) + .stream() + .map(Class::getName) + ); + }); + Stream.concat(serdeClasses, entityClasses) + .filter(className -> className.startsWith("com.arangodb")) + .map(className -> { + ObjectNode entry = mapper.createObjectNode(); + entry.put("name", className); + entry.put("allDeclaredFields", true); + entry.put("allDeclaredMethods", true); + entry.put("allDeclaredConstructors", true); + return entry; + }) + .forEach(rootNode::add); + + String jsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode); + System.out.println(jsonString); + } +} diff --git a/driver/src/test/java/mp/ArangoConfigPropertiesMPImpl.java b/driver/src/test/java/mp/ArangoConfigPropertiesMPImpl.java new file mode 100644 index 000000000..21f6fe850 --- /dev/null +++ b/driver/src/test/java/mp/ArangoConfigPropertiesMPImpl.java @@ -0,0 +1,147 @@ +package mp; + +import com.arangodb.Protocol; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.HostDescription; +import com.arangodb.entity.LoadBalancingStrategy; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +/** + * Implementation of ArangoConfigProperties compatible with MicroProfile Config. + */ +public final class ArangoConfigPropertiesMPImpl implements ArangoConfigProperties { + private Optional> hosts; + private Optional protocol; + private Optional user; + private Optional password; + private Optional jwt; + private Optional timeout; + private Optional useSsl; + private Optional verifyHost; + private Optional chunkSize; + private Optional maxConnections; + private Optional connectionTtl; + private Optional keepAliveInterval; + private Optional acquireHostList; + private Optional acquireHostListInterval; + private Optional loadBalancingStrategy; + private Optional responseQueueTimeSamples; + + @Override + public Optional> getHosts() { + return hosts; + } + + @Override + public Optional getProtocol() { + return protocol; + } + + @Override + public Optional getUser() { + return user; + } + + @Override + public Optional getPassword() { + return password; + } + + @Override + public Optional getJwt() { + return jwt; + } + + @Override + public Optional getTimeout() { + return timeout; + } + + @Override + public Optional getUseSsl() { + return useSsl; + } + + @Override + public Optional getVerifyHost() { + return verifyHost; + } + + @Override + public Optional getChunkSize() { + return chunkSize; + } + + @Override + public Optional getMaxConnections() { + return maxConnections; + } + + @Override + public Optional getConnectionTtl() { + return connectionTtl; + } + + @Override + public Optional getKeepAliveInterval() { + return keepAliveInterval; + } + + @Override + public Optional getAcquireHostList() { + return acquireHostList; + } + + @Override + public Optional getAcquireHostListInterval() { + return acquireHostListInterval; + } + + @Override + public Optional getLoadBalancingStrategy() { + return loadBalancingStrategy; + } + + @Override + public Optional getResponseQueueTimeSamples() { + return responseQueueTimeSamples; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ArangoConfigPropertiesMPImpl that = (ArangoConfigPropertiesMPImpl) o; + return Objects.equals(hosts, that.hosts) && Objects.equals(protocol, that.protocol) && Objects.equals(user, that.user) && Objects.equals(password, that.password) && Objects.equals(jwt, that.jwt) && Objects.equals(timeout, that.timeout) && Objects.equals(useSsl, that.useSsl) && Objects.equals(verifyHost, that.verifyHost) && Objects.equals(chunkSize, that.chunkSize) && Objects.equals(maxConnections, that.maxConnections) && Objects.equals(connectionTtl, that.connectionTtl) && Objects.equals(keepAliveInterval, that.keepAliveInterval) && Objects.equals(acquireHostList, that.acquireHostList) && Objects.equals(acquireHostListInterval, that.acquireHostListInterval) && Objects.equals(loadBalancingStrategy, that.loadBalancingStrategy) && Objects.equals(responseQueueTimeSamples, that.responseQueueTimeSamples); + } + + @Override + public int hashCode() { + return Objects.hash(hosts, protocol, user, password, jwt, timeout, useSsl, verifyHost, chunkSize, maxConnections, connectionTtl, keepAliveInterval, acquireHostList, acquireHostListInterval, loadBalancingStrategy, responseQueueTimeSamples); + } + + @Override + public String toString() { + return "ArangoConfigPropertiesImpl{" + + "hosts=" + hosts + + ", protocol=" + protocol + + ", user=" + user + + ", password=" + password + + ", jwt=" + jwt + + ", timeout=" + timeout + + ", useSsl=" + useSsl + + ", verifyHost=" + verifyHost + + ", chunkSize=" + chunkSize + + ", maxConnections=" + maxConnections + + ", connectionTtl=" + connectionTtl + + ", keepAliveInterval=" + keepAliveInterval + + ", acquireHostList=" + acquireHostList + + ", acquireHostListInterval=" + acquireHostListInterval + + ", loadBalancingStrategy=" + loadBalancingStrategy + + ", responseQueueTimeSamples=" + responseQueueTimeSamples + + '}'; + } +} diff --git a/driver/src/test/java/mp/ConfigMPDefaultsTest.java b/driver/src/test/java/mp/ConfigMPDefaultsTest.java new file mode 100644 index 000000000..5e32807c2 --- /dev/null +++ b/driver/src/test/java/mp/ConfigMPDefaultsTest.java @@ -0,0 +1,37 @@ +package mp; + +import com.arangodb.config.ArangoConfigProperties; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledInNativeImage; + +import static org.assertj.core.api.Assertions.assertThat; + +@DisabledInNativeImage +class ConfigMPDefaultsTest { + + @Test + void defaultValues() { + ArangoConfigProperties config = ConfigUtilsMP.loadConfigMP("arangodb.properties", "wrong"); + checkResult(config); + } + + private void checkResult(ArangoConfigProperties config) { + assertThat(config.getHosts()).isEmpty(); + assertThat(config.getProtocol()).isEmpty(); + assertThat(config.getUser()).isEmpty(); + assertThat(config.getPassword()).isNotPresent(); + assertThat(config.getJwt()).isNotPresent(); + assertThat(config.getTimeout()).isEmpty(); + assertThat(config.getUseSsl()).isEmpty(); + assertThat(config.getVerifyHost()).isEmpty(); + assertThat(config.getChunkSize()).isEmpty(); + assertThat(config.getMaxConnections()).isNotPresent(); + assertThat(config.getConnectionTtl()).isNotPresent(); + assertThat(config.getKeepAliveInterval()).isNotPresent(); + assertThat(config.getAcquireHostList()).isEmpty(); + assertThat(config.getAcquireHostListInterval()).isEmpty(); + assertThat(config.getLoadBalancingStrategy()).isEmpty(); + assertThat(config.getResponseQueueTimeSamples()).isEmpty(); + } + +} diff --git a/driver/src/test/java/mp/ConfigMPTest.java b/driver/src/test/java/mp/ConfigMPTest.java new file mode 100644 index 000000000..c26c26171 --- /dev/null +++ b/driver/src/test/java/mp/ConfigMPTest.java @@ -0,0 +1,70 @@ +package mp; + +import com.arangodb.Protocol; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.config.HostDescription; +import com.arangodb.entity.LoadBalancingStrategy; +import org.assertj.core.api.InstanceOfAssertFactories; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledInNativeImage; + +import static org.assertj.core.api.Assertions.assertThat; + +@DisabledInNativeImage +class ConfigMPTest { + private final HostDescription hostA = new HostDescription("aaa", 1111); + private final HostDescription hostB = new HostDescription("bbb", 2222); + private final Protocol protocol = Protocol.HTTP_VPACK; + private final String user = "testUser"; + private final String password = "testPassword"; + private final String jwt = "testJwt"; + private final Integer timeout = 9876; + private final Boolean useSsl = true; + private final Boolean verifyHost = false; + private final Integer vstChunkSize = 1234; + private final Integer maxConnections = 123; + private final Long connectionTtl = 12345L; + private final Integer keepAliveInterval = 123456; + private final Boolean acquireHostList = true; + private final Integer acquireHostListInterval = 1234567; + private final LoadBalancingStrategy loadBalancingStrategy = LoadBalancingStrategy.ROUND_ROBIN; + private final Integer responseQueueTimeSamples = 12345678; + + @Test + void readConfig() { + ArangoConfigProperties config = ConfigUtilsMP.loadConfigMP("arangodb-config-test.properties", "adb"); + checkResult(config); + } + + private void checkResult(ArangoConfigProperties config) { + assertThat(config.getHosts()) + .isPresent() + .get(InstanceOfAssertFactories.LIST) + .containsExactly(hostA, hostB); + assertThat(config.getProtocol()).hasValue(protocol); + assertThat(config.getUser()).hasValue(user); + assertThat(config.getPassword()) + .isPresent() + .hasValue(password); + assertThat(config.getJwt()) + .isPresent() + .hasValue(jwt); + assertThat(config.getTimeout()).hasValue(timeout); + assertThat(config.getUseSsl()).hasValue(useSsl); + assertThat(config.getVerifyHost()).hasValue(verifyHost); + assertThat(config.getChunkSize()).hasValue(vstChunkSize); + assertThat(config.getMaxConnections()) + .isPresent() + .hasValue(maxConnections); + assertThat(config.getConnectionTtl()) + .isPresent() + .hasValue(connectionTtl); + assertThat(config.getKeepAliveInterval()) + .isPresent() + .hasValue(keepAliveInterval); + assertThat(config.getAcquireHostList()).hasValue(acquireHostList); + assertThat(config.getAcquireHostListInterval()).hasValue(acquireHostListInterval); + assertThat(config.getLoadBalancingStrategy()).hasValue(loadBalancingStrategy); + assertThat(config.getResponseQueueTimeSamples()).hasValue(responseQueueTimeSamples); + } +} diff --git a/driver/src/test/java/mp/ConfigUtilsMP.java b/driver/src/test/java/mp/ConfigUtilsMP.java new file mode 100644 index 000000000..dabd62cde --- /dev/null +++ b/driver/src/test/java/mp/ConfigUtilsMP.java @@ -0,0 +1,26 @@ +package mp; + +import com.arangodb.config.ArangoConfigProperties; +import io.smallrye.config.PropertiesConfigSourceProvider; +import io.smallrye.config.SmallRyeConfig; +import io.smallrye.config.SmallRyeConfigBuilder; + +public class ConfigUtilsMP { + + public static ArangoConfigProperties loadConfigMP() { + return loadConfigMP("arangodb.properties"); + } + + public static ArangoConfigProperties loadConfigMP(final String location) { + return loadConfigMP(location, "arangodb"); + } + + public static ArangoConfigProperties loadConfigMP(final String location, final String prefix) { + SmallRyeConfig cfg = new SmallRyeConfigBuilder() + .withSources(new PropertiesConfigSourceProvider(location, ConfigUtilsMP.class.getClassLoader(), false)) + .withMapping(ArangoConfigPropertiesMPImpl.class, prefix) + .build(); + return cfg.getConfigMapping(ArangoConfigPropertiesMPImpl.class, prefix); + } + +} diff --git a/driver/src/test/java/perf/Benchmark.java b/driver/src/test/java/perf/Benchmark.java new file mode 100644 index 000000000..8fade9e17 --- /dev/null +++ b/driver/src/test/java/perf/Benchmark.java @@ -0,0 +1,123 @@ +package perf; + +import java.util.Date; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +public abstract class Benchmark { + + private static final int SYNC_THREADS = 128; + private final CountDownLatch completed = new CountDownLatch(1); + private volatile Long startTime = null; + private volatile Long endTime = null; + private volatile int targetCount = Integer.MAX_VALUE; + private final AtomicInteger counter = new AtomicInteger(); + private final ExecutorService es = Executors.newFixedThreadPool(SYNC_THREADS); + private final int warmupDurationSeconds; + private final int numberOfRequests; + + public Benchmark(int warmupDurationSeconds, int numberOfRequests) { + this.warmupDurationSeconds = warmupDurationSeconds; + this.numberOfRequests = numberOfRequests; + } + + public void run() { + // warmup + startBenchmark(); + + // start monitor / warmup + startMonitor(); + + // start benchmark + startMeasuring(); + } + + private void startMonitor() { + for (int i = 0; i < warmupDurationSeconds; i++) { + counter.set(0); + long start = new Date().getTime(); + try { + Thread.sleep(1_000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + long current = new Date().getTime(); + long elapsed = current - start; + double reqsPerSec = 1_000.0 * counter.get() / elapsed; + System.out.println("reqs/s: \t" + reqsPerSec); + } + } + + private void startBenchmark() { + start(); + new Thread(() -> { + try { + completed.await(); + // wait graceful shutdown + Thread.sleep(1_000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // force shutdown + es.shutdown(); + shutdown(); + }).start(); + } + + private void startMeasuring() { + counter.set(0); + targetCount = numberOfRequests; + startTime = System.currentTimeMillis(); + } + + public long waitComplete() { + try { + completed.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return endTime - startTime; + } + + /** + * @return req/s + */ + public long getThroughput() { + return targetCount * 1000L / (endTime - startTime); + } + + /** + * notify the success of #count requests + * + * @return whether more requests should be performed + */ + private boolean success() { + if (endTime != null) return false; + if (counter.addAndGet(1) >= targetCount) { + endTime = System.currentTimeMillis(); + completed.countDown(); + return false; + } + return true; + } + + private void start() { + for (int i = 0; i < SYNC_THREADS; i++) { + es.execute(() -> { + boolean more = true; + while (more) { + sendRequest(); + more = success(); + } + }); + } + } + + protected abstract void sendRequest(); + + protected abstract void shutdown(); + +} diff --git a/src/test/java/perf/SimpleSyncPerfTest.java b/driver/src/test/java/perf/SimpleSyncPerfTest.java similarity index 95% rename from src/test/java/perf/SimpleSyncPerfTest.java rename to driver/src/test/java/perf/SimpleSyncPerfTest.java index e801659ab..2d230779f 100644 --- a/src/test/java/perf/SimpleSyncPerfTest.java +++ b/driver/src/test/java/perf/SimpleSyncPerfTest.java @@ -22,7 +22,6 @@ import com.arangodb.ArangoDB; import com.arangodb.Protocol; -import com.arangodb.mapping.ArangoJack; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -45,7 +44,7 @@ private void doGetVersion(ArangoDB arangoDB) { @ParameterizedTest @EnumSource(Protocol.class) void getVersion(Protocol protocol) throws InterruptedException { - ArangoDB arangoDB = new ArangoDB.Builder().useProtocol(protocol).serializer(new ArangoJack()).build(); + ArangoDB arangoDB = new ArangoDB.Builder().useProtocol(protocol).build(); // warmup doGetVersion(arangoDB); diff --git a/driver/src/test/java/perf/SyncBenchmarkTest.java b/driver/src/test/java/perf/SyncBenchmarkTest.java new file mode 100644 index 000000000..f30ef331a --- /dev/null +++ b/driver/src/test/java/perf/SyncBenchmarkTest.java @@ -0,0 +1,71 @@ +package perf; + +import com.arangodb.ArangoDB; +import com.arangodb.DbName; +import com.arangodb.Protocol; +import com.arangodb.Request; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +@Disabled +public class SyncBenchmarkTest { + private final int warmupDurationSeconds = 15; + private final int numberOfRequests = 1_000_000; + + @ParameterizedTest + @EnumSource(Protocol.class) + void getVersion(Protocol protocol) { + System.out.println("-----------------------------------------"); + System.out.println("--- getVersion(): " + protocol); + System.out.println("-----------------------------------------"); + + ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).build(); + Benchmark benchmark = new Benchmark(warmupDurationSeconds, numberOfRequests) { + @Override + protected void sendRequest() { + adb.getVersion(); + } + + @Override + protected void shutdown() { + adb.shutdown(); + } + }; + benchmark.run(); + System.out.println("elapsed time [ms]: \t" + benchmark.waitComplete()); + System.out.println("throughput [req/s]: \t" + benchmark.getThroughput()); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void getVersionWithDetails(Protocol protocol) { + System.out.println("-----------------------------------------"); + System.out.println("--- getVersion w/ details: " + protocol); + System.out.println("-----------------------------------------"); + + ArangoDB adb = new ArangoDB.Builder().useProtocol(protocol).build(); + Benchmark benchmark = new Benchmark(warmupDurationSeconds, numberOfRequests) { + private final Request request = Request.builder() + .db(DbName.SYSTEM) + .method(Request.Method.GET) + .path("/_api/version") + .queryParam("details", "true") + .build(); + + @Override + protected void sendRequest() { + adb.execute(request, Void.class); + } + + @Override + protected void shutdown() { + adb.shutdown(); + } + }; + benchmark.run(); + System.out.println("elapsed time [ms]: \t" + benchmark.waitComplete()); + System.out.println("throughput [req/s]: \t" + benchmark.getThroughput()); + } + +} diff --git a/driver/src/test/resources/META-INF/native-image/native-image.properties b/driver/src/test/resources/META-INF/native-image/native-image.properties new file mode 100644 index 000000000..b039368e7 --- /dev/null +++ b/driver/src/test/resources/META-INF/native-image/native-image.properties @@ -0,0 +1,8 @@ +Args=\ + -H:ResourceConfigurationResources=${.}/resource-config.json \ + -H:ReflectionConfigurationResources=${.}/reflect-config.json \ + -H:SerializationConfigurationResources=${.}/serialization-config.json \ + --initialize-at-build-time=\ + ch.qos.logback,\ + org.slf4j,\ + org.junit.platform.engine.TestTag diff --git a/driver/src/test/resources/META-INF/native-image/reflect-config.json b/driver/src/test/resources/META-INF/native-image/reflect-config.json new file mode 100644 index 000000000..e8a1f86bc --- /dev/null +++ b/driver/src/test/resources/META-INF/native-image/reflect-config.json @@ -0,0 +1,359 @@ +[ + { + "name":"org.junit.jupiter.engine.extension.TimeoutInvocationFactory$SingleThreadExecutorResource", + "methods":[{"name":"","parameterTypes":[] }] + }, + { + "name": "org.junit.jupiter.engine.extension.TimeoutInvocationFactory$SingleThreadExecutorResource", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.encoder.PatternLayoutEncoder", + "allPublicMethods": true, + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.pattern.DateConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.pattern.LevelConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.pattern.LineSeparatorConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.pattern.LoggerConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.pattern.MessageConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.classic.pattern.ThreadConverter", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "ch.qos.logback.core.ConsoleAppender", + "allPublicMethods": true, + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.arangodb.ArangoCollectionTest$TestUpdateEntity", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name": "com.arangodb.ArangoCollectionTest$TestUpdateEntitySerializeNullFalse", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name": "com.arangodb.ArangoDatabaseTest$TransactionTestEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.ArangoDatabaseTest$TransactionTestEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.document.AqlQueryWithSpecialReturnTypesExampleTest$Gender", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.document.TestEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.graph.AQLActorsAndMoviesExampleTest$Actor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.graph.AQLActorsAndMoviesExampleTest$Movie", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.graph.Circle", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.graph.CircleEdge", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.async.example.graph.ShortestPathInAQLExampleTest$Pair", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.document.AqlQueryWithSpecialReturnTypesExampleTest$Gender", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.document.TestEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.graph.AQLActorsAndMoviesExampleTest$Actor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.graph.AQLActorsAndMoviesExampleTest$Movie", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.graph.Circle", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.graph.CircleEdge", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.example.graph.ShortestPathInAQLExampleTest$Pair", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.serde.CustomSerdeTest$Person", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.serde.CustomSerdeTest$PersonDeserializer", + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.serde.CustomSerdeTest$PersonSerializer", + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.arangodb.serde.CustomTypeHintTest$Animal", + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.serde.CustomTypeHintTest$Gorilla", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "com.arangodb.serde.CustomTypeHintTest$Zoo", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredConstructors": true, + "allDeclaredClasses": true + }, + { + "name": "java.util.HashSet", + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.mapping.annotations.AnnotatedEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.fasterxml.jackson.databind.deser.std.DateDeserializers$SqlDateDeserializer", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.fasterxml.jackson.databind.ser.std.SqlDateSerializer", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name":"com.arangodb.async.ArangoCollectionTest$Animal", + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.async.ArangoCollectionTest$Cat", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.async.ArangoCollectionTest$Dog", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.ArangoCollectionTest$Animal", + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.ArangoCollectionTest$AnnotatedEntity", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.ArangoCollectionTest$Cat", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + }, + { + "name":"com.arangodb.ArangoCollectionTest$Dog", + "allDeclaredFields":true, + "allDeclaredMethods":true, + "allPublicMethods":true, + "allDeclaredConstructors":true, + "allDeclaredClasses":true + } +] diff --git a/src/test/resources/META-INF/native-image/resource-config.json b/driver/src/test/resources/META-INF/native-image/resource-config.json similarity index 83% rename from src/test/resources/META-INF/native-image/resource-config.json rename to driver/src/test/resources/META-INF/native-image/resource-config.json index a603a885a..a6eea307e 100644 --- a/src/test/resources/META-INF/native-image/resource-config.json +++ b/driver/src/test/resources/META-INF/native-image/resource-config.json @@ -10,6 +10,9 @@ { "pattern": "\\Qarangodb-bad2.properties\\E" }, + { + "pattern":"\\Qarangodb-with-prefix.properties\\E" + }, { "pattern": "\\Qlogback-test.xml\\E" }, diff --git a/driver/src/test/resources/META-INF/native-image/serialization-config.json b/driver/src/test/resources/META-INF/native-image/serialization-config.json new file mode 100644 index 000000000..8c832f7ba --- /dev/null +++ b/driver/src/test/resources/META-INF/native-image/serialization-config.json @@ -0,0 +1,26 @@ +[ + { + "name": "java.lang.Exception" + }, + { + "name": "java.lang.RuntimeException" + }, + { + "name": "java.lang.StackTraceElement" + }, + { + "name": "java.lang.StackTraceElement[]" + }, + { + "name": "java.lang.String" + }, + { + "name": "java.lang.Throwable" + }, + { + "name": "java.util.Collections$EmptyList" + }, + { + "name": "java.util.Collections$SingletonList" + } +] diff --git a/src/test/resources/arangodb-bad.properties b/driver/src/test/resources/arangodb-bad.properties similarity index 100% rename from src/test/resources/arangodb-bad.properties rename to driver/src/test/resources/arangodb-bad.properties diff --git a/driver/src/test/resources/arangodb-config-test.properties b/driver/src/test/resources/arangodb-config-test.properties new file mode 100644 index 000000000..48fe4f1ed --- /dev/null +++ b/driver/src/test/resources/arangodb-config-test.properties @@ -0,0 +1,17 @@ +adb.hosts=aaa:1111,bbb:2222 +adb.protocol=HTTP_VPACK +adb.user=testUser +adb.password=testPassword +adb.jwt=testJwt +adb.timeout=9876 +adb.useSsl=true +adb.verifyHost=false +adb.chunkSize=1234 +adb.maxConnections=123 +adb.connectionTtl=12345 +adb.keepAliveInterval=123456 +adb.acquireHostList=true +adb.acquireHostListInterval=1234567 +adb.loadBalancingStrategy=ROUND_ROBIN +adb.responseQueueTimeSamples=12345678 + diff --git a/driver/src/test/resources/arangodb-with-prefix.properties b/driver/src/test/resources/arangodb-with-prefix.properties new file mode 100644 index 000000000..36fb2d0a5 --- /dev/null +++ b/driver/src/test/resources/arangodb-with-prefix.properties @@ -0,0 +1,3 @@ +adb.hosts=172.28.0.1:8529 +adb.acquireHostList=true +adb.password=test diff --git a/src/test/resources/arangodb.properties b/driver/src/test/resources/arangodb.properties similarity index 59% rename from src/test/resources/arangodb.properties rename to driver/src/test/resources/arangodb.properties index 54638964b..fa580e439 100644 --- a/src/test/resources/arangodb.properties +++ b/driver/src/test/resources/arangodb.properties @@ -1,6 +1,5 @@ arangodb.hosts=172.28.0.1:8529 -arangodb.connections.max=20 arangodb.acquireHostList=true arangodb.password=test arangodb.timeout=30000 -arangodb.metrics.responseQueueTimeSamples=20 +arangodb.responseQueueTimeSamples=20 diff --git a/src/test/resources/example.truststore b/driver/src/test/resources/example.truststore similarity index 100% rename from src/test/resources/example.truststore rename to driver/src/test/resources/example.truststore diff --git a/src/test/resources/logback-test.xml b/driver/src/test/resources/logback-test.xml similarity index 92% rename from src/test/resources/logback-test.xml rename to driver/src/test/resources/logback-test.xml index f67855e9c..b1d65b196 100644 --- a/src/test/resources/logback-test.xml +++ b/driver/src/test/resources/logback-test.xml @@ -12,6 +12,7 @@ + diff --git a/formatter.xml b/formatter.xml deleted file mode 100644 index 0485cd4ba..000000000 --- a/formatter.xml +++ /dev/null @@ -1,419 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/http/pom.xml b/http/pom.xml new file mode 100644 index 000000000..10e710bb7 --- /dev/null +++ b/http/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + + com.arangodb + arangodb-java-driver-parent + 7.0.0-ALPHA.2 + + + http-protocol + http-protocol + HTTP Protocol module for ArangoDB Java Driver + + + false + com.arangodb.http + + + + + com.arangodb + core + provided + + + io.vertx + vertx-web-client + + + + + + + io.vertx + vertx-stack-depchain + 4.3.5 + pom + import + + + io.netty + netty-bom + 4.1.85.Final + pom + import + + + + \ No newline at end of file diff --git a/src/main/java/com/arangodb/internal/http/HttpCommunication.java b/http/src/main/java/com/arangodb/http/HttpCommunication.java similarity index 56% rename from src/main/java/com/arangodb/internal/http/HttpCommunication.java rename to http/src/main/java/com/arangodb/http/HttpCommunication.java index dcb840ce1..fafc1b721 100644 --- a/src/main/java/com/arangodb/internal/http/HttpCommunication.java +++ b/http/src/main/java/com/arangodb/http/HttpCommunication.java @@ -18,15 +18,18 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.http; +package com.arangodb.http; import com.arangodb.ArangoDBException; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.RequestType; +import com.arangodb.internal.InternalResponse; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.*; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.HostUtils; import com.arangodb.internal.util.RequestUtils; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,6 +37,7 @@ import java.io.IOException; import java.net.SocketTimeoutException; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicLong; /** * @author Mark Vollmary @@ -41,30 +45,15 @@ public class HttpCommunication implements Closeable { private static final Logger LOGGER = LoggerFactory.getLogger(HttpCommunication.class); - - public static class Builder { - - private final HostHandler hostHandler; - - public Builder(final HostHandler hostHandler) { - super(); - this.hostHandler = hostHandler; - } - - public Builder(final Builder builder) { - this(builder.hostHandler); - } - - public HttpCommunication build(final ArangoSerialization util) { - return new HttpCommunication(hostHandler); - } - } - private final HostHandler hostHandler; + private final InternalSerde serde; + private final AtomicLong reqCount; - private HttpCommunication(final HostHandler hostHandler) { + HttpCommunication(final HostHandler hostHandler, final ArangoConfig config) { super(); this.hostHandler = hostHandler; + this.serde = config.getInternalSerde(); + reqCount = new AtomicLong(); } @Override @@ -72,28 +61,35 @@ public void close() throws IOException { hostHandler.close(); } - public Response execute(final Request request, final HostHandle hostHandle) throws ArangoDBException { + public InternalResponse execute(final InternalRequest request, final HostHandle hostHandle) { return execute(request, hostHandle, 0); } - private Response execute(final Request request, final HostHandle hostHandle, final int attemptCount) throws ArangoDBException { + private InternalResponse execute(final InternalRequest request, final HostHandle hostHandle, final int attemptCount) { final AccessType accessType = RequestUtils.determineAccessType(request); Host host = hostHandler.get(hostHandle, accessType); try { while (true) { + long reqId = reqCount.getAndIncrement(); try { final HttpConnection connection = (HttpConnection) host.connection(); - final Response response = connection.execute(request); + if (LOGGER.isDebugEnabled()) { + String body = request.getBody() == null ? "" : serde.toJsonString(request.getBody()); + LOGGER.debug("Send Request [id={}]: {} {}", reqId, request, body); + } + final InternalResponse response = connection.execute(request); + if (LOGGER.isDebugEnabled()) { + String body = response.getBody() == null ? "" : serde.toJsonString(response.getBody()); + LOGGER.debug("Received Response [id={}]: {} {}", reqId, response, body); + } hostHandler.success(); hostHandler.confirm(); return response; } catch (final SocketTimeoutException e) { // SocketTimeoutException exceptions are wrapped and rethrown. - // Differently from other IOException exceptions they must not be retried, - // since the requests could not be idempotent. TimeoutException te = new TimeoutException(e.getMessage()); te.initCause(e); - throw new ArangoDBException(te); + throw new ArangoDBException(te, reqId); } catch (final IOException e) { hostHandler.fail(e); if (hostHandle != null && hostHandle.getHost() != null) { @@ -101,19 +97,19 @@ private Response execute(final Request request, final HostHandle hostHandle, fin } final Host failedHost = host; host = hostHandler.get(hostHandle, accessType); - if (host != null) { - LOGGER.warn(String.format("Could not connect to %s", failedHost.getDescription()), e); - LOGGER.warn(String.format("Could not connect to %s. Try connecting to %s", - failedHost.getDescription(), host.getDescription())); + if (host != null && isSafe(request)) { + LOGGER.warn("Could not connect to {} while executing request [id={}]", + failedHost.getDescription(), reqId, e); + LOGGER.debug("Try connecting to {}", host.getDescription()); } else { LOGGER.error(e.getMessage(), e); - throw new ArangoDBException(e); + throw new ArangoDBException(e, reqId); } } } - } catch (final ArangoDBException e) { - if (e instanceof ArangoDBRedirectException && attemptCount < 3) { - final String location = ((ArangoDBRedirectException) e).getLocation(); + } catch (final ArangoDBRedirectException e) { + if (attemptCount < 3) { + final String location = e.getLocation(); final HostDescription redirectHost = HostUtils.createFromLocation(location); hostHandler.failIfNotMatch(redirectHost, e); return execute(request, new HostHandle().setHost(redirectHost), attemptCount + 1); @@ -123,4 +119,9 @@ private Response execute(final Request request, final HostHandle hostHandle, fin } } + private boolean isSafe(final InternalRequest request) { + RequestType type = request.getRequestType(); + return type == RequestType.GET || type == RequestType.HEAD || type == RequestType.OPTIONS; + } + } diff --git a/http/src/main/java/com/arangodb/http/HttpConnection.java b/http/src/main/java/com/arangodb/http/HttpConnection.java new file mode 100644 index 000000000..5c8d424cf --- /dev/null +++ b/http/src/main/java/com/arangodb/http/HttpConnection.java @@ -0,0 +1,309 @@ +/* + * DISCLAIMER + * + * Copyright 2017 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.http; + +import com.arangodb.*; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.Connection; +import com.arangodb.internal.serde.ContentTypeFactory; +import com.arangodb.internal.serde.InternalSerde; +import com.arangodb.internal.util.EncodeUtils; +import com.arangodb.internal.util.ResponseUtils; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.RequestType; +import com.arangodb.internal.InternalResponse; +import io.netty.handler.ssl.ApplicationProtocolConfig; +import io.netty.handler.ssl.ClientAuth; +import io.netty.handler.ssl.IdentityCipherSuiteFilter; +import io.netty.handler.ssl.JdkSslContext; +import io.vertx.core.Vertx; +import io.vertx.core.VertxOptions; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpHeaders; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.HttpVersion; +import io.vertx.core.net.JdkSSLEngineOptions; +import io.vertx.core.spi.tls.SslContextFactory; +import io.vertx.ext.auth.authentication.TokenCredentials; +import io.vertx.ext.auth.authentication.UsernamePasswordCredentials; +import io.vertx.ext.web.client.HttpRequest; +import io.vertx.ext.web.client.HttpResponse; +import io.vertx.ext.web.client.WebClient; +import io.vertx.ext.web.client.WebClientOptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; + + +/** + * @author Mark Vollmary + * @author Michele Rastelli + */ +public class HttpConnection implements Connection { + private static final Logger LOGGER = LoggerFactory.getLogger(HttpConnection.class); + private static final String CONTENT_TYPE_APPLICATION_JSON_UTF8 = "application/json; charset=utf-8"; + private static final String CONTENT_TYPE_VPACK = "application/x-velocypack"; + private static final String USER_AGENT = getUserAgent(); + private static final AtomicInteger THREAD_COUNT = new AtomicInteger(); + private final InternalSerde serde; + private final ContentType contentType; + private String auth; + private final WebClient client; + private final Integer timeout; + private final Vertx vertx; + + private static String getUserAgent() { + return "JavaDriver/" + PackageVersion.VERSION + " (JVM/" + System.getProperty("java.specification.version") + ")"; + } + + HttpConnection(final ArangoConfig config, final HostDescription host) { + super(); + serde = config.getInternalSerde(); + Protocol protocol = config.getProtocol(); + contentType = ContentTypeFactory.of(protocol); + timeout = config.getTimeout(); + vertx = Vertx.vertx(new VertxOptions().setPreferNativeTransport(true).setEventLoopPoolSize(1)); + vertx.runOnContext(e -> { + Thread.currentThread().setName("adb-eventloop-" + THREAD_COUNT.getAndIncrement()); + auth = new UsernamePasswordCredentials( + config.getUser(), Optional.ofNullable(config.getPassword()).orElse("") + ).toHttpAuthorization(); + LOGGER.debug("Created Vert.x context"); + }); + + int intTtl = Optional.ofNullable(config.getConnectionTtl()) + .map(ttl -> Math.toIntExact(ttl / 1000)) + .orElse(0); + + HttpVersion httpVersion = protocol == Protocol.HTTP_JSON || protocol == Protocol.HTTP_VPACK ? + HttpVersion.HTTP_1_1 : HttpVersion.HTTP_2; + + WebClientOptions webClientOptions = new WebClientOptions() + .setMaxPoolSize(1) + .setHttp2MaxPoolSize(1) + .setConnectTimeout(timeout) + .setIdleTimeoutUnit(TimeUnit.MILLISECONDS) + .setIdleTimeout(timeout) + .setKeepAliveTimeout(intTtl) + .setHttp2KeepAliveTimeout(intTtl) + .setUserAgentEnabled(false) + .setFollowRedirects(false) + .setLogActivity(true) + .setKeepAlive(true) + .setTcpKeepAlive(true) + .setPipelining(true) + .setReuseAddress(true) + .setReusePort(true) + .setHttp2ClearTextUpgrade(false) + .setProtocolVersion(httpVersion) + .setDefaultHost(host.getHost()) + .setDefaultPort(host.getPort()); + + + if (Boolean.TRUE.equals(config.getUseSsl())) { + SSLContext ctx; + if (config.getSslContext() != null) { + ctx = config.getSslContext(); + } else { + try { + ctx = SSLContext.getDefault(); + } catch (NoSuchAlgorithmException e) { + throw new ArangoDBException(e); + } + } + + webClientOptions + .setSsl(true) + .setUseAlpn(true) + .setVerifyHost(config.getVerifyHost()) + .setJdkSslEngineOptions(new JdkSSLEngineOptions() { + @Override + public JdkSSLEngineOptions copy() { + return this; + } + + @Override + public SslContextFactory sslContextFactory() { + return () -> new JdkSslContext( + ctx, + true, + null, + IdentityCipherSuiteFilter.INSTANCE, + ApplicationProtocolConfig.DISABLED, + ClientAuth.NONE, + null, + false + ); + } + }); + } + + client = WebClient.create(vertx, webClientOptions); + } + + private static String buildUrl(final InternalRequest request) { + StringBuilder sb = new StringBuilder(); + DbName dbName = request.getDbName(); + if (dbName != null && !dbName.get().isEmpty()) { + sb.append("/_db/").append(dbName.getEncoded()); + } + sb.append(request.getPath()); + if (!request.getQueryParam().isEmpty()) { + sb.append("?"); + for (Iterator> iterator = request.getQueryParam().entrySet().iterator(); iterator.hasNext(); ) { + Entry param = iterator.next(); + if (param.getValue() != null) { + sb.append(EncodeUtils.encodeURIComponent(param.getKey())); + sb.append("="); + sb.append(EncodeUtils.encodeURIComponent(param.getValue())); + if (iterator.hasNext()) { + sb.append("&"); + } + } + } + } + return sb.toString(); + } + + private static void addHeader(final InternalRequest request, final HttpRequest httpRequest) { + for (final Entry header : request.getHeaderParam().entrySet()) { + httpRequest.putHeader(header.getKey(), header.getValue()); + } + } + + @Override + public void close() { + client.close(); + vertx.close(); + } + + private HttpMethod requestTypeToHttpMethod(RequestType requestType) { + switch (requestType) { + case POST: + return HttpMethod.POST; + case PUT: + return HttpMethod.PUT; + case PATCH: + return HttpMethod.PATCH; + case DELETE: + return HttpMethod.DELETE; + case HEAD: + return HttpMethod.HEAD; + case GET: + default: + return HttpMethod.GET; + } + } + + public InternalResponse execute(final InternalRequest request) throws IOException { + CompletableFuture rfuture = new CompletableFuture<>(); + vertx.runOnContext(e -> doExecute(request, rfuture)); + InternalResponse resp; + try { + resp = rfuture.get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw ArangoDBException.wrap(e); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + if (cause instanceof TimeoutException) { + throw ArangoDBException.wrap(cause); + } else if (cause instanceof IOException) { + throw (IOException) cause; + } else { + throw new IOException(cause); + } + } + checkError(resp); + return resp; + } + + public void doExecute(final InternalRequest request, final CompletableFuture rfuture) { + String path = buildUrl(request); + HttpRequest httpRequest = client + .request(requestTypeToHttpMethod(request.getRequestType()), path) + .timeout(timeout); + if (contentType == ContentType.VPACK) { + httpRequest.putHeader("Accept", CONTENT_TYPE_VPACK); + } + addHeader(request, httpRequest); + httpRequest.putHeader(HttpHeaders.AUTHORIZATION.toString(), auth); + httpRequest.putHeader("x-arango-driver", USER_AGENT); + + byte[] reqBody = request.getBody(); + Buffer buffer; + if (reqBody != null) { + buffer = Buffer.buffer(reqBody); + if (contentType == ContentType.VPACK) { + httpRequest.putHeader(HttpHeaders.CONTENT_TYPE.toString(), CONTENT_TYPE_VPACK); + } else { + httpRequest.putHeader(HttpHeaders.CONTENT_TYPE.toString(), CONTENT_TYPE_APPLICATION_JSON_UTF8); + } + } else { + buffer = Buffer.buffer(); + } + + httpRequest.sendBuffer(buffer) + .map(this::buildResponse) + .onSuccess(rfuture::complete) + .onFailure(rfuture::completeExceptionally); + } + + private InternalResponse buildResponse(final HttpResponse httpResponse) { + final InternalResponse response = new InternalResponse(); + response.setResponseCode(httpResponse.statusCode()); + Buffer body = httpResponse.body(); + if (body != null) { + byte[] bytes = body.getBytes(); + if (bytes.length > 0) { + response.setBody(bytes); + } + } + for (Entry header : httpResponse.headers()) { + response.putMeta(header.getKey(), header.getValue()); + } + return response; + } + + protected void checkError(final InternalResponse response) { + ResponseUtils.checkError(serde, response); + } + + @Override + public void setJwt(String jwt) { + if (jwt != null) { + vertx.runOnContext(e -> auth = new TokenCredentials(jwt).toHttpAuthorization()); + } + } + +} diff --git a/src/main/java/com/arangodb/Predicate.java b/http/src/main/java/com/arangodb/http/HttpConnectionFactory.java similarity index 62% rename from src/main/java/com/arangodb/Predicate.java rename to http/src/main/java/com/arangodb/http/HttpConnectionFactory.java index 4c7257862..4c24c06c1 100644 --- a/src/main/java/com/arangodb/Predicate.java +++ b/http/src/main/java/com/arangodb/http/HttpConnectionFactory.java @@ -18,22 +18,19 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb; +package com.arangodb.http; + +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.Connection; +import com.arangodb.internal.net.ConnectionFactory; /** - * @param the type of the input to the predicate * @author Mark Vollmary - * @deprecated Use {@link java.util.function.Predicate} instead. */ -@Deprecated -public interface Predicate { - - /** - * Evaluates this predicate on the given argument. - * - * @param t the input argument - * @return {@code true} if the input argument matches the predicate, otherwise {@code false} - */ - boolean test(T t); - +public class HttpConnectionFactory implements ConnectionFactory { + @Override + public Connection create(final ArangoConfig config, final HostDescription host) { + return new HttpConnection(config, host); + } } diff --git a/src/main/java/com/arangodb/internal/http/HttpProtocol.java b/http/src/main/java/com/arangodb/http/HttpProtocol.java similarity index 84% rename from src/main/java/com/arangodb/internal/http/HttpProtocol.java rename to http/src/main/java/com/arangodb/http/HttpProtocol.java index c3df748e9..a78f5487f 100644 --- a/src/main/java/com/arangodb/internal/http/HttpProtocol.java +++ b/http/src/main/java/com/arangodb/http/HttpProtocol.java @@ -18,13 +18,12 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.http; +package com.arangodb.http; -import com.arangodb.ArangoDBException; import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; import java.io.IOException; @@ -41,7 +40,7 @@ public HttpProtocol(final HttpCommunication httpCommunitaction) { } @Override - public Response execute(final Request request, final HostHandle hostHandle) throws ArangoDBException { + public InternalResponse execute(final InternalRequest request, final HostHandle hostHandle) { return httpCommunitaction.execute(request, hostHandle); } diff --git a/http/src/main/java/com/arangodb/http/HttpProtocolProvider.java b/http/src/main/java/com/arangodb/http/HttpProtocolProvider.java new file mode 100644 index 000000000..e6bc1d3b9 --- /dev/null +++ b/http/src/main/java/com/arangodb/http/HttpProtocolProvider.java @@ -0,0 +1,36 @@ +package com.arangodb.http; + +import com.arangodb.Protocol; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.CommunicationProtocol; +import com.arangodb.internal.net.ConnectionFactory; +import com.arangodb.internal.net.HostHandler; +import com.arangodb.internal.net.ProtocolProvider; +import com.fasterxml.jackson.databind.Module; + +public class HttpProtocolProvider implements ProtocolProvider { + + @Override + public boolean supportsProtocol(Protocol protocol) { + return Protocol.HTTP_VPACK.equals(protocol) || + Protocol.HTTP_JSON.equals(protocol) || + Protocol.HTTP2_VPACK.equals(protocol) || + Protocol.HTTP2_JSON.equals(protocol); + } + + @Override + public ConnectionFactory createConnectionFactory() { + return new HttpConnectionFactory(); + } + + @Override + public CommunicationProtocol createProtocol(ArangoConfig config, HostHandler hostHandler) { + return new HttpProtocol(new HttpCommunication(hostHandler, config)); + } + + @Override + public Module protocolModule() { + return null; + } + +} diff --git a/http/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider b/http/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider new file mode 100644 index 000000000..f48d178b7 --- /dev/null +++ b/http/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider @@ -0,0 +1 @@ +com.arangodb.http.HttpProtocolProvider diff --git a/http/src/main/resources/META-INF/vertx/vertx-version.txt b/http/src/main/resources/META-INF/vertx/vertx-version.txt new file mode 100644 index 000000000..a6695ff98 --- /dev/null +++ b/http/src/main/resources/META-INF/vertx/vertx-version.txt @@ -0,0 +1 @@ +4.3.4 \ No newline at end of file diff --git a/jackson-serde-json/pom.xml b/jackson-serde-json/pom.xml new file mode 100644 index 000000000..29421c675 --- /dev/null +++ b/jackson-serde-json/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + com.arangodb + arangodb-java-driver-parent + 7.0.0-ALPHA.2 + + + jackson-serde-json + jackson-serde-json + Jackson Serde JSON module for ArangoDB Java Driver + + + false + com.arangodb.serde.jackson.json + + + + + com.arangodb + core + provided + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + + + \ No newline at end of file diff --git a/src/main/java/com/arangodb/entity/From.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/From.java similarity index 70% rename from src/main/java/com/arangodb/entity/From.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/From.java index 056c1e1c6..b84ee1fb0 100644 --- a/src/main/java/com/arangodb/entity/From.java +++ b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/From.java @@ -1,6 +1,5 @@ -package com.arangodb.entity; +package com.arangodb.serde.jackson; -import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; @@ -13,11 +12,10 @@ /** * @author Michele Rastelli */ -// TODO: in v7 add targets ElementType.METHOD and ElementType.PARAMETER -@Target(ElementType.FIELD) +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside -@JsonProperty(DocumentFields.FROM) +@JsonProperty("_from") @JsonInclude(JsonInclude.Include.NON_NULL) public @interface From { } diff --git a/src/main/java/com/arangodb/entity/Id.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Id.java similarity index 70% rename from src/main/java/com/arangodb/entity/Id.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Id.java index f4333438d..ee1033993 100644 --- a/src/main/java/com/arangodb/entity/Id.java +++ b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Id.java @@ -1,6 +1,5 @@ -package com.arangodb.entity; +package com.arangodb.serde.jackson; -import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; @@ -13,11 +12,10 @@ /** * @author Michele Rastelli */ -// TODO: in v7 add targets ElementType.METHOD and ElementType.PARAMETER -@Target(ElementType.FIELD) +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside -@JsonProperty(DocumentFields.ID) +@JsonProperty("_id") @JsonInclude(JsonInclude.Include.NON_NULL) public @interface Id { } diff --git a/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/JacksonSerde.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/JacksonSerde.java new file mode 100644 index 000000000..35e1555ab --- /dev/null +++ b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/JacksonSerde.java @@ -0,0 +1,20 @@ +package com.arangodb.serde.jackson; + +import com.arangodb.serde.ArangoSerde; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.function.Consumer; + +/** + * User data serde based on Jackson Databind. Not shaded in arangodb-java-driver-shaded. + */ +public interface JacksonSerde extends ArangoSerde { + + /** + * Allows configuring the underlying Jackson ObjectMapper + * + * @param configureFunction function to configure the Jackson ObjectMapper + */ + void configure(final Consumer configureFunction); + +} diff --git a/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java new file mode 100644 index 000000000..c2f437e21 --- /dev/null +++ b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/JacksonSerdeProvider.java @@ -0,0 +1,35 @@ +package com.arangodb.serde.jackson; + +import com.arangodb.ContentType; +import com.arangodb.serde.ArangoSerdeProvider; +import com.arangodb.serde.jackson.internal.JacksonMapperProvider; +import com.arangodb.serde.jackson.internal.JacksonSerdeImpl; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JacksonSerdeProvider implements ArangoSerdeProvider { + + /** + * Creates a new JacksonSerde with default settings for the specified data type. + * Registers all the Jackson modules ({@link com.fasterxml.jackson.databind.Module}) discovered via SPI. + * + * @param contentType serialization target data type + * @return the created JacksonSerde + */ + @Override + public JacksonSerde of(final ContentType contentType) { + JacksonSerde serde = create(JacksonMapperProvider.of(contentType)); + serde.configure(mapper -> mapper.registerModules(ObjectMapper.findModules())); + return serde; + } + + /** + * Creates a new JacksonSerde using the provided ObjectMapper. + * + * @param mapper Jackson ObjectMapper to use + * @return the created JacksonSerde + */ + static JacksonSerde create(final ObjectMapper mapper) { + return new JacksonSerdeImpl(mapper); + } + +} diff --git a/src/main/java/com/arangodb/entity/Key.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Key.java similarity index 70% rename from src/main/java/com/arangodb/entity/Key.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Key.java index f510a2c65..94177c44d 100644 --- a/src/main/java/com/arangodb/entity/Key.java +++ b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Key.java @@ -1,6 +1,5 @@ -package com.arangodb.entity; +package com.arangodb.serde.jackson; -import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; @@ -13,11 +12,10 @@ /** * @author Michele Rastelli */ -// TODO: in v7 add targets ElementType.METHOD and ElementType.PARAMETER -@Target(ElementType.FIELD) +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside -@JsonProperty(DocumentFields.KEY) +@JsonProperty("_key") @JsonInclude(JsonInclude.Include.NON_NULL) public @interface Key { } diff --git a/src/main/java/com/arangodb/entity/Rev.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Rev.java similarity index 70% rename from src/main/java/com/arangodb/entity/Rev.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Rev.java index bd5aa7600..764927d6f 100644 --- a/src/main/java/com/arangodb/entity/Rev.java +++ b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/Rev.java @@ -1,6 +1,5 @@ -package com.arangodb.entity; +package com.arangodb.serde.jackson; -import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; @@ -13,11 +12,10 @@ /** * @author Michele Rastelli */ -// TODO: in v7 add targets ElementType.METHOD and ElementType.PARAMETER -@Target(ElementType.FIELD) +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside -@JsonProperty(DocumentFields.REV) +@JsonProperty("_rev") @JsonInclude(JsonInclude.Include.NON_NULL) public @interface Rev { } diff --git a/src/main/java/com/arangodb/entity/To.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/To.java similarity index 70% rename from src/main/java/com/arangodb/entity/To.java rename to jackson-serde-json/src/main/java/com/arangodb/serde/jackson/To.java index a58db8604..7510e2e53 100644 --- a/src/main/java/com/arangodb/entity/To.java +++ b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/To.java @@ -1,6 +1,5 @@ -package com.arangodb.entity; +package com.arangodb.serde.jackson; -import com.arangodb.internal.DocumentFields; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; @@ -13,11 +12,10 @@ /** * @author Michele Rastelli */ -// TODO: in v7 add targets ElementType.METHOD and ElementType.PARAMETER -@Target(ElementType.FIELD) +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside -@JsonProperty(DocumentFields.TO) +@JsonProperty("_to") @JsonInclude(JsonInclude.Include.NON_NULL) public @interface To { } diff --git a/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java new file mode 100644 index 000000000..936192d0e --- /dev/null +++ b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/internal/JacksonMapperProvider.java @@ -0,0 +1,34 @@ +package com.arangodb.serde.jackson.internal; + +import com.arangodb.ArangoDBException; +import com.arangodb.ContentType; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.ServiceLoader; +import java.util.function.Supplier; + +/** + * Not shaded in arangodb-java-driver-shaded. + */ +public interface JacksonMapperProvider extends Supplier { + static ObjectMapper of(final ContentType contentType) { + String formatName; + if (contentType == ContentType.JSON) { + formatName = "JSON"; + } else if (contentType == ContentType.VPACK) { + formatName = "Velocypack"; + } else { + throw new IllegalArgumentException("Unexpected value: " + contentType); + } + + ServiceLoader sl = ServiceLoader.load(JsonFactory.class); + for (JsonFactory jf : sl) { + if(formatName.equals(jf.getFormatName())){ + return new ObjectMapper(jf); + } + } + + throw new ArangoDBException("No JsonFactory found for content type: " + contentType); + } +} diff --git a/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java new file mode 100644 index 000000000..7b6e812c1 --- /dev/null +++ b/jackson-serde-json/src/main/java/com/arangodb/serde/jackson/internal/JacksonSerdeImpl.java @@ -0,0 +1,46 @@ +package com.arangodb.serde.jackson.internal; + +import com.arangodb.serde.jackson.JacksonSerde; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.util.function.Consumer; + +/** + * Not shaded in arangodb-java-driver-shaded. + */ +public final class JacksonSerdeImpl implements JacksonSerde { + + private final ObjectMapper mapper; + + public JacksonSerdeImpl(final ObjectMapper mapper) { + this.mapper = mapper; + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + @Override + public byte[] serialize(final Object value) { + try { + return mapper.writeValueAsBytes(value); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + @Override + public T deserialize(final byte[] content, final Class type) { + try { + return mapper.readerFor(mapper.constructType(type)).readValue(content); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void configure(Consumer configureFunction) { + configureFunction.accept(mapper); + } + +} diff --git a/jackson-serde-json/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider b/jackson-serde-json/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider new file mode 100644 index 000000000..198620d5b --- /dev/null +++ b/jackson-serde-json/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider @@ -0,0 +1 @@ +com.arangodb.serde.jackson.JacksonSerdeProvider diff --git a/jackson-serde-vpack/pom.xml b/jackson-serde-vpack/pom.xml new file mode 100644 index 000000000..875b6b5b9 --- /dev/null +++ b/jackson-serde-vpack/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + + com.arangodb + arangodb-java-driver-parent + 7.0.0-ALPHA.2 + + + jackson-serde-vpack + jackson-serde-vpack + Jackson Serde VPACK module for ArangoDB Java Driver + + + false + com.arangodb.serde.jackson.vpack + + + + + com.arangodb + jackson-serde-json + + + com.arangodb + jackson-dataformat-velocypack + + + com.arangodb + velocypack + + + + diff --git a/jackson-serde-vpack/src/main/resources/META-INF/MANIFEST.MF b/jackson-serde-vpack/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 000000000..e69de29bb diff --git a/jsonb-serde/pom.xml b/jsonb-serde/pom.xml new file mode 100644 index 000000000..b28ea81b6 --- /dev/null +++ b/jsonb-serde/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + com.arangodb + arangodb-java-driver-parent + 7.0.0-ALPHA.2 + + + jsonb-serde + jsonb-serde + JsonB Serde module for ArangoDB Java Driver + + + + true + com.arangodb.serde.jsonb + + + + + com.arangodb + core + provided + + + jakarta.json.bind + jakarta.json.bind-api + 3.0.0 + + + + \ No newline at end of file diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/From.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/From.java new file mode 100644 index 000000000..057be2105 --- /dev/null +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/From.java @@ -0,0 +1,19 @@ +package com.arangodb.serde.jsonb; + +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JsonbAnnotation +@JsonbProperty("_from") +public @interface From { +} diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Id.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Id.java new file mode 100644 index 000000000..f2c4f8462 --- /dev/null +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Id.java @@ -0,0 +1,19 @@ +package com.arangodb.serde.jsonb; + +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JsonbAnnotation +@JsonbProperty("_id") +public @interface Id { +} diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerde.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerde.java new file mode 100644 index 000000000..b1d2baa36 --- /dev/null +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerde.java @@ -0,0 +1,35 @@ +package com.arangodb.serde.jsonb; + +import com.arangodb.serde.ArangoSerde; +import jakarta.json.bind.Jsonb; +import jakarta.json.bind.JsonbBuilder; +import jakarta.json.bind.JsonbConfig; + +import java.nio.charset.StandardCharsets; + +/** + * User data serde based on Jakarta JSON Binding (JSON-B). + */ +public class JsonbSerde implements ArangoSerde { + + private final Jsonb jsonb; + + public JsonbSerde() { + jsonb = JsonbBuilder.create(); + } + + public JsonbSerde(final JsonbConfig config) { + jsonb = JsonbBuilder.create(config); + } + + @Override + public byte[] serialize(Object value) { + return jsonb.toJson(value).getBytes(StandardCharsets.UTF_8); + } + + @Override + public T deserialize(byte[] content, Class type) { + return jsonb.fromJson(new String(content, StandardCharsets.UTF_8), type); + } + +} diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerdeProvider.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerdeProvider.java new file mode 100644 index 000000000..149aa1427 --- /dev/null +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/JsonbSerdeProvider.java @@ -0,0 +1,33 @@ +package com.arangodb.serde.jsonb; + +import com.arangodb.ContentType; +import com.arangodb.serde.ArangoSerdeProvider; +import jakarta.json.bind.JsonbConfig; + +import java.util.Objects; + +public class JsonbSerdeProvider implements ArangoSerdeProvider { + + /** + * Creates a new JsonbSerde with default settings. + * + * @return the created JsonbSerde + */ + @Override + public JsonbSerde of(final ContentType contentType) { + if (Objects.requireNonNull(contentType) == ContentType.JSON) { + return new JsonbSerde(); + } + throw new IllegalArgumentException(contentType.toString()); + } + + /** + * Creates a new JsonbSerde using the provided . + * + * @param config JsonbConfig to use + * @return the created JsonbSerde + */ + static JsonbSerde create(final JsonbConfig config) { + return new JsonbSerde(config); + } +} diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Key.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Key.java new file mode 100644 index 000000000..e5ff89558 --- /dev/null +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Key.java @@ -0,0 +1,19 @@ +package com.arangodb.serde.jsonb; + +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JsonbAnnotation +@JsonbProperty("_key") +public @interface Key { +} diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Rev.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Rev.java new file mode 100644 index 000000000..86a7a5ee1 --- /dev/null +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/Rev.java @@ -0,0 +1,19 @@ +package com.arangodb.serde.jsonb; + +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JsonbAnnotation +@JsonbProperty("_rev") +public @interface Rev { +} diff --git a/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/To.java b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/To.java new file mode 100644 index 000000000..89b4ef7d2 --- /dev/null +++ b/jsonb-serde/src/main/java/com/arangodb/serde/jsonb/To.java @@ -0,0 +1,19 @@ +package com.arangodb.serde.jsonb; + +import jakarta.json.bind.annotation.JsonbAnnotation; +import jakarta.json.bind.annotation.JsonbProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Michele Rastelli + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JsonbAnnotation +@JsonbProperty("_to") +public @interface To { +} diff --git a/jsonb-serde/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider b/jsonb-serde/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider new file mode 100644 index 000000000..7a37a64b1 --- /dev/null +++ b/jsonb-serde/src/main/resources/META-INF/services/com.arangodb.serde.ArangoSerdeProvider @@ -0,0 +1 @@ +com.arangodb.serde.jsonb.JsonbSerdeProvider diff --git a/pom.xml b/pom.xml index c9b2825a0..24508f88f 100644 --- a/pom.xml +++ b/pom.xml @@ -4,14 +4,23 @@ 4.0.0 com.arangodb - arangodb-java-driver - 6.18.0 + arangodb-java-driver-parent + 7.0.0-ALPHA.2 2016 - jar + + core + driver + shaded + jackson-serde-json + jackson-serde-vpack + http + vst + + pom - arangodb-java-driver - ArangoDB Java Driver - http://maven.apache.org + arangodb-java-driver-parent + ArangoDB Java Driver Project + https://github.com/arangodb/arangodb-java-driver @@ -22,7 +31,15 @@ + 1.8 + 1.8 UTF-8 + true + arangodb-1 + https://sonarcloud.io + 2.14.1 + + @@ -37,132 +54,156 @@ - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - + + ArangoDB GmbH + https://www.arangodb.com + - - - doclint-java8-disable - - [1.8,) - - - none - - - - no-graalvm - - 1.8 - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - com/arangodb/util/UnicodeUtilsTest.java - - - - - - - - native - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M5 - - - org.graalvm.buildtools - native-maven-plugin - 0.9.11 - true - - - test-native - - generateTestResourceConfig - test - - test - - - - false - - --no-fallback - - - - - - - + + + ch.qos.logback + logback-classic + test + + + org.junit.platform + junit-platform-launcher + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.assertj + assertj-core + test + + + + + + + com.fasterxml.jackson + jackson-bom + ${adb.jackson.version} + import + pom + + + org.junit + junit-bom + 5.9.1 + pom + import + + + com.arangodb + arangodb-java-driver + ${project.version} + + + com.arangodb + core + ${project.version} + + + com.arangodb + http-protocol + ${project.version} + + + com.arangodb + vst-protocol + ${project.version} + + + com.arangodb + jackson-serde-json + ${project.version} + + + com.arangodb + jackson-serde-vpack + ${project.version} + + + com.arangodb + jsonb-serde + ${project.version} + + + com.arangodb + arangodb-java-driver-shaded + ${project.version} + + + com.arangodb + velocypack + 3.0.0 + + + com.arangodb + jackson-dataformat-velocypack + 4.0.0 + + + org.slf4j + slf4j-api + 2.0.5 + + + ch.qos.logback + logback-classic + 1.3.5 + + + org.assertj + assertj-core + 3.23.1 + + + com.tngtech.archunit + archunit-junit5 + 1.0.1 + + + org.eclipse + yasson + 3.0.2 + + + - - org.apache.maven.plugins - maven-enforcer-plugin - 3.0.0-M3 - - - enforce - - enforce - - - - - - - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.8 - true - - ossrh - https://oss.sonatype.org/ - 84aff6e87e214c - false - - org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.10.1 -Xlint:unchecked -Xlint:deprecation true - 1.8 - 1.8 org.apache.maven.plugins maven-resources-plugin - 3.1.0 + 3.3.0 UTF-8 @@ -170,7 +211,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.0 + 3.2.1 @@ -182,7 +223,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 + 3.4.1 attach-javadocs @@ -190,7 +231,7 @@ jar - com.arangodb.internal + **.internal** @@ -198,7 +239,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M5 + 3.0.0-M7 **/*Test.java @@ -208,17 +249,14 @@ org.apache.maven.plugins - maven-deploy-plugin - 2.8.2 + maven-gpg-plugin + 3.0.1 - false - 10 + + --pinentry-mode + loopback + - - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 sign-artifacts @@ -229,119 +267,116 @@ + + org.codehaus.mojo + flatten-maven-plugin + 1.3.0 + + oss + + + + + flatten + package + + flatten + + + + + flatten.clean + clean + + clean + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + ${project.name} + ${project.version} + ${moduleName} + + + true + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.1.0 + + + enforce + + enforce + + + + + 3.6 + + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.0.0 + + 10 + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.13 + true + + ossrh + https://oss.sonatype.org/ + 84aff6e87e214c + false + ${maven.deploy.skip} + + + + org.apache.maven.plugins + maven-clean-plugin + 3.2.0 + + + + ${project.basedir} + + **/dependency-reduced-pom.xml + + + + + - - - com.arangodb - velocypack - - - org.slf4j - slf4j-api - - - org.apache.httpcomponents - httpclient - true - - - com.arangodb - jackson-dataformat-velocypack - true - - - ch.qos.logback - logback-classic - test - - - org.junit.platform - junit-platform-launcher - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - org.junit.jupiter - junit-jupiter-params - test - - - org.assertj - assertj-core - 3.22.0 - test - - - org.reflections - reflections - 0.9.12 - test - - - org.graalvm.sdk - graal-sdk - 22.1.0 - test - - - - - - - com.arangodb - jackson-dataformat-velocypack - 3.0.1 - - - org.apache.httpcomponents - httpclient - 4.5.13 - - - org.apache.httpcomponents - httpcore - 4.4.15 - - - commons-codec - commons-codec - 1.15 - - - commons-logging - commons-logging - 1.2 - - - com.arangodb - velocypack - 2.5.4 - - - org.slf4j - slf4j-api - 1.7.36 - - - ch.qos.logback - logback-classic - 1.2.9 - - - org.junit - junit-bom - 5.8.2 - pom - import - - - + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + https://github.com/arangodb/arangodb-java-driver @@ -349,9 +384,60 @@ scm:git:git://github.com/arangodb/arangodb-java-driver.git - - ArangoDB GmbH - https://www.arangodb.com - + + + no-deploy + + + !deploy + + + + jsonb-serde + + + + doclint-java8-disable + + [1.8,) + + + none + + + + native + + + + org.graalvm.buildtools + native-maven-plugin + 0.9.19 + true + + + test-native + + generateTestResourceConfig + test + + test + + + + true + false + + --no-fallback + + + ${SslTest} + + + + + + + diff --git a/resilience-tests/README.md b/resilience-tests/README.md new file mode 100644 index 000000000..4cd121c14 --- /dev/null +++ b/resilience-tests/README.md @@ -0,0 +1,15 @@ +# arangodb-java-driver-resiliency-tests + +## run + +Start (single server) ArangoDB: +```shell +./docker/start_db.sh +``` + +Start [toxiproxy-server](https://github.com/Shopify/toxiproxy) at `127.0.0.1:8474`. + +Run the tests: +```shell + mvn test -am -pl resilience-tests +``` diff --git a/resilience-tests/bin/startProxy.sh b/resilience-tests/bin/startProxy.sh new file mode 100755 index 000000000..00c1802df --- /dev/null +++ b/resilience-tests/bin/startProxy.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +wget -O bin/toxiproxy-server-linux-amd64 https://github.com/Shopify/toxiproxy/releases/download/${TOXIPROXY_VERSION}/toxiproxy-server-linux-amd64 +chmod a+x bin/toxiproxy-server-linux-amd64 +bin/toxiproxy-server-linux-amd64 & diff --git a/resilience-tests/pom.xml b/resilience-tests/pom.xml new file mode 100644 index 000000000..8d379f9bf --- /dev/null +++ b/resilience-tests/pom.xml @@ -0,0 +1,40 @@ + + + + arangodb-java-driver-parent + com.arangodb + 7.0.0-ALPHA.2 + + 4.0.0 + + resilience-tests + + + + org.mock-server + mockserver-netty + 5.13.2 + + + com.arangodb + arangodb-java-driver + + + com.arangodb + jackson-dataformat-velocypack + + + eu.rekawek.toxiproxy + toxiproxy-java + 2.1.7 + + + org.awaitility + awaitility + 4.2.0 + + + + \ No newline at end of file diff --git a/resilience-tests/src/test/java/resilience/ActiveFailoverTest.java b/resilience-tests/src/test/java/resilience/ActiveFailoverTest.java new file mode 100644 index 000000000..8b2573a5b --- /dev/null +++ b/resilience-tests/src/test/java/resilience/ActiveFailoverTest.java @@ -0,0 +1,76 @@ +package resilience; + +import ch.qos.logback.classic.Level; +import com.arangodb.ArangoDB; +import com.arangodb.async.ArangoDBAsync; +import resilience.utils.MemoryAppender; +import eu.rekawek.toxiproxy.Proxy; +import eu.rekawek.toxiproxy.ToxiproxyClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +@Tag("activeFailover") +public abstract class ActiveFailoverTest { + + protected static final String HOST = "127.0.0.1"; + protected static final String PASSWORD = "test"; + protected static final MemoryAppender logs = new MemoryAppender(Level.WARN); + private static final List endpoints = Arrays.asList( + new Endpoint("activeFailover1", HOST, 18529, "172.28.0.1:8529"), + new Endpoint("activeFailover2", HOST, 18539, "172.28.0.1:8539"), + new Endpoint("activeFailover3", HOST, 18549, "172.28.0.1:8549") + ); + + @BeforeAll + static void beforeAll() throws IOException { + ToxiproxyClient client = new ToxiproxyClient(HOST, 8474); + for (Endpoint ph : endpoints) { + Proxy p = client.getProxyOrNull(ph.getName()); + if (p != null) { + p.delete(); + } + ph.setProxy(client.createProxy(ph.getName(), ph.getHost() + ":" + ph.getPort(), ph.getUpstream())); + } + } + + @AfterAll + static void afterAll() throws IOException { + for (Endpoint ph : endpoints) { + ph.getProxy().delete(); + } + } + + @BeforeEach + void beforeEach() throws IOException { + for (Endpoint ph : endpoints) { + ph.getProxy().enable(); + } + } + + protected static List getEndpoints() { + return endpoints; + } + + protected static ArangoDB.Builder dbBuilder() { + ArangoDB.Builder builder = new ArangoDB.Builder().password(PASSWORD); + for (Endpoint ph : endpoints) { + builder.host(ph.getHost(), ph.getPort()); + } + return builder; + } + + protected static ArangoDBAsync.Builder dbBuilderAsync() { + ArangoDBAsync.Builder builder = new ArangoDBAsync.Builder().password(PASSWORD); + for (Endpoint ph : endpoints) { + builder.host(ph.getHost(), ph.getPort()); + } + return builder; + } + +} diff --git a/resilience-tests/src/test/java/resilience/ClusterTest.java b/resilience-tests/src/test/java/resilience/ClusterTest.java new file mode 100644 index 000000000..a757f5f76 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/ClusterTest.java @@ -0,0 +1,76 @@ +package resilience; + +import ch.qos.logback.classic.Level; +import com.arangodb.ArangoDB; +import com.arangodb.async.ArangoDBAsync; +import resilience.utils.MemoryAppender; +import eu.rekawek.toxiproxy.Proxy; +import eu.rekawek.toxiproxy.ToxiproxyClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +@Tag("cluster") +public abstract class ClusterTest { + + protected static final String HOST = "127.0.0.1"; + protected static final String PASSWORD = "test"; + protected static final MemoryAppender logs = new MemoryAppender(Level.WARN); + private static final List endpoints = Arrays.asList( + new Endpoint("cluster1", HOST, 18529, "172.28.0.1:8529"), + new Endpoint("cluster2", HOST, 18539, "172.28.0.1:8539"), + new Endpoint("cluster3", HOST, 18549, "172.28.0.1:8549") + ); + + @BeforeAll + static void beforeAll() throws IOException { + ToxiproxyClient client = new ToxiproxyClient(HOST, 8474); + for (Endpoint ph : endpoints) { + Proxy p = client.getProxyOrNull(ph.getName()); + if (p != null) { + p.delete(); + } + ph.setProxy(client.createProxy(ph.getName(), ph.getHost() + ":" + ph.getPort(), ph.getUpstream())); + } + } + + @AfterAll + static void afterAll() throws IOException { + for (Endpoint ph : endpoints) { + ph.getProxy().delete(); + } + } + + @BeforeEach + void beforeEach() throws IOException { + for (Endpoint ph : endpoints) { + ph.getProxy().enable(); + } + } + + protected static List getEndpoints() { + return endpoints; + } + + protected static ArangoDB.Builder dbBuilder() { + ArangoDB.Builder builder = new ArangoDB.Builder().password(PASSWORD); + for (Endpoint ph : endpoints) { + builder.host(ph.getHost(), ph.getPort()); + } + return builder; + } + + protected static ArangoDBAsync.Builder dbBuilderAsync() { + ArangoDBAsync.Builder builder = new ArangoDBAsync.Builder().password(PASSWORD); + for (Endpoint ph : endpoints) { + builder.host(ph.getHost(), ph.getPort()); + } + return builder; + } + +} diff --git a/resilience-tests/src/test/java/resilience/Endpoint.java b/resilience-tests/src/test/java/resilience/Endpoint.java new file mode 100644 index 000000000..9e8c697d4 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/Endpoint.java @@ -0,0 +1,45 @@ +package resilience; + +import eu.rekawek.toxiproxy.Proxy; + +/** + * class representing a proxied db endpoint + */ +public class Endpoint { + private final String name; + private final String host; + private final int port; + private final String upstream; + private Proxy proxy; + + public Endpoint(String name, String host, int port, String upstream) { + this.name = name; + this.host = host; + this.port = port; + this.upstream = upstream; + } + + public String getName() { + return name; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public String getUpstream() { + return upstream; + } + + public Proxy getProxy() { + return proxy; + } + + public void setProxy(Proxy proxy) { + this.proxy = proxy; + } +} diff --git a/resilience-tests/src/test/java/resilience/SingleServerTest.java b/resilience-tests/src/test/java/resilience/SingleServerTest.java new file mode 100644 index 000000000..05c87d7e2 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/SingleServerTest.java @@ -0,0 +1,78 @@ +package resilience; + +import ch.qos.logback.classic.Level; +import com.arangodb.ArangoDB; +import com.arangodb.async.ArangoDBAsync; +import resilience.utils.MemoryAppender; +import eu.rekawek.toxiproxy.Proxy; +import eu.rekawek.toxiproxy.ToxiproxyClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; + +import java.io.IOException; + +@Tag("singleServer") +public abstract class SingleServerTest { + + protected static final String HOST = "127.0.0.1"; + protected static final String PASSWORD = "test"; + protected static final MemoryAppender logs = new MemoryAppender(Level.INFO); + private static final Endpoint endpoint = new Endpoint("singleServer", HOST, 18529, "172.28.0.1:8529"); + + @BeforeAll + static void beforeAll() throws IOException { + ToxiproxyClient client = new ToxiproxyClient(HOST, 8474); + Proxy p = client.getProxyOrNull(endpoint.getName()); + if (p != null) { + p.delete(); + } + endpoint.setProxy(client.createProxy(endpoint.getName(), HOST + ":" + endpoint.getPort(), endpoint.getUpstream())); + } + + @AfterAll + static void afterAll() throws IOException { + endpoint.getProxy().delete(); + } + + @BeforeEach + void beforeEach() { + enableEndpoint(); + } + + protected static Endpoint getEndpoint() { + return endpoint; + } + + protected static ArangoDB.Builder dbBuilder() { + return new ArangoDB.Builder() + .host(endpoint.getHost(), endpoint.getPort()) + .password(PASSWORD); + } + + protected static ArangoDBAsync.Builder dbBuilderAsync() { + return new ArangoDBAsync.Builder() + .host(endpoint.getHost(), endpoint.getPort()) + .password(PASSWORD); + } + + protected void enableEndpoint(){ + try { + getEndpoint().getProxy().enable(); + Thread.sleep(100); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + } + + protected void disableEndpoint(){ + try { + getEndpoint().getProxy().disable(); + Thread.sleep(100); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/resilience-tests/src/test/java/resilience/connection/ConnectionTest.java b/resilience-tests/src/test/java/resilience/connection/ConnectionTest.java new file mode 100644 index 000000000..24e484282 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/connection/ConnectionTest.java @@ -0,0 +1,75 @@ +package resilience.connection; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.ArangoDBMultipleException; +import com.arangodb.Protocol; +import resilience.SingleServerTest; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.net.ConnectException; +import java.net.UnknownHostException; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + +/** + * @author Michele Rastelli + */ +class ConnectionTest extends SingleServerTest { + + static Stream protocolProvider() { + return Stream.of( + Protocol.VST, + Protocol.HTTP_VPACK, + Protocol.HTTP2_VPACK + ); + } + + static Stream arangoProvider() { + return Stream.of( + dbBuilder().useProtocol(Protocol.VST).build(), + dbBuilder().useProtocol(Protocol.HTTP_VPACK).build(), + dbBuilder().useProtocol(Protocol.HTTP2_VPACK).build() + ); + } + + @ParameterizedTest + @MethodSource("protocolProvider") + void nameResolutionFailTest(Protocol protocol) { + ArangoDB arangoDB = new ArangoDB.Builder() + .host("wrongHost", 8529) + .useProtocol(protocol) + .build(); + + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getMessage()).contains("Cannot contact any host!"); + assertThat(thrown.getCause()).isNotNull(); + assertThat(thrown.getCause()).isInstanceOf(ArangoDBMultipleException.class); + ((ArangoDBMultipleException) thrown.getCause()).getExceptions().forEach(e -> { + assertThat(e).isInstanceOf(UnknownHostException.class); + assertThat(e.getMessage()).contains("wrongHost"); + }); + arangoDB.shutdown(); + } + + @ParameterizedTest + @MethodSource("arangoProvider") + void connectionFailTest(ArangoDB arangoDB) { + disableEndpoint(); + + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getMessage()).contains("Cannot contact any host"); + assertThat(thrown.getCause()).isNotNull(); + assertThat(thrown.getCause()).isInstanceOf(ArangoDBMultipleException.class); + ((ArangoDBMultipleException) thrown.getCause()).getExceptions().forEach(e -> + assertThat(e).isInstanceOf(ConnectException.class)); + arangoDB.shutdown(); + enableEndpoint(); + } + +} diff --git a/resilience-tests/src/test/java/resilience/http/MockTest.java b/resilience-tests/src/test/java/resilience/http/MockTest.java new file mode 100644 index 000000000..e5eb6fab0 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/http/MockTest.java @@ -0,0 +1,60 @@ +package resilience.http; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.Protocol; +import resilience.SingleServerTest; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockserver.integration.ClientAndServer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.mockserver.integration.ClientAndServer.startClientAndServer; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +class MockTest extends SingleServerTest { + + private ClientAndServer mockServer; + private ArangoDB arangoDB; + + @BeforeEach + void before() { + mockServer = startClientAndServer(getEndpoint().getHost(), getEndpoint().getPort()); + arangoDB = new ArangoDB.Builder() + .useProtocol(Protocol.HTTP_JSON) + .password(PASSWORD) + .host("127.0.0.1", mockServer.getPort()) + .build(); + } + + @AfterEach + void after() { + arangoDB.shutdown(); + mockServer.stop(); + } + + @Test + void doTest() { + arangoDB.getVersion(); + + mockServer + .when( + request() + .withMethod("GET") + .withPath("/.*/_api/version") + ) + .respond( + response() + .withStatusCode(503) + .withBody("{\"error\":true,\"errorNum\":503,\"errorMessage\":\"boom\",\"code\":503}") + ); + + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown) + .isInstanceOf(ArangoDBException.class) + .hasMessageContaining("boom"); + } +} diff --git a/resilience-tests/src/test/java/resilience/retry/RetryTest.java b/resilience-tests/src/test/java/resilience/retry/RetryTest.java new file mode 100644 index 000000000..1f2817b6c --- /dev/null +++ b/resilience-tests/src/test/java/resilience/retry/RetryTest.java @@ -0,0 +1,202 @@ +package resilience.retry; + +import ch.qos.logback.classic.Level; +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.ArangoDBMultipleException; +import com.arangodb.Protocol; +import io.vertx.core.http.HttpClosedException; +import org.junit.jupiter.params.provider.EnumSource; +import resilience.SingleServerTest; +import eu.rekawek.toxiproxy.model.ToxicDirection; +import eu.rekawek.toxiproxy.model.toxic.Latency; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.net.ConnectException; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Michele Rastelli + */ +class RetryTest extends SingleServerTest { + + static Stream arangoProvider() { + return Stream.of( + dbBuilder().useProtocol(Protocol.VST).build(), + dbBuilder().useProtocol(Protocol.HTTP_VPACK).build(), + dbBuilder().useProtocol(Protocol.HTTP2_VPACK).build() + ); + } + + /** + * on reconnection failure: - 3x logs WARN Could not connect to host[addr=127.0.0.1,port=8529] - + * ArangoDBException("Cannot contact any host") + *

    + * once the proxy is re-enabled: - the subsequent requests should be successful + */ + @ParameterizedTest + @MethodSource("arangoProvider") + void unreachableHost(ArangoDB arangoDB) { + arangoDB.getVersion(); + disableEndpoint(); + + for (int i = 0; i < 10; i++) { + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getMessage()).contains("Cannot contact any host"); + assertThat(thrown.getCause()).isNotNull(); + assertThat(thrown.getCause()).isInstanceOf(ArangoDBMultipleException.class); + ((ArangoDBMultipleException) thrown.getCause()).getExceptions().forEach(e -> + assertThat(e).isInstanceOf(ConnectException.class)); + } + + long warnsCount = logs.getLoggedEvents().stream() + .filter(e -> e.getLevel().equals(Level.WARN)) + .filter(e -> e.getMessage().contains("Could not connect to host[addr=127.0.0.1,port=18529]")) + .count(); + assertThat(warnsCount).isGreaterThanOrEqualTo(3); + + enableEndpoint(); + arangoDB.getVersion(); + arangoDB.shutdown(); + } + + /** + * on delayed response: + * - ArangoDBException with cause TimeoutException + *

    + * once the delay is removed: + * - the subsequent requests should be successful + */ + @ParameterizedTest + @EnumSource(Protocol.class) + void connectionTimeout(Protocol protocol) throws IOException, InterruptedException { + // https://github.com/vert-x3/vertx-web/issues/2296 + // WebClient: HTTP/2 request timeout does not throw TimeoutException + assumeTrue(protocol != Protocol.HTTP2_VPACK); + assumeTrue(protocol != Protocol.HTTP2_JSON); + + ArangoDB arangoDB = dbBuilder() + .timeout(1_000) + .useProtocol(protocol) + .build(); + + arangoDB.getVersion(); + + // slow down the driver connection + Latency toxic = getEndpoint().getProxy().toxics().latency("latency", ToxicDirection.DOWNSTREAM, 10_000); + Thread.sleep(100); + + Throwable thrown = catchThrowable(arangoDB::getVersion); + thrown.printStackTrace(); + assertThat(thrown) + .isInstanceOf(ArangoDBException.class) + .extracting(Throwable::getCause) + .isInstanceOf(TimeoutException.class); + + toxic.remove(); + Thread.sleep(100); + + arangoDB.getVersion(); + arangoDB.shutdown(); + } + + + /** + * on closed pending requests of safe HTTP methods: + *

    + * - retry 3 times + * - ArangoDBMultipleException with 3 exceptions + *

    + * once restored: + *

    + * - the subsequent requests should be successful + */ + @ParameterizedTest + @EnumSource(Protocol.class) + void retryGetOnClosedConnection(Protocol protocol) throws IOException, InterruptedException { + assumeTrue(protocol != Protocol.VST); + ArangoDB arangoDB = dbBuilder() + .useProtocol(protocol) + .build(); + + arangoDB.getVersion(); + + // slow down the driver connection + Latency toxic = getEndpoint().getProxy().toxics().latency("latency", ToxicDirection.DOWNSTREAM, 10_000); + Thread.sleep(100); + + ScheduledExecutorService es = Executors.newSingleThreadScheduledExecutor(); + es.schedule(this::disableEndpoint, 300, TimeUnit.MILLISECONDS); + + Throwable thrown = catchThrowable(arangoDB::getVersion); + thrown.printStackTrace(); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getCause()).isInstanceOf(ArangoDBMultipleException.class); + List exceptions = ((ArangoDBMultipleException) thrown.getCause()).getExceptions(); + assertThat(exceptions).hasSize(3); + assertThat(exceptions.get(0)).isInstanceOf(IOException.class); + assertThat(exceptions.get(0).getCause()).isInstanceOf(HttpClosedException.class); + assertThat(exceptions.get(1)).isInstanceOf(ConnectException.class); + assertThat(exceptions.get(2)).isInstanceOf(ConnectException.class); + + toxic.remove(); + Thread.sleep(100); + enableEndpoint(); + + arangoDB.getVersion(); + arangoDB.shutdown(); + es.shutdown(); + } + + + /** + * on closed pending requests of unsafe HTTP methods: - no retry should happen + *

    + * once restored: - the subsequent requests should be successful + */ + @ParameterizedTest + @EnumSource(Protocol.class) + void notRetryPostOnClosedConnection(Protocol protocol) throws IOException, InterruptedException { + ArangoDB arangoDB = dbBuilder() + .useProtocol(protocol) + .build(); + + arangoDB.db().query("return null", Void.class); + + // slow down the driver connection + Latency toxic = getEndpoint().getProxy().toxics().latency("latency", ToxicDirection.DOWNSTREAM, 10_000); + Thread.sleep(100); + + ScheduledExecutorService es = Executors.newSingleThreadScheduledExecutor(); + es.schedule(this::disableEndpoint, 300, TimeUnit.MILLISECONDS); + + Throwable thrown = catchThrowable(() -> arangoDB.db().query("return null", Void.class)); + thrown.printStackTrace(); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getCause()).isInstanceOf(IOException.class); + if (protocol != Protocol.VST) { + assertThat(thrown.getCause().getCause()).isInstanceOf(HttpClosedException.class); + } + + toxic.remove(); + Thread.sleep(100); + enableEndpoint(); + + arangoDB.db().query("return null", Void.class); + arangoDB.shutdown(); + es.shutdown(); + } + +} diff --git a/resilience-tests/src/test/java/resilience/shutdown/ShutdownTest.java b/resilience-tests/src/test/java/resilience/shutdown/ShutdownTest.java new file mode 100644 index 000000000..a53e3c331 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/shutdown/ShutdownTest.java @@ -0,0 +1,57 @@ +package resilience.shutdown; + +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.Protocol; +import io.vertx.core.http.HttpClosedException; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import resilience.SingleServerTest; + +import java.io.IOException; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Michele Rastelli + */ +class ShutdownTest extends SingleServerTest { + + @ParameterizedTest + @EnumSource(Protocol.class) + void shutdown(Protocol protocol) throws InterruptedException { + ArangoDB arangoDB = dbBuilder() + .useProtocol(protocol) + .build(); + + arangoDB.getVersion(); + arangoDB.shutdown(); + Thread.sleep(1_000); + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getMessage()).contains("closed"); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void shutdownWithPendingRequests(Protocol protocol) { + assumeTrue(protocol != Protocol.VST); + ArangoDB arangoDB = dbBuilder() + .useProtocol(protocol) + .build(); + + ScheduledExecutorService es = Executors.newSingleThreadScheduledExecutor(); + es.schedule(arangoDB::shutdown, 200, TimeUnit.MILLISECONDS); + Throwable thrown = catchThrowable(() -> arangoDB.db().query("return sleep(1)", Void.class)); + assertThat(thrown).isInstanceOf(ArangoDBException.class); + assertThat(thrown.getCause()).isInstanceOf(IOException.class); + assertThat(thrown.getCause().getCause()).isInstanceOf(HttpClosedException.class); + es.shutdown(); + } + +} diff --git a/resilience-tests/src/test/java/resilience/timeout/TimeoutTest.java b/resilience-tests/src/test/java/resilience/timeout/TimeoutTest.java new file mode 100644 index 000000000..079c2e3fd --- /dev/null +++ b/resilience-tests/src/test/java/resilience/timeout/TimeoutTest.java @@ -0,0 +1,73 @@ +package resilience.timeout; + +import com.arangodb.ArangoCollection; +import com.arangodb.ArangoDB; +import com.arangodb.ArangoDBException; +import com.arangodb.Protocol; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import resilience.SingleServerTest; + +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.TimeoutException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * @author Michele Rastelli + */ +class TimeoutTest extends SingleServerTest { + + /** + * on timeout failure: + * - throw exception + * - expect operation performed (at most) once + *

    + * after the exception: + * - the subsequent requests should be successful + */ + @ParameterizedTest + @EnumSource(Protocol.class) + void requestTimeout(Protocol protocol) throws InterruptedException { + // https://github.com/vert-x3/vertx-web/issues/2296 + // WebClient: HTTP/2 request timeout does not throw TimeoutException + assumeTrue(protocol != Protocol.HTTP2_VPACK); + assumeTrue(protocol != Protocol.HTTP2_JSON); + + ArangoDB arangoDB = dbBuilder() + .timeout(1_000) + .useProtocol(protocol) + .build(); + + arangoDB.getVersion(); + String colName = "timeoutTest"; + ArangoCollection col = arangoDB.db().collection(colName); + if (!col.exists()) col.create(); + col.truncate(); + + try { + arangoDB.db().query("" + + "INSERT {value:sleep(2)}\n" + + "INTO @@col\n" + + "RETURN NEW\n", + Collections.singletonMap("@col", colName), + Map.class); + } catch (Exception e) { + e.printStackTrace(); + assertThat(e) + .isInstanceOf(ArangoDBException.class) + .extracting(Throwable::getCause) + .isInstanceOf(TimeoutException.class); + } + + arangoDB.getVersion(); + + Thread.sleep(2_000); + assertThat(col.count().getCount()).isEqualTo(1); + + arangoDB.shutdown(); + } + +} diff --git a/resilience-tests/src/test/java/resilience/utils/MemoryAppender.java b/resilience-tests/src/test/java/resilience/utils/MemoryAppender.java new file mode 100644 index 000000000..018dd5415 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/utils/MemoryAppender.java @@ -0,0 +1,30 @@ +package resilience.utils; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.List; + +public class MemoryAppender extends ListAppender { + + public MemoryAppender(Level level) { + setContext((LoggerContext) LoggerFactory.getILoggerFactory()); + start(); + Logger logger = (Logger) LoggerFactory.getLogger("root"); + logger.setLevel(level); + logger.addAppender(this); + } + + public void reset() { + this.list.clear(); + } + + public List getLoggedEvents() { + return Collections.unmodifiableList(this.list); + } +} \ No newline at end of file diff --git a/resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseAsyncTest.java b/resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseAsyncTest.java new file mode 100644 index 000000000..6a751da8d --- /dev/null +++ b/resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseAsyncTest.java @@ -0,0 +1,54 @@ +package resilience.vstKeepAlive; + +import ch.qos.logback.classic.Level; +import com.arangodb.async.ArangoDBAsync; +import resilience.SingleServerTest; +import eu.rekawek.toxiproxy.model.ToxicDirection; +import eu.rekawek.toxiproxy.model.toxic.Latency; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import static org.awaitility.Awaitility.await; + +/** + * @author Michele Rastelli + */ +class VstKeepAliveCloseAsyncTest extends SingleServerTest { + + private ArangoDBAsync arangoDB; + + @BeforeEach + void init() { + arangoDB = dbBuilderAsync() + .timeout(1000) + .keepAliveInterval(1) + .build(); + } + + @AfterEach + void shutDown() { + arangoDB.shutdown(); + } + + /** + * after 3 consecutive VST keepAlive failures: + * - log ERROR Connection unresponsive + * - reconnect on next request + */ + @Test + @Timeout(10) + void keepAliveCloseAndReconnect() throws IOException, ExecutionException, InterruptedException { + arangoDB.getVersion().get(); + Latency toxic = getEndpoint().getProxy().toxics().latency("latency", ToxicDirection.DOWNSTREAM, 10_000); + await().until(() -> logs.getLoggedEvents().stream() + .filter(e -> e.getLevel().equals(Level.ERROR)) + .anyMatch(e -> e.getMessage().contains("Connection unresponsive!"))); + toxic.setLatency(0L); + arangoDB.getVersion().get(); + } +} diff --git a/resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseTest.java b/resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseTest.java new file mode 100644 index 000000000..f55c97862 --- /dev/null +++ b/resilience-tests/src/test/java/resilience/vstKeepAlive/VstKeepAliveCloseTest.java @@ -0,0 +1,55 @@ +package resilience.vstKeepAlive; + +import ch.qos.logback.classic.Level; +import com.arangodb.ArangoDB; +import com.arangodb.Protocol; +import resilience.SingleServerTest; +import eu.rekawek.toxiproxy.model.ToxicDirection; +import eu.rekawek.toxiproxy.model.toxic.Latency; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; + +import java.io.IOException; + +import static org.awaitility.Awaitility.await; + +/** + * @author Michele Rastelli + */ +class VstKeepAliveCloseTest extends SingleServerTest { + + private ArangoDB arangoDB; + + @BeforeEach + void init() { + arangoDB = dbBuilder() + .useProtocol(Protocol.VST) + .timeout(1000) + .keepAliveInterval(1) + .build(); + } + + @AfterEach + void shutDown() { + arangoDB.shutdown(); + } + + /** + * after 3 consecutive VST keepAlive failures: + * - log ERROR Connection unresponsive + * - reconnect on next request + */ + @Test + @Timeout(10) + void keepAliveCloseAndReconnect() throws IOException { + arangoDB.getVersion(); + Latency toxic = getEndpoint().getProxy().toxics().latency("latency", ToxicDirection.DOWNSTREAM, 10_000); + await().until(() -> logs.getLoggedEvents().stream() + .filter(e -> e.getLevel().equals(Level.ERROR)) + .anyMatch(e -> e.getMessage().contains("Connection unresponsive!"))); + toxic.setLatency(0); + arangoDB.getVersion(); + } +} diff --git a/resilience-tests/src/test/resources/logback-test.xml b/resilience-tests/src/test/resources/logback-test.xml new file mode 100644 index 000000000..840d133d7 --- /dev/null +++ b/resilience-tests/src/test/resources/logback-test.xml @@ -0,0 +1,13 @@ + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + diff --git a/shaded-integration-tests/pom.xml b/shaded-integration-tests/pom.xml new file mode 100644 index 000000000..2c7e8da7f --- /dev/null +++ b/shaded-integration-tests/pom.xml @@ -0,0 +1,190 @@ + + + 4.0.0 + + + com.arangodb + arangodb-java-driver-parent + 7.0.0-ALPHA.2 + + + shaded-integration-tests + + + 17 + 17 + + + + ${testSourceDirectory} + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${serde} + + + + + + + + + internal-serde + + true + + + src/test/internal/java + jackson + + + + com.arangodb + arangodb-java-driver-shaded + + + com.arangodb + jackson-dataformat-velocypack + + + com.tngtech.archunit + archunit-junit5 + + + + + jackson-serde + + true + + + src/test/jackson/java + jackson + + + + com.arangodb + arangodb-java-driver-shaded + + + com.arangodb + jackson-serde-json + + + com.arangodb + jackson-serde-vpack + + + com.tngtech.archunit + archunit-junit5 + + + + + jsonb-serde + + src/test/jsonb/java + jsonb + + + + com.arangodb + arangodb-java-driver-shaded + + + com.arangodb + jsonb-serde + + + org.eclipse + yasson + + + com.tngtech.archunit + archunit-junit5 + + + + + native + + ${project.build.directory}/generated-sources/replacer + jackson + + + + com.arangodb + arangodb-java-driver-shaded + + + com.arangodb + jackson-serde-json + + + com.arangodb + jackson-serde-vpack + + + + + + com.google.code.maven-replacer-plugin + replacer + 1.5.3 + + + generate-test-sources + + replace + + + + + ${project.basedir}/src/test/native/java + ** + ${project.build.directory}/generated-test-sources + replacer + + **/CustomSerdeTest.**,**/SerdeTest.**,**/SerializableTest.** + + + + com.fasterxml.jackson.databind.JsonNode + com.arangodb.shaded.fasterxml.jackson.databind.JsonNode + + + com.fasterxml.jackson.databind.ObjectNode + com.arangodb.shaded.fasterxml.jackson.databind.ObjectNode + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.3.0 + + + generate-test-sources + + add-test-source + + + + ${project.build.directory}/generated-test-sources/replacer + + + + + + + + + + + \ No newline at end of file diff --git a/shaded-integration-tests/src/test/internal/java/arch/AdbTest.java b/shaded-integration-tests/src/test/internal/java/arch/AdbTest.java new file mode 100644 index 000000000..fc320db4e --- /dev/null +++ b/shaded-integration-tests/src/test/internal/java/arch/AdbTest.java @@ -0,0 +1,18 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.assertj.core.api.Assertions.assertThat; + +class AdbTest extends BaseTest { + @ParameterizedTest + @MethodSource("adbByProtocol") + void getVersion(ArangoDB adb) { + final ArangoDBVersion version = adb.getVersion(); + assertThat(version.getServer()).isNotNull(); + assertThat(version.getVersion()).isNotNull(); + } +} diff --git a/shaded-integration-tests/src/test/internal/java/arch/BaseTest.java b/shaded-integration-tests/src/test/internal/java/arch/BaseTest.java new file mode 100644 index 000000000..3fcbb5aa8 --- /dev/null +++ b/shaded-integration-tests/src/test/internal/java/arch/BaseTest.java @@ -0,0 +1,50 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.ContentType; +import com.arangodb.DbName; +import com.arangodb.Protocol; +import com.arangodb.config.ArangoConfigProperties; +import org.junit.jupiter.params.provider.Arguments; + +import java.util.Arrays; +import java.util.stream.Stream; + +public class BaseTest { + private static final ArangoConfigProperties config = ConfigUtils.loadConfig(); + protected static final DbName TEST_DB = DbName.of("java_driver_integration_tests"); + + protected static ArangoDB createAdb() { + return new ArangoDB.Builder() + .loadProperties(config) + .build(); + } + + protected static ArangoDB createAdb(ContentType contentType) { + Protocol protocol = contentType == ContentType.VPACK ? Protocol.HTTP2_VPACK : Protocol.HTTP2_JSON; + return new ArangoDB.Builder() + .loadProperties(config) + .useProtocol(protocol) + .build(); + } + + protected static ArangoDB createAdb(Protocol protocol) { + return new ArangoDB.Builder() + .loadProperties(config) + .useProtocol(protocol) + .build(); + } + + protected static Stream adbByProtocol() { + return Arrays.stream(Protocol.values()) + .map(BaseTest::createAdb) + .map(Arguments::of); + } + + protected static Stream adbByContentType() { + return Arrays.stream(ContentType.values()) + .map(BaseTest::createAdb) + .map(Arguments::of); + } + +} diff --git a/shaded-integration-tests/src/test/internal/java/arch/ConfigUtils.java b/shaded-integration-tests/src/test/internal/java/arch/ConfigUtils.java new file mode 100644 index 000000000..9f18a7bb8 --- /dev/null +++ b/shaded-integration-tests/src/test/internal/java/arch/ConfigUtils.java @@ -0,0 +1,19 @@ +package arch; + +import com.arangodb.config.ArangoConfigProperties; + +public class ConfigUtils { + + public static ArangoConfigProperties loadConfig() { + return ArangoConfigProperties.fromFile(); + } + + public static ArangoConfigProperties loadConfig(final String location) { + return ArangoConfigProperties.fromFile(location); + } + + public static ArangoConfigProperties loadConfig(final String location, final String prefix) { + return ArangoConfigProperties.fromFile(location, prefix); + } + +} diff --git a/shaded-integration-tests/src/test/internal/java/arch/Person.java b/shaded-integration-tests/src/test/internal/java/arch/Person.java new file mode 100644 index 000000000..67a0b4501 --- /dev/null +++ b/shaded-integration-tests/src/test/internal/java/arch/Person.java @@ -0,0 +1,14 @@ +package arch; + + +import com.arangodb.serde.InternalKey; +import com.arangodb.shaded.fasterxml.jackson.annotation.JsonProperty; + +public record Person( + @InternalKey + String key, + @JsonProperty("firstName") + String name, + int age +) { +} diff --git a/shaded-integration-tests/src/test/internal/java/arch/RelocationsTest.java b/shaded-integration-tests/src/test/internal/java/arch/RelocationsTest.java new file mode 100644 index 000000000..761556d78 --- /dev/null +++ b/shaded-integration-tests/src/test/internal/java/arch/RelocationsTest.java @@ -0,0 +1,56 @@ +package arch; + +import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests; +import com.tngtech.archunit.junit.AnalyzeClasses; +import com.tngtech.archunit.junit.ArchTest; +import com.tngtech.archunit.lang.ArchRule; + +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; + + +@AnalyzeClasses(packages = "com.arangodb..", importOptions = {DoNotIncludeTests.class}) +public class RelocationsTest { + + @ArchTest + public static final ArchRule nettyRelocation = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("io.netty.."); + + @ArchTest + public static final ArchRule vertxRelocation = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("io.vertx.."); + + @ArchTest + public static final ArchRule jacksonRelocation = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.jackson.dataformat.velocypack..").and() + .resideOutsideOfPackage("com.arangodb.serde.jackson..") + .should().dependOnClassesThat() + .resideInAPackage("com.fasterxml.jackson.."); + + @ArchTest + public static final ArchRule jacksonDataformatVelocypackRelocation = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.jackson.dataformat.velocypack..").and() + .resideOutsideOfPackage("com.arangodb.serde.jackson..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.jackson.dataformat.velocypack.."); + + @ArchTest + public static final ArchRule noJsonbDependency = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.serde.jsonb.."); + + @ArchTest + // jackson-serde is accessed via SPI + public static final ArchRule noExplicitDependencyOnJacksonSerde = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.serde.jackson..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.serde.jackson.."); + +} diff --git a/shaded-integration-tests/src/test/internal/java/arch/SerdeTest.java b/shaded-integration-tests/src/test/internal/java/arch/SerdeTest.java new file mode 100644 index 000000000..6b03aa7df --- /dev/null +++ b/shaded-integration-tests/src/test/internal/java/arch/SerdeTest.java @@ -0,0 +1,65 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.shaded.fasterxml.jackson.databind.JsonNode; +import com.arangodb.shaded.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.arangodb.util.RawJson; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Collections; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class SerdeTest extends BaseTest { + + @ParameterizedTest + @MethodSource("adbByContentType") + void shadedJsonNode(ArangoDB adb) { + // uses the internal serde + JsonNode doc = JsonNodeFactory.instance + .objectNode() + .put("foo", "bar"); + JsonNode res = adb.db().query("return @d", Collections.singletonMap("d", doc), JsonNode.class).next(); + assertThat(res.size()).isEqualTo(1); + assertThat(res.get("foo").asText()).isEqualTo("bar"); + JsonNode value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), JsonNode.class).next(); + assertThat(value.textValue()).isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void map(ArangoDB adb) { + Map doc = Collections.singletonMap("foo", "bar"); + Map res = adb.db().query("return @d", Collections.singletonMap("d", doc), Map.class).next(); + assertThat(res).hasSize(1); + assertThat(res.get("foo")).isEqualTo("bar"); + String value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), String.class).next(); + assertThat(value).isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void rawJson(ArangoDB adb) { + RawJson doc = RawJson.of(""" + {"foo":"bar"}"""); + RawJson res = adb.db().query("return @d", Collections.singletonMap("d", doc), RawJson.class).next(); + assertThat(res.getValue()).isEqualTo(doc.getValue()); + RawJson value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), RawJson.class).next(); + assertThat(value.getValue()).isEqualTo("\"bar\""); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void person(ArangoDB adb) { + Person doc = new Person("key", "Jim", 22); + Person res = adb.db().query("return @d", Collections.singletonMap("d", doc), Person.class).next(); + assertThat(res).isEqualTo(doc); + String key = adb.db().query("return @d._key", Collections.singletonMap("d", doc), String.class).next(); + assertThat(key).isEqualTo("key"); + String name = adb.db().query("return @d.firstName", Collections.singletonMap("d", doc), String.class).next(); + assertThat(name).isEqualTo("Jim"); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/arch/AdbTest.java b/shaded-integration-tests/src/test/jackson/java/arch/AdbTest.java new file mode 100644 index 000000000..fc320db4e --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/arch/AdbTest.java @@ -0,0 +1,18 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.assertj.core.api.Assertions.assertThat; + +class AdbTest extends BaseTest { + @ParameterizedTest + @MethodSource("adbByProtocol") + void getVersion(ArangoDB adb) { + final ArangoDBVersion version = adb.getVersion(); + assertThat(version.getServer()).isNotNull(); + assertThat(version.getVersion()).isNotNull(); + } +} diff --git a/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java b/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java new file mode 100644 index 000000000..3fcbb5aa8 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/arch/BaseTest.java @@ -0,0 +1,50 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.ContentType; +import com.arangodb.DbName; +import com.arangodb.Protocol; +import com.arangodb.config.ArangoConfigProperties; +import org.junit.jupiter.params.provider.Arguments; + +import java.util.Arrays; +import java.util.stream.Stream; + +public class BaseTest { + private static final ArangoConfigProperties config = ConfigUtils.loadConfig(); + protected static final DbName TEST_DB = DbName.of("java_driver_integration_tests"); + + protected static ArangoDB createAdb() { + return new ArangoDB.Builder() + .loadProperties(config) + .build(); + } + + protected static ArangoDB createAdb(ContentType contentType) { + Protocol protocol = contentType == ContentType.VPACK ? Protocol.HTTP2_VPACK : Protocol.HTTP2_JSON; + return new ArangoDB.Builder() + .loadProperties(config) + .useProtocol(protocol) + .build(); + } + + protected static ArangoDB createAdb(Protocol protocol) { + return new ArangoDB.Builder() + .loadProperties(config) + .useProtocol(protocol) + .build(); + } + + protected static Stream adbByProtocol() { + return Arrays.stream(Protocol.values()) + .map(BaseTest::createAdb) + .map(Arguments::of); + } + + protected static Stream adbByContentType() { + return Arrays.stream(ContentType.values()) + .map(BaseTest::createAdb) + .map(Arguments::of); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/arch/ConfigUtils.java b/shaded-integration-tests/src/test/jackson/java/arch/ConfigUtils.java new file mode 100644 index 000000000..9f18a7bb8 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/arch/ConfigUtils.java @@ -0,0 +1,19 @@ +package arch; + +import com.arangodb.config.ArangoConfigProperties; + +public class ConfigUtils { + + public static ArangoConfigProperties loadConfig() { + return ArangoConfigProperties.fromFile(); + } + + public static ArangoConfigProperties loadConfig(final String location) { + return ArangoConfigProperties.fromFile(location); + } + + public static ArangoConfigProperties loadConfig(final String location, final String prefix) { + return ArangoConfigProperties.fromFile(location, prefix); + } + +} diff --git a/shaded-integration-tests/src/test/jackson/java/arch/Person.java b/shaded-integration-tests/src/test/jackson/java/arch/Person.java new file mode 100644 index 000000000..a168c9d0c --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/arch/Person.java @@ -0,0 +1,13 @@ +package arch; + +import com.arangodb.serde.jackson.Key; +import com.fasterxml.jackson.annotation.JsonProperty; + +public record Person( + @Key + String key, + @JsonProperty("firstName") + String name, + int age +) { +} diff --git a/shaded-integration-tests/src/test/jackson/java/arch/RelocationsTest.java b/shaded-integration-tests/src/test/jackson/java/arch/RelocationsTest.java new file mode 100644 index 000000000..761556d78 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/arch/RelocationsTest.java @@ -0,0 +1,56 @@ +package arch; + +import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests; +import com.tngtech.archunit.junit.AnalyzeClasses; +import com.tngtech.archunit.junit.ArchTest; +import com.tngtech.archunit.lang.ArchRule; + +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; + + +@AnalyzeClasses(packages = "com.arangodb..", importOptions = {DoNotIncludeTests.class}) +public class RelocationsTest { + + @ArchTest + public static final ArchRule nettyRelocation = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("io.netty.."); + + @ArchTest + public static final ArchRule vertxRelocation = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("io.vertx.."); + + @ArchTest + public static final ArchRule jacksonRelocation = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.jackson.dataformat.velocypack..").and() + .resideOutsideOfPackage("com.arangodb.serde.jackson..") + .should().dependOnClassesThat() + .resideInAPackage("com.fasterxml.jackson.."); + + @ArchTest + public static final ArchRule jacksonDataformatVelocypackRelocation = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.jackson.dataformat.velocypack..").and() + .resideOutsideOfPackage("com.arangodb.serde.jackson..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.jackson.dataformat.velocypack.."); + + @ArchTest + public static final ArchRule noJsonbDependency = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.serde.jsonb.."); + + @ArchTest + // jackson-serde is accessed via SPI + public static final ArchRule noExplicitDependencyOnJacksonSerde = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.serde.jackson..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.serde.jackson.."); + +} diff --git a/shaded-integration-tests/src/test/jackson/java/arch/SerdeTest.java b/shaded-integration-tests/src/test/jackson/java/arch/SerdeTest.java new file mode 100644 index 000000000..91b2e0831 --- /dev/null +++ b/shaded-integration-tests/src/test/jackson/java/arch/SerdeTest.java @@ -0,0 +1,81 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.shaded.fasterxml.jackson.databind.JsonNode; +import com.arangodb.shaded.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.arangodb.util.RawJson; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Collections; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class SerdeTest extends BaseTest { + + @ParameterizedTest + @MethodSource("adbByContentType") + void shadedJsonNode(ArangoDB adb) { + // uses the internal serde + JsonNode doc = JsonNodeFactory.instance + .objectNode() + .put("foo", "bar"); + JsonNode res = adb.db().query("return @d", Collections.singletonMap("d", doc), JsonNode.class).next(); + assertThat(res.size()).isEqualTo(1); + assertThat(res.get("foo").asText()).isEqualTo("bar"); + JsonNode value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), JsonNode.class).next(); + assertThat(value.textValue()).isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void jsonNode(ArangoDB adb) { + // uses the user serde + com.fasterxml.jackson.databind.JsonNode doc = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance + .objectNode() + .put("foo", "bar"); + com.fasterxml.jackson.databind.JsonNode res = adb.db().query("return @d", Collections.singletonMap("d", doc), + com.fasterxml.jackson.databind.JsonNode.class).next(); + assertThat(res.size()).isEqualTo(1); + assertThat(res.get("foo").asText()).isEqualTo("bar"); + com.fasterxml.jackson.databind.JsonNode value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), + com.fasterxml.jackson.databind.JsonNode.class).next(); + assertThat(value.textValue()).isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void map(ArangoDB adb) { + Map doc = Collections.singletonMap("foo", "bar"); + Map res = adb.db().query("return @d", Collections.singletonMap("d", doc), Map.class).next(); + assertThat(res).hasSize(1); + assertThat(res.get("foo")).isEqualTo("bar"); + String value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), String.class).next(); + assertThat(value).isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void rawJson(ArangoDB adb) { + RawJson doc = RawJson.of(""" + {"foo":"bar"}"""); + RawJson res = adb.db().query("return @d", Collections.singletonMap("d", doc), RawJson.class).next(); + assertThat(res.getValue()).isEqualTo(doc.getValue()); + RawJson value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), RawJson.class).next(); + assertThat(value.getValue()).isEqualTo("\"bar\""); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void person(ArangoDB adb) { + Person doc = new Person("key", "Jim", 22); + Person res = adb.db().query("return @d", Collections.singletonMap("d", doc), Person.class).next(); + assertThat(res).isEqualTo(doc); + String key = adb.db().query("return @d._key", Collections.singletonMap("d", doc), String.class).next(); + assertThat(key).isEqualTo("key"); + String name = adb.db().query("return @d.firstName", Collections.singletonMap("d", doc), String.class).next(); + assertThat(name).isEqualTo("Jim"); + } + +} diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/AdbTest.java b/shaded-integration-tests/src/test/jsonb/java/arch/AdbTest.java new file mode 100644 index 000000000..fc320db4e --- /dev/null +++ b/shaded-integration-tests/src/test/jsonb/java/arch/AdbTest.java @@ -0,0 +1,18 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.entity.ArangoDBVersion; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.assertj.core.api.Assertions.assertThat; + +class AdbTest extends BaseTest { + @ParameterizedTest + @MethodSource("adbByProtocol") + void getVersion(ArangoDB adb) { + final ArangoDBVersion version = adb.getVersion(); + assertThat(version.getServer()).isNotNull(); + assertThat(version.getVersion()).isNotNull(); + } +} diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/BaseTest.java b/shaded-integration-tests/src/test/jsonb/java/arch/BaseTest.java new file mode 100644 index 000000000..661742202 --- /dev/null +++ b/shaded-integration-tests/src/test/jsonb/java/arch/BaseTest.java @@ -0,0 +1,76 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.ContentType; +import com.arangodb.DbName; +import com.arangodb.Protocol; +import com.arangodb.config.ArangoConfigProperties; +import com.arangodb.internal.serde.ContentTypeFactory; +import org.junit.jupiter.params.provider.Arguments; + +import java.util.Arrays; +import java.util.Locale; +import java.util.stream.Stream; + +public class BaseTest { + private static final ArangoConfigProperties config = ConfigUtils.loadConfig(); + protected static final DbName TEST_DB = DbName.of("java_driver_integration_tests"); + protected static final String HOST = "172.28.0.1"; + protected static final int PORT = 8529; + protected static final String PASSWD = "test"; + private static final Serde serde = Serde.valueOf(System.getProperty("serde").toUpperCase(Locale.ROOT)); + + private enum Serde { + JACKSON, JSONB + } + + protected static ArangoDB createAdb() { + return new ArangoDB.Builder() + .host(HOST, PORT) + .password(PASSWD) + .build(); + } + + protected static ArangoDB createAdb(ContentType contentType) { + Protocol protocol = contentType == ContentType.VPACK ? Protocol.HTTP2_VPACK : Protocol.HTTP2_JSON; + return new ArangoDB.Builder() + .host(HOST, PORT) + .password(PASSWD) + .useProtocol(protocol) + .build(); + } + + protected static ArangoDB createAdb(Protocol protocol) { + return new ArangoDB.Builder() + .host(HOST, PORT) + .password(PASSWD) + .useProtocol(protocol) + .build(); + } + + protected static Stream adbByProtocol() { + return Arrays.stream(Protocol.values()) + .filter(BaseTest::isProtocolSupported) + .map(BaseTest::createAdb) + .map(Arguments::of); + } + + protected static Stream adbByContentType() { + return Arrays.stream(ContentType.values()) + .filter(BaseTest::isContentTypeSupported) + .map(BaseTest::createAdb) + .map(Arguments::of); + } + + private static boolean isProtocolSupported(Protocol protocol) { + return isContentTypeSupported(ContentTypeFactory.of(protocol)); + } + + private static boolean isContentTypeSupported(ContentType contentType) { + if (serde == Serde.JACKSON) { + return true; + } else { + return contentType == ContentType.JSON; + } + } +} diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/ConfigUtils.java b/shaded-integration-tests/src/test/jsonb/java/arch/ConfigUtils.java new file mode 100644 index 000000000..9f18a7bb8 --- /dev/null +++ b/shaded-integration-tests/src/test/jsonb/java/arch/ConfigUtils.java @@ -0,0 +1,19 @@ +package arch; + +import com.arangodb.config.ArangoConfigProperties; + +public class ConfigUtils { + + public static ArangoConfigProperties loadConfig() { + return ArangoConfigProperties.fromFile(); + } + + public static ArangoConfigProperties loadConfig(final String location) { + return ArangoConfigProperties.fromFile(location); + } + + public static ArangoConfigProperties loadConfig(final String location, final String prefix) { + return ArangoConfigProperties.fromFile(location, prefix); + } + +} diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/Person.java b/shaded-integration-tests/src/test/jsonb/java/arch/Person.java new file mode 100644 index 000000000..c67dab135 --- /dev/null +++ b/shaded-integration-tests/src/test/jsonb/java/arch/Person.java @@ -0,0 +1,61 @@ +package arch; + + +import com.arangodb.serde.jsonb.Key; +import jakarta.json.bind.annotation.JsonbProperty; + +import java.util.Objects; + +public class Person { + @Key + private String key; + @JsonbProperty("firstName") + private String name; + private int age; + + public Person() { + } + + public Person(String key, String name, int age) { + this.key = key; + this.name = name; + this.age = age; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Person person = (Person) o; + return age == person.age && Objects.equals(key, person.key) && Objects.equals(name, person.name); + } + + @Override + public int hashCode() { + return Objects.hash(key, name, age); + } +} \ No newline at end of file diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/RelocationsTest.java b/shaded-integration-tests/src/test/jsonb/java/arch/RelocationsTest.java new file mode 100644 index 000000000..b78a416bb --- /dev/null +++ b/shaded-integration-tests/src/test/jsonb/java/arch/RelocationsTest.java @@ -0,0 +1,46 @@ +package arch; + +import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests; +import com.tngtech.archunit.junit.AnalyzeClasses; +import com.tngtech.archunit.junit.ArchTest; +import com.tngtech.archunit.lang.ArchRule; + +import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; + + +@AnalyzeClasses(packages = "com.arangodb..", importOptions = {DoNotIncludeTests.class}) +public class RelocationsTest { + + @ArchTest + public static final ArchRule nettyRelocation = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("io.netty.."); + + @ArchTest + public static final ArchRule vertxRelocation = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("io.vertx.."); + + @ArchTest + public static final ArchRule noJacksonDependency = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("com.fasterxml.jackson.."); + + @ArchTest + public static final ArchRule noJacksonDataformatVelocypackDependency = noClasses().that() + .resideInAPackage("com.arangodb..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.jackson.dataformat.velocypack.."); + + @ArchTest + // jsonb-serde is accessed via SPI + public static final ArchRule noExplicitDependencyOnJsonbSerde = noClasses().that() + .resideInAPackage("com.arangodb..").and() + .resideOutsideOfPackage("com.arangodb.serde.jsonb..") + .should().dependOnClassesThat() + .resideInAPackage("com.arangodb.serde.jsonb.."); + +} diff --git a/shaded-integration-tests/src/test/jsonb/java/arch/SerdeTest.java b/shaded-integration-tests/src/test/jsonb/java/arch/SerdeTest.java new file mode 100644 index 000000000..c679a4310 --- /dev/null +++ b/shaded-integration-tests/src/test/jsonb/java/arch/SerdeTest.java @@ -0,0 +1,66 @@ +package arch; + +import com.arangodb.ArangoDB; +import com.arangodb.util.RawJson; +import jakarta.json.*; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Collections; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class SerdeTest extends BaseTest { + + @ParameterizedTest + @MethodSource("adbByContentType") + void jsonNode(ArangoDB adb) { + JsonObject doc = Json.createObjectBuilder() + .add("foo", "bar") + .build(); + JsonObject res = adb.db().query("return @d", Collections.singletonMap("d", doc), JsonObject.class).next(); + assertThat(res.size()).isEqualTo(1); + assertThat(res.getString("foo")).isEqualTo("bar"); + JsonValue value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), JsonValue.class).next(); + assertThat(value) + .isInstanceOf(JsonString.class) + .extracting(v -> ((JsonString) v).getString()) + .isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void map(ArangoDB adb) { + Map doc = Collections.singletonMap("foo", "bar"); + Map res = adb.db().query("return @d", Collections.singletonMap("d", doc), Map.class).next(); + assertThat(res).hasSize(1); + assertThat(res.get("foo")).isEqualTo("bar"); + String value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), String.class).next(); + assertThat(value).isEqualTo("bar"); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void rawJson(ArangoDB adb) { + RawJson doc = RawJson.of(""" + {"foo":"bar"}"""); + RawJson res = adb.db().query("return @d", Collections.singletonMap("d", doc), RawJson.class).next(); + assertThat(res.getValue()).isEqualTo(doc.getValue()); + RawJson value = adb.db().query("return @d.foo", Collections.singletonMap("d", doc), RawJson.class).next(); + assertThat(value.getValue()).isEqualTo("\"bar\""); + } + + @ParameterizedTest + @MethodSource("adbByContentType") + void person(ArangoDB adb) { + Person doc = new Person("key", "Jim", 22); + Person res = adb.db().query("return @d", Collections.singletonMap("d", doc), Person.class).next(); + assertThat(res).isEqualTo(doc); + String key = adb.db().query("return @d._key", Collections.singletonMap("d", doc), String.class).next(); + assertThat(key).isEqualTo("key"); + String name = adb.db().query("return @d.firstName", Collections.singletonMap("d", doc), String.class).next(); + assertThat(name).isEqualTo("Jim"); + } + +} diff --git a/shaded-integration-tests/src/test/native/java/com b/shaded-integration-tests/src/test/native/java/com new file mode 120000 index 000000000..9af9cd5c2 --- /dev/null +++ b/shaded-integration-tests/src/test/native/java/com @@ -0,0 +1 @@ +../../../../../driver/src/test/java/com \ No newline at end of file diff --git a/shaded-integration-tests/src/test/resources b/shaded-integration-tests/src/test/resources new file mode 120000 index 000000000..88e279d36 --- /dev/null +++ b/shaded-integration-tests/src/test/resources @@ -0,0 +1 @@ +../../../driver/src/test/resources \ No newline at end of file diff --git a/shaded/pom.xml b/shaded/pom.xml new file mode 100644 index 000000000..40db119e9 --- /dev/null +++ b/shaded/pom.xml @@ -0,0 +1,195 @@ + + + 4.0.0 + + + com.arangodb + arangodb-java-driver-parent + 7.0.0-ALPHA.2 + + + arangodb-java-driver-shaded + arangodb-java-driver-shaded + ArangoDB Java Driver Shaded + + + false + com.arangodb.driver + + + + + com.arangodb + core + + + com.arangodb + http-protocol + + + com.arangodb + vst-protocol + + + com.arangodb + jackson-dataformat-velocypack + + + org.slf4j + slf4j-api + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + maven-shade-plugin + 3.4.1 + + + shade-core-dependencies + package + + shade + + + true + true + + + org.slf4j:slf4j-api + + + + + com.fasterxml.jackson + com.arangodb.shaded.fasterxml.jackson + + + com.arangodb.jackson.dataformat.velocypack + com.arangodb.shaded.jackson.dataformat.velocypack + + + io.netty + com.arangodb.shaded.netty + + + io.vertx + com.arangodb.shaded.vertx + + + + + com.arangodb:core + + META-INF/** + + + + com.arangodb:vst-protocol + + META-INF/** + + + + com.arangodb:http-protocol + + META-INF/MANIFEST.MF + META-INF/services/** + + + + com.arangodb:velocypack + + META-INF/** + + + + com.arangodb:jackson-dataformat-velocypack + + META-INF/** + + + + com.fasterxml.jackson.core:* + + META-INF/** + module-info.class + + + + io.netty:* + + META-INF/** + + + + io.vertx:* + + *.adoc + examples/** + META-INF/** + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.4.0 + + + unpack-shaded-sources + package + + unpack + + + + + com.arangodb + arangodb-java-driver-shaded + jar + sources + ${project.build.directory}/shaded-sources + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + ${project.build.directory}/shaded-sources + + com.arangodb.shaded.**,**.internal**,com.arangodb.vst.**,com.arangodb.http.**,com.arangodb.velocypack.** + + + + + + + org.codehaus.mojo + flatten-maven-plugin + + + + + \ No newline at end of file diff --git a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/native-image.properties b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/native-image.properties new file mode 100644 index 000000000..ecbea5c1b --- /dev/null +++ b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/native-image.properties @@ -0,0 +1,9 @@ +Args=\ +-H:ResourceConfigurationResources=${.}/resource-config.json \ +-H:ReflectionConfigurationResources=${.}/reflect-config.json,${.}/netty-reflect-config.json \ +-H:SerializationConfigurationResources=${.}/serialization-config.json \ +--initialize-at-run-time=\ + com.arangodb.shaded.netty.handler.ssl.BouncyCastleAlpnSslUtils,\ + com.arangodb.shaded.netty.handler.codec.compression.ZstdOptions \ +-Dcom.arangodb.shaded.netty.noUnsafe=true \ +-Dcom.arangodb.shaded.netty.leakDetection.level=DISABLED diff --git a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/netty-reflect-config.json b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/netty-reflect-config.json new file mode 100644 index 000000000..f0ec33a5b --- /dev/null +++ b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/netty-reflect-config.json @@ -0,0 +1,923 @@ +[ + { + "name": "com.arangodb.shaded.netty.buffer.AbstractByteBufAllocator", + "queryAllDeclaredMethods": true + }, + { + "name": "com.arangodb.shaded.netty.buffer.AbstractReferenceCountedByteBuf", + "fields": [ + { + "name": "refCnt" + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.ChannelDuplexHandler", + "methods": [ + { + "name": "bind", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "connect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "deregister", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "disconnect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "flush", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "read", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "write", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.ChannelHandlerAdapter", + "methods": [ + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.ChannelInboundHandlerAdapter", + "methods": [ + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRegistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelUnregistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.ChannelInitializer", + "methods": [ + { + "name": "channelRegistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.ChannelOutboundHandlerAdapter", + "methods": [ + { + "name": "bind", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "close", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "connect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "deregister", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "disconnect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "flush", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "read", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.CombinedChannelDuplexHandler", + "methods": [ + { + "name": "bind", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRegistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelUnregistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "close", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "connect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "deregister", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "disconnect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "flush", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "read", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "write", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.DefaultChannelPipeline$HeadContext", + "methods": [ + { + "name": "bind", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRegistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelUnregistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "close", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "connect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "deregister", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "disconnect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "flush", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "read", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "write", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.channel.DefaultChannelPipeline$TailContext", + "methods": [ + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRegistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelUnregistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.handler.codec.MessageToMessageDecoder", + "methods": [ + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.handler.codec.MessageToMessageEncoder", + "methods": [ + { + "name": "write", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.handler.codec.dns.DatagramDnsQueryEncoder" + }, + { + "name": "com.arangodb.shaded.netty.handler.codec.http.HttpClientCodec" + }, + { + "name": "com.arangodb.shaded.netty.handler.codec.http2.Http2ConnectionHandler", + "methods": [ + { + "name": "bind", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "close", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "connect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "deregister", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "disconnect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "flush", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "read", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "write", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.handler.logging.LoggingHandler", + "methods": [ + { + "name": "bind", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRegistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelUnregistered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "close", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "connect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.net.SocketAddress", + "java.net.SocketAddress", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "deregister", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "disconnect", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "flush", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "write", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.resolver.dns.DnsNameResolver$1" + }, + { + "name": "com.arangodb.shaded.netty.resolver.dns.DnsNameResolver$3" + }, + { + "name": "com.arangodb.shaded.netty.resolver.dns.DnsNameResolver$DnsResponseHandler", + "methods": [ + { + "name": "channelActive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.netty.util.ReferenceCountUtil", + "queryAllDeclaredMethods": true + }, + { + "name": "com.arangodb.shaded.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields", + "fields": [ + { + "name": "producerLimit" + } + ] + }, + { + "name": "com.arangodb.shaded.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields", + "fields": [ + { + "name": "consumerIndex" + } + ] + }, + { + "name": "com.arangodb.shaded.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields", + "fields": [ + { + "name": "producerIndex" + } + ] + }, + { + "name": "com.arangodb.shaded.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField", + "fields": [ + { + "name": "consumerIndex" + } + ] + }, + { + "name": "com.arangodb.shaded.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField", + "fields": [ + { + "name": "producerIndex" + } + ] + }, + { + "name": "com.arangodb.shaded.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField", + "fields": [ + { + "name": "producerLimit" + } + ] + }, + { + "name": "com.arangodb.shaded.vertx.core.http.impl.VertxHttp2ConnectionHandler", + "methods": [ + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + } + ] + }, + { + "name": "com.arangodb.shaded.vertx.core.logging.SLF4JLogDelegateFactory", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "name": "com.arangodb.shaded.vertx.core.net.impl.ChannelProvider$2" + }, + { + "name": "com.arangodb.shaded.vertx.core.net.impl.VertxHandler", + "methods": [ + { + "name": "channelInactive", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelRead", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + }, + { + "name": "channelReadComplete", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "channelWritabilityChanged", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext" + ] + }, + { + "name": "close", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "com.arangodb.shaded.netty.channel.ChannelPromise" + ] + }, + { + "name": "exceptionCaught", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Throwable" + ] + }, + { + "name": "userEventTriggered", + "parameterTypes": [ + "com.arangodb.shaded.netty.channel.ChannelHandlerContext", + "java.lang.Object" + ] + } + ] + } +] diff --git a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/reflect-config.json b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/reflect-config.json new file mode 100644 index 000000000..f4b9641c1 --- /dev/null +++ b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/reflect-config.json @@ -0,0 +1,1502 @@ +[ + { + "name": "com.arangodb.internal.serde.InternalSerializers$FieldLinksSerializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalSerializers$CollectionLinksSerializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalSerializers$CollectionSchemaRuleSerializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalDeserializers$CollectionLinksDeserializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalDeserializers$CollectionSchemaRuleDeserializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.serde.InternalDeserializers$FieldLinksDeserializer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ViewEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AbstractBaseDocument", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerRole", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor$SatelliteReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties$BreakMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerFeature", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBEngine$StorageEngineName", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasIndex$OperationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.StreamTransactionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryExecutionState", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryCachePropertiesEntity$CacheMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevelEntity$LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.StoreValuesType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LoadBalancingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort$Field$Direction", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.IndexType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ArangoSearchCompression", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.License", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzerCase", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties$ReturnType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StreamType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.KeyType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ViewType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties$GeoJSONAnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ShardingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ConsolidationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.Permissions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionRevisionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryOptimizerRule", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort$Field", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.ClassificationAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasIndex", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.MetaAware", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.IndexEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlParseEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.EdgeDefinition", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.MultiDocumentEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionVariable", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryCachePropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.GraphEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlFunctionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DatabaseEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.PrimarySort", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.EdgeNgram", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionNode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.TransactionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBEngine", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.UserEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ErrorEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.FieldLink", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlParseEntity$AstNode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoAnalyzerOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ShardEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryOptimizerRule$Flags", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionCollection", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NearestNeighborsAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.PipelineAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor$NumericReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.EdgeDefinition$Options", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBVersion", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.MinHashAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ConsolidationPolicy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.KeyOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionPlan", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevelEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CursorWarning", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CursorStats", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.StreamTransactionEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogEntriesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.CollectionLink", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.StoredValue", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentImportEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzerProperties", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryTrackingPropertiesEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogEntriesEntity$Message", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexField", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionExpression", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.BaseEdgeDocument", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.BaseDocument", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.EdgeUpdateEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentCreateEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.VertexUpdateEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentDeleteEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.VertexEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.DocumentUpdateEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.EdgeEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.IdentityAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.PipelineAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NearestNeighborsAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.MinHashAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.ClassificationAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerRole", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ReplicationFactor$SatelliteReplicationFactor", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties$BreakMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerFeature", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ArangoDBEngine$StorageEngineName", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.SearchAliasIndex$OperationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.StreamTransactionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryExecutionState", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.QueryCachePropertiesEntity$CacheMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LogLevelEntity$LogLevel", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.StoreValuesType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.LoadBalancingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.InvertedIndexPrimarySort$Field$Direction", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.IndexType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ArangoSearchCompression", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.License", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionStatus", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzerCase", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties$ReturnType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.StreamType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.CollectionType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.KeyType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ViewType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ServerMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.AnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties$GeoJSONAnalyzerType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.ShardingStrategy", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.arangosearch.ConsolidationType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.Permissions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.IndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentImportOptions$OnDuplicate", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.OverwriteMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ImportType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.LogOptions$SortOrder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ComputedValue$ComputeOn", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionSchema$Level", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ZKDIndexOptions$FieldValueTypes", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentReadOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryOptions$Optimizer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DBCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlFunctionDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.AnalyzerDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.UserUpdateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.StreamTransactionOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentReplaceOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DatabaseUsersOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ViewRenameOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.SearchAliasPropertiesOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryExplainOptions$Options", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ViewCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexCollectionCreateOptions$Options", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.ArangoSearchOptionsBuilder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryParseOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.UserAccessOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ComputedValue", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.EdgeUpdateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexCollectionCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.ArangoSearchCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.EdgeCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.GraphCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionsReadOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.TransactionOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionTruncateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionSchema", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentImportOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryOptions$Options", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.EdgeReplaceOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexReplaceOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.GraphDocumentReadOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentUpdateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.VertexUpdateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.OptionsBuilder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.TransactionCollectionOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.LogOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.UserCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionPropertiesOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DatabaseOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.GraphCreateOptions$SmartOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionCountOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.EdgeDeleteOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.SearchAliasOptionsBuilder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionRenameOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.arangosearch.SearchAliasCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentExistsOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlFunctionGetOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlFunctionCreateOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryExplainOptions$Optimizer", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.AqlQueryExplainOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.QueueTimeSample", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.SkiplistIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.GeoIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.TtlIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.FulltextIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.HashIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ZKDIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.InvertedIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.PersistentIndexOptions", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.DocumentImportOptions$OnDuplicate", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.OverwriteMode", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ImportType", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.LogOptions$SortOrder", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ComputedValue$ComputeOn", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.CollectionSchema$Level", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.model.ZKDIndexOptions$FieldValueTypes", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.entity.MetaAware", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.cursor.entity.InternalCursorEntity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.arangodb.internal.cursor.entity.InternalCursorEntity$Extras", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + } +] diff --git a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/resource-config.json b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/resource-config.json new file mode 100644 index 000000000..3bb430bb1 --- /dev/null +++ b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/resource-config.json @@ -0,0 +1,10 @@ +{ + "resources": { + "includes": [ + { + "pattern": "META-INF/vertx/vertx-version.txt" + } + ] + }, + "bundles": [] +} diff --git a/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/serialization-config.json b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/serialization-config.json new file mode 100644 index 000000000..7160b9bd4 --- /dev/null +++ b/shaded/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver-shaded/serialization-config.json @@ -0,0 +1,14 @@ +[ + { + "name": "com.arangodb.entity.ErrorEntity" + }, + { + "name": "com.arangodb.ArangoDBException" + }, + { + "name": "com.arangodb.ArangoDBMultipleException" + }, + { + "name": "com.arangodb.internal.net.ArangoDBRedirectException" + } +] diff --git a/shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider b/shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider new file mode 100644 index 000000000..dc7f09560 --- /dev/null +++ b/shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider @@ -0,0 +1 @@ +com.arangodb.vst.VstAsyncProtocolProvider diff --git a/shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider b/shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider new file mode 100644 index 000000000..faf8cac63 --- /dev/null +++ b/shaded/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider @@ -0,0 +1,2 @@ +com.arangodb.http.HttpProtocolProvider +com.arangodb.vst.VstProtocolProvider diff --git a/shaded/src/main/resources/META-INF/services/com.arangodb.shaded.fasterxml.jackson.core.JsonFactory b/shaded/src/main/resources/META-INF/services/com.arangodb.shaded.fasterxml.jackson.core.JsonFactory new file mode 100644 index 000000000..89123f5a5 --- /dev/null +++ b/shaded/src/main/resources/META-INF/services/com.arangodb.shaded.fasterxml.jackson.core.JsonFactory @@ -0,0 +1,2 @@ +com.arangodb.shaded.fasterxml.jackson.core.JsonFactory +com.arangodb.shaded.jackson.dataformat.velocypack.VPackFactory diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java deleted file mode 100644 index bb149d55c..000000000 --- a/src/main/java/com/arangodb/ArangoDB.java +++ /dev/null @@ -1,1055 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.*; -import com.arangodb.internal.ArangoContext; -import com.arangodb.internal.ArangoDBImpl; -import com.arangodb.internal.ArangoDefaults; -import com.arangodb.internal.InternalArangoDBBuilder; -import com.arangodb.internal.http.HttpCommunication; -import com.arangodb.internal.http.HttpConnectionFactory; -import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.internal.net.Host; -import com.arangodb.internal.net.HostHandle; -import com.arangodb.internal.net.HostHandler; -import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.util.ArangoDeserializerImpl; -import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializerImpl; -import com.arangodb.internal.util.DefaultArangoSerialization; -import com.arangodb.internal.velocystream.VstCommunicationSync; -import com.arangodb.internal.velocystream.VstConnectionFactorySync; -import com.arangodb.model.DBCreateOptions; -import com.arangodb.model.LogOptions; -import com.arangodb.model.UserCreateOptions; -import com.arangodb.model.UserUpdateOptions; -import com.arangodb.util.*; -import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPackAnnotationFieldFilter; -import com.arangodb.velocypack.VPackAnnotationFieldNaming; -import com.arangodb.velocypack.VPackDeserializer; -import com.arangodb.velocypack.VPackInstanceCreator; -import com.arangodb.velocypack.VPackJsonDeserializer; -import com.arangodb.velocypack.VPackJsonSerializer; -import com.arangodb.velocypack.VPackModule; -import com.arangodb.velocypack.VPackParser; -import com.arangodb.velocypack.VPackParserModule; -import com.arangodb.velocypack.VPackSerializer; -import com.arangodb.velocypack.ValueType; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; -import org.apache.http.client.HttpRequestRetryHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLContext; -import java.io.InputStream; -import java.lang.annotation.Annotation; -import java.util.Collection; -import java.util.Locale; -import java.util.Properties; - -/** - * Central access point for applications to communicate with an ArangoDB server. - * - *

    - * Will be instantiated through {@link ArangoDB.Builder} - *

    - * - *
    - * ArangoDB arango = new ArangoDB.Builder().build();
    - * ArangoDB arango = new ArangoDB.Builder().host("127.0.0.1", 8529).build();
    - * 
    - * - * @author Mark Vollmary - * @author Michele Rastelli - */ -@SuppressWarnings("UnusedReturnValue") -public interface ArangoDB extends ArangoSerializationAccessor { - - /** - * Builder class to build an instance of {@link ArangoDB}. - * - * @author Mark Vollmary - */ - class Builder extends InternalArangoDBBuilder { - private static final Logger logger = LoggerFactory.getLogger(Builder.class); - private static final String PROPERTY_KEY_PROTOCOL = "arangodb.protocol"; - - protected Protocol protocol; - - public Builder() { - super(); - } - - @Override - protected void loadProperties(final Properties properties) { - super.loadProperties(properties); - protocol = loadProtocol(properties, protocol); - } - - private static Protocol loadProtocol(final Properties properties, final Protocol currentValue) { - return Protocol.valueOf( - getProperty(properties, PROPERTY_KEY_PROTOCOL, currentValue, ArangoDefaults.DEFAULT_NETWORK_PROTOCOL) - .toUpperCase(Locale.ENGLISH)); - } - - public Builder useProtocol(final Protocol protocol) { - this.protocol = protocol; - return this; - } - - @Override - public Builder loadProperties(final InputStream in) throws ArangoDBException { - super.loadProperties(in); - return this; - } - - /** - * Adds a host to connect to. Multiple hosts can be added to provide fallbacks. - * - * @param host address of the host - * @param port port of the host - * @return {@link ArangoDB.Builder} - */ - public Builder host(final String host, final int port) { - setHost(host, port); - return this; - } - - /** - * Sets the connection and request timeout in milliseconds. - * - * @param timeout timeout in milliseconds - * @return {@link ArangoDB.Builder} - */ - public Builder timeout(final Integer timeout) { - setTimeout(timeout); - return this; - } - - /** - * Sets the username to use for authentication. - * - * @param user the user in the database (default: {@code root}) - * @return {@link ArangoDB.Builder} - */ - public Builder user(final String user) { - setUser(user); - return this; - } - - /** - * Sets the password for the user for authentication. - * - * @param password the password of the user in the database (default: {@code null}) - * @return {@link ArangoDB.Builder} - */ - public Builder password(final String password) { - setPassword(password); - return this; - } - - /** - * Sets the JWT for the user authentication. - * - * @param jwt token to use (default: {@code null}) - * @return {@link ArangoDB.Builder} - */ - public Builder jwt(final String jwt) { - setJwt(jwt); - return this; - } - - /** - * If set to {@code true} SSL will be used when connecting to an ArangoDB server. - * - * @param useSsl whether or not use SSL (default: {@code false}) - * @return {@link ArangoDB.Builder} - */ - public Builder useSsl(final Boolean useSsl) { - setUseSsl(useSsl); - return this; - } - - /** - * Sets the SSL context to be used when {@code true} is passed through {@link #useSsl(Boolean)}. - * - * @param sslContext SSL context to be used - * @return {@link ArangoDB.Builder} - */ - public Builder sslContext(final SSLContext sslContext) { - setSslContext(sslContext); - return this; - } - - /** - * Sets the {@link javax.net.ssl.HostnameVerifier} to be used when using ssl with http protocol. - * - * @param hostnameVerifier HostnameVerifier to be used - * @return {@link ArangoDB.Builder} - */ - public Builder hostnameVerifier(final HostnameVerifier hostnameVerifier) { - setHostnameVerifier(hostnameVerifier); - return this; - } - - /** - * Sets the {@link HttpRequestRetryHandler} to be used when using http protocol. - * - * @param httpRequestRetryHandler HttpRequestRetryHandler to be used - * @return {@link ArangoDB.Builder} - *

    - *

    - * NOTE: - * Some ArangoDB HTTP endpoints do not honor RFC-2616 HTTP 1.1 specification in respect to - * 9.1 Safe and Idempotent Methods. - * Please refer to HTTP API Documentation for details. - */ - public Builder httpRequestRetryHandler(final HttpRequestRetryHandler httpRequestRetryHandler) { - setHttpRequestRetryHandler(httpRequestRetryHandler); - return this; - } - - /** - * Sets the chunk size when {@link Protocol#VST} is used. - * - * @param chunksize size of a chunk in bytes - * @return {@link ArangoDB.Builder} - */ - public Builder chunksize(final Integer chunksize) { - setChunksize(chunksize); - return this; - } - - /** - * Sets the maximum number of connections the built in connection pool will open per host. - * - *

    - * Defaults: - *

    - * - *
    -         * {@link Protocol#VST} == 1
    -         * {@link Protocol#HTTP_JSON} == 20
    -         * {@link Protocol#HTTP_VPACK} == 20
    -         * 
    - * - * @param maxConnections max number of connections - * @return {@link ArangoDB.Builder} - */ - public Builder maxConnections(final Integer maxConnections) { - setMaxConnections(maxConnections); - return this; - } - - /** - * Set the maximum time to life of a connection. After this time the connection will be closed automatically. - * - * @param connectionTtl the maximum time to life of a connection in milliseconds - * @return {@link ArangoDB.Builder} - */ - public Builder connectionTtl(final Long connectionTtl) { - setConnectionTtl(connectionTtl); - return this; - } - - /** - * Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request every - * {@code keepAliveInterval} seconds, to avoid to be closed due to inactivity by the server (or by the external - * environment, eg. firewall, intermediate routers, operating system). - * - * @param keepAliveInterval interval in seconds - * @return {@link ArangoDB.Builder} - */ - public Builder keepAliveInterval(final Integer keepAliveInterval) { - setKeepAliveInterval(keepAliveInterval); - return this; - } - - /** - * Whether or not the driver should acquire a list of available coordinators in an ArangoDB cluster or a single - * server with active failover. - * In case of Active-Failover deployment set to {@code true} to enable automatic master discovery. - * - *

    - * The host list will be used for failover and load balancing. - *

    - * - * @param acquireHostList whether or not automatically acquire a list of available hosts (default: false) - * @return {@link ArangoDB.Builder} - */ - public Builder acquireHostList(final Boolean acquireHostList) { - setAcquireHostList(acquireHostList); - return this; - } - - /** - * Setting the Interval for acquireHostList - * - * @param acquireHostListInterval Interval in milliseconds - * @return {@link ArangoDB.Builder} - */ - public Builder acquireHostListInterval(final Integer acquireHostListInterval) { - setAcquireHostListInterval(acquireHostListInterval); - return this; - } - - /** - * Sets the load balancing strategy to be used in an ArangoDB cluster setup. - * In case of Active-Failover deployment set to {@link LoadBalancingStrategy#NONE} or not set at all, since that - * would be the default. - * - * @param loadBalancingStrategy the load balancing strategy to be used (default: {@link LoadBalancingStrategy#NONE} - * @return {@link ArangoDB.Builder} - */ - public Builder loadBalancingStrategy(final LoadBalancingStrategy loadBalancingStrategy) { - setLoadBalancingStrategy(loadBalancingStrategy); - return this; - } - - /** - * Setting the amount of samples kept for queue time metrics - * - * @param responseQueueTimeSamples amount of samples to keep - * @return {@link ArangoDB.Builder} - */ - public Builder responseQueueTimeSamples(final Integer responseQueueTimeSamples) { - setResponseQueueTimeSamples(responseQueueTimeSamples); - return this; - } - - /** - * Register a custom {@link VPackSerializer} for a specific type to be used within the internal serialization - * process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param clazz the type the serializer should be registered for - * @param serializer serializer to register - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerSerializer(final Class clazz, final VPackSerializer serializer) { - vpackBuilder.registerSerializer(clazz, serializer); - return this; - } - - /** - * Register a special serializer for a member class which can only be identified by its enclosing class. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param clazz the type of the enclosing class - * @param serializer serializer to register - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerEnclosingSerializer(final Class clazz, final VPackSerializer serializer) { - vpackBuilder.registerEnclosingSerializer(clazz, serializer); - return this; - } - - /** - * Register a custom {@link VPackDeserializer} for a specific type to be used within the internal serialization - * process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param clazz the type the serializer should be registered for - * @param deserializer - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerDeserializer(final Class clazz, final VPackDeserializer deserializer) { - vpackBuilder.registerDeserializer(clazz, deserializer); - return this; - } - - /** - * Register a custom {@link VPackInstanceCreator} for a specific type to be used within the internal - * serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param clazz the type the instance creator should be registered for - * @param creator - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerInstanceCreator(final Class clazz, final VPackInstanceCreator creator) { - vpackBuilder.registerInstanceCreator(clazz, creator); - return this; - } - - /** - * Register a custom {@link VPackJsonDeserializer} for a specific type to be used within the internal - * serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param type the type the serializer should be registered for - * @param deserializer - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonDeserializer(final ValueType type, final VPackJsonDeserializer deserializer) { - vpackParserBuilder.registerDeserializer(type, deserializer); - return this; - } - - /** - * Register a custom {@link VPackJsonDeserializer} for a specific type and attribute name to be used within the - * internal serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param attribute - * @param type the type the serializer should be registered for - * @param deserializer - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonDeserializer( - final String attribute, - final ValueType type, - final VPackJsonDeserializer deserializer) { - vpackParserBuilder.registerDeserializer(attribute, type, deserializer); - return this; - } - - /** - * Register a custom {@link VPackJsonSerializer} for a specific type to be used within the internal - * serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param clazz the type the serializer should be registered for - * @param serializer - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonSerializer(final Class clazz, final VPackJsonSerializer serializer) { - vpackParserBuilder.registerSerializer(clazz, serializer); - return this; - } - - /** - * Register a custom {@link VPackJsonSerializer} for a specific type and attribute name to be used within the - * internal serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param attribute - * @param clazz the type the serializer should be registered for - * @param serializer - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonSerializer( - final String attribute, - final Class clazz, - final VPackJsonSerializer serializer) { - vpackParserBuilder.registerSerializer(attribute, clazz, serializer); - return this; - } - - /** - * Register a custom {@link VPackAnnotationFieldFilter} for a specific type to be used within the internal - * serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param type the type the serializer should be registered for - * @param fieldFilter - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder annotationFieldFilter( - final Class type, - final VPackAnnotationFieldFilter fieldFilter) { - vpackBuilder.annotationFieldFilter(type, fieldFilter); - return this; - } - - /** - * Register a custom {@link VPackAnnotationFieldNaming} for a specific type to be used within the internal - * serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param type the type the serializer should be registered for - * @param fieldNaming - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see
    Reference Documentation - */ - @Deprecated - public Builder annotationFieldNaming( - final Class type, - final VPackAnnotationFieldNaming fieldNaming) { - vpackBuilder.annotationFieldNaming(type, fieldNaming); - return this; - } - - /** - * Register a {@link VPackModule} to be used within the internal serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param module module to register - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see
    Reference Documentation - */ - @Deprecated - public Builder registerModule(final VPackModule module) { - vpackBuilder.registerModule(module); - return this; - } - - /** - * Register a list of {@link VPackModule} to be used within the internal serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param modules modules to register - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see Reference Documentation - */ - @Deprecated - public Builder registerModules(final VPackModule... modules) { - vpackBuilder.registerModules(modules); - return this; - } - - /** - * Register a {@link VPackParserModule} to be used within the internal serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param module module to register - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonModule(final VPackParserModule module) { - vpackParserBuilder.registerModule(module); - return this; - } - - /** - * Register a list of {@link VPackParserModule} to be used within the internal serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param modules modules to register - * @return {@link ArangoDB.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonModules(final VPackParserModule... modules) { - vpackParserBuilder.registerModules(modules); - return this; - } - - /** - * Replace the built-in serializer with the given serializer. - *

    - *
    - * ATTENTION!: Use at your own risk - * - * @param serializer custom serializer - * @return {@link ArangoDB.Builder} - * @deprecated use {@link #serializer(ArangoSerialization)} instead - */ - @Deprecated - public Builder setSerializer(final ArangoSerializer serializer) { - serializer(serializer); - return this; - } - - /** - * Replace the built-in deserializer with the given deserializer. - *

    - *
    - * ATTENTION!: Use at your own risk - * - * @param deserializer custom deserializer - * @return {@link ArangoDB.Builder} - * @deprecated use {@link #serializer(ArangoSerialization)} instead - */ - @Deprecated - public Builder setDeserializer(final ArangoDeserializer deserializer) { - deserializer(deserializer); - return this; - } - - /** - * Replace the built-in serializer/deserializer with the given one. - *

    - *
    - * ATTENTION!: Any registered custom serializer/deserializer or module will be ignored. - * - * @param serialization custom serializer/deserializer - * @return {@link ArangoDB.Builder} - */ - public Builder serializer(final ArangoSerialization serialization) { - setSerializer(serialization); - return this; - } - - /** - * Returns an instance of {@link ArangoDB}. - * - * @return {@link ArangoDB} - */ - public synchronized ArangoDB build() { - if (customSerializer == null) { - logger.warn("Usage of VelocyPack Java serialization is now deprecated for removal. " + - "Future driver versions will only support Jackson serialization (for both JSON and VPACK formats). " + - "Please configure according to: https://www.arangodb.com/docs/stable/drivers/java-reference-serialization.html"); - } - if (hosts.isEmpty()) { - hosts.add(host); - } - final VPack vpacker = vpackBuilder.serializeNullValues(false).build(); - final VPack vpackerNull = vpackBuilder.serializeNullValues(true).build(); - final VPackParser vpackParser = vpackParserBuilder.build(); - final ArangoSerializer serializerTemp = serializer != null ? serializer - : new ArangoSerializerImpl(vpacker, vpackerNull, vpackParser); - final ArangoDeserializer deserializerTemp = deserializer != null ? deserializer - : new ArangoDeserializerImpl(vpackerNull, vpackParser); - final DefaultArangoSerialization internal = new DefaultArangoSerialization(serializerTemp, - deserializerTemp); - final ArangoSerialization custom = customSerializer != null ? customSerializer : internal; - final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); - - int protocolMaxConnections = protocol == Protocol.VST ? - ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT : - ArangoDefaults.MAX_CONNECTIONS_HTTP_DEFAULT; - final int max = maxConnections != null ? Math.max(1, maxConnections) : protocolMaxConnections; - - final ConnectionFactory connectionFactory = (protocol == null || Protocol.VST == protocol) - ? new VstConnectionFactorySync(host, timeout, connectionTtl, keepAliveInterval, useSsl, sslContext) - : new HttpConnectionFactory(timeout, user, password, useSsl, sslContext, hostnameVerifier, custom, - protocol, connectionTtl, httpCookieSpec, httpRequestRetryHandler); - - final Collection hostList = createHostList(max, connectionFactory); - final HostResolver hostResolver = createHostResolver(hostList, max, connectionFactory); - final HostHandler hostHandler = createHostHandler(hostResolver); - hostHandler.setJwt(jwt); - - return new ArangoDBImpl( - new VstCommunicationSync.Builder(hostHandler).timeout(timeout).user(user).password(password) - .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize) - .maxConnections(maxConnections).connectionTtl(connectionTtl), - new HttpCommunication.Builder(hostHandler), - util, - protocol, - hostResolver, - hostHandler, - new ArangoContext(), - responseQueueTimeSamples, timeout); - } - - } - - /** - * Releases all connections to the server and clear the connection pool. - * - * @throws ArangoDBException - */ - void shutdown() throws ArangoDBException; - - /** - * Updates the JWT used for requests authorization. It does not change already existing VST connections, since VST - * connections are authenticated during the initialization phase. - * - * @param jwt token to use - */ - void updateJwt(String jwt); - - /** - * Returns a {@code ArangoDatabase} instance for the {@code _system} database. - * - * @return database handler - */ - ArangoDatabase db(); - - /** - * Returns a {@code ArangoDatabase} instance for the given database name. - * - * @param name Name of the database - * @return database handler - * @deprecated Use {@link #db(DbName)} instead - */ - @Deprecated - default ArangoDatabase db(String name) { - return db(DbName.of(name)); - } - - /** - * Returns a {@code ArangoDatabase} instance for the given database name. - * - * @param dbName Name of the database - * @return database handler - */ - ArangoDatabase db(DbName dbName); - - /** - * @return entry point for accessing client metrics - */ - ArangoMetrics metrics(); - - /** - * Creates a new database with the given name. - * - * @param name Name of the database to create - * @return true if the database was created successfully. - * @throws ArangoDBException - * @see API - * Documentation - * @deprecated Use {@link #createDatabase(DbName)} instead - */ - @Deprecated - default Boolean createDatabase(String name) throws ArangoDBException { - return createDatabase(DbName.of(name)); - } - - /** - * Creates a new database with the given name. - * - * @param dbName Name of the database to create - * @return true if the database was created successfully. - * @throws ArangoDBException - * @see API - * Documentation - */ - Boolean createDatabase(DbName dbName) throws ArangoDBException; - - /** - * Creates a new database with the given name. - * - * @param options Creation options - * @return true if the database was created successfully. - * @throws ArangoDBException - * @see API - * Documentation - * @since ArangoDB 3.6.0 - */ - Boolean createDatabase(DBCreateOptions options) throws ArangoDBException; - - /** - * Retrieves a list of all existing databases - * - * @return a list of all existing databases - * @throws ArangoDBException - * @see API - * Documentation - */ - Collection getDatabases() throws ArangoDBException; - - /** - * Retrieves a list of all databases the current user can access - * - * @return a list of all databases the current user can access - * @throws ArangoDBException - * @see API - * Documentation - */ - Collection getAccessibleDatabases() throws ArangoDBException; - - /** - * List available database to the specified user - * - * @param user The name of the user for which you want to query the databases - * @return list of database names which are available for the specified user - * @throws ArangoDBException - * @see API - * Documentation - */ - Collection getAccessibleDatabasesFor(String user) throws ArangoDBException; - - /** - * Returns the server name and version number. - * - * @return the server version, number - * @throws ArangoDBException - * @see API - * Documentation - */ - ArangoDBVersion getVersion() throws ArangoDBException; - - /** - * Returns the server storage engine. - * - * @return the storage engine name - * @throws ArangoDBException - * @see API - * Documentation - */ - ArangoDBEngine getEngine() throws ArangoDBException; - - /** - * Returns the server role. - * - * @return the server role - * @throws ArangoDBException - */ - ServerRole getRole() throws ArangoDBException; - - /** - * Returns the id of a server in a cluster. - * - * @return the server id - * @throws ArangoDBException - * @see API - * Documentation - */ - String getServerId() throws ArangoDBException; - - /** - * Create a new user. This user will not have access to any database. You need permission to the _system database in - * order to execute this call. - * - * @param user The name of the user - * @param passwd The user password - * @return information about the user - * @throws ArangoDBException - * @see API Documentation - */ - UserEntity createUser(String user, String passwd) throws ArangoDBException; - - /** - * Create a new user. This user will not have access to any database. You need permission to the _system database in - * order to execute this call. - * - * @param user The name of the user - * @param passwd The user password - * @param options Additional options, can be null - * @return information about the user - * @throws ArangoDBException - * @see API Documentation - */ - UserEntity createUser(String user, String passwd, UserCreateOptions options) throws ArangoDBException; - - /** - * Removes an existing user, identified by user. You need access to the _system database. - * - * @param user The name of the user - * @throws ArangoDBException - * @see API Documentation - */ - void deleteUser(String user) throws ArangoDBException; - - /** - * Fetches data about the specified user. You can fetch information about yourself or you need permission to the - * _system database in order to execute this call. - * - * @param user The name of the user - * @return information about the user - * @throws ArangoDBException - * @see API Documentation - */ - UserEntity getUser(String user) throws ArangoDBException; - - /** - * Fetches data about all users. You can only execute this call if you have access to the _system database. - * - * @return informations about all users - * @throws ArangoDBException - * @see API - * Documentation - */ - Collection getUsers() throws ArangoDBException; - - /** - * Partially updates the data of an existing user. The name of an existing user must be specified in user. You can - * only change the password of your self. You need access to the _system database to change the active flag. - * - * @param user The name of the user - * @param options Properties of the user to be changed - * @return information about the user - * @throws ArangoDBException - * @see API Documentation - */ - UserEntity updateUser(String user, UserUpdateOptions options) throws ArangoDBException; - - /** - * Replaces the data of an existing user. The name of an existing user must be specified in user. You can only - * change the password of your self. You need access to the _system database to change the active flag. - * - * @param user The name of the user - * @param options Additional properties of the user, can be null - * @return information about the user - * @throws ArangoDBException - * @see API - * Documentation - */ - UserEntity replaceUser(String user, UserUpdateOptions options) throws ArangoDBException; - - /** - * Sets the default access level for databases for the user {@code user}. You need permission to the _system - * database in order to execute this call. - * - * @param user The name of the user - * @param permissions The permissions the user grant - * @throws ArangoDBException - * @since ArangoDB 3.2.0 - */ - void grantDefaultDatabaseAccess(String user, Permissions permissions) throws ArangoDBException; - - /** - * Sets the default access level for collections for the user {@code user}. You need permission to the _system - * database in order to execute this call. - * - * @param user The name of the user - * @param permissions The permissions the user grant - * @throws ArangoDBException - * @since ArangoDB 3.2.0 - */ - void grantDefaultCollectionAccess(String user, Permissions permissions) throws ArangoDBException; - - /** - * Generic Execute. Use this method to execute custom FOXX services. - * - * @param request VelocyStream request - * @return VelocyStream response - * @throws ArangoDBException - */ - Response execute(Request request) throws ArangoDBException; - - /** - * Generic Execute. Use this method to execute custom FOXX services. - * - * @param request VelocyStream request - * @param hostHandle Used to stick to a specific host when using {@link LoadBalancingStrategy#ROUND_ROBIN} - * @return VelocyStream response - * @throws ArangoDBException - */ - Response execute(Request request, HostHandle hostHandle) throws ArangoDBException; - - /** - * Returns fatal, error, warning or info log messages from the server's global log. - * - * @param options Additional options, can be null - * @return the log messages - * @throws ArangoDBException - * @see API - * Documentation - * @deprecated use {@link #getLogEntries(LogOptions)} instead - */ - @Deprecated - LogEntity getLogs(LogOptions options) throws ArangoDBException; - - /** - * Returns the server logs - * - * @param options Additional options, can be null - * @return the log messages - * @see API - * Documentation - * @since ArangoDB 3.8 - */ - LogEntriesEntity getLogEntries(LogOptions options) throws ArangoDBException; - - /** - * Returns the server's current loglevel settings. - * - * @return the server's current loglevel settings - * @throws ArangoDBException - * @since ArangoDB 3.1.0 - */ - LogLevelEntity getLogLevel() throws ArangoDBException; - - /** - * Modifies and returns the server's current loglevel settings. - * - * @param entity loglevel settings - * @return the server's current loglevel settings - * @throws ArangoDBException - * @since ArangoDB 3.1.0 - */ - LogLevelEntity setLogLevel(LogLevelEntity entity) throws ArangoDBException; - - /** - * Attention: Please do not use! - * - * @param cursorInitializer - * @return ArangoDB - */ - ArangoDB _setCursorInitializer(ArangoCursorInitializer cursorInitializer); - -} diff --git a/src/main/java/com/arangodb/ArangoIterable.java b/src/main/java/com/arangodb/ArangoIterable.java deleted file mode 100644 index 40ab262bc..000000000 --- a/src/main/java/com/arangodb/ArangoIterable.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import java.util.Collection; -import java.util.stream.Stream; - -/** - * @author Mark Vollmary - */ -public interface ArangoIterable extends Iterable { - - @Override - ArangoIterator iterator(); - - Stream stream(); - - /** - * Performs the given action for each element of the {@code ArangoIterable} - * - * @param action - * a action to perform on the elements - * @deprecated Use {@link #forEach(java.util.function.Consumer)} instead. - */ - @Deprecated - void foreach(Consumer action); - - /** - * Returns a {@code ArangoIterable} consisting of the results of applying the given function to the elements of this - * {@code ArangoIterable}. - * - * @param mapper - * a function to apply to each element - * @return the new {@code ArangoIterable} - * - * @deprecated Use {@link #stream()} and {@link Stream#map(java.util.function.Function)} instead. - */ - @Deprecated - ArangoIterable map(Function mapper); - - /** - * Returns a {@code ArangoIterable} consisting of the elements of this {@code ArangoIterable} that match the given - * predicate. - * - * @param predicate - * a predicate to apply to each element to determine if it should be included - * @return the new {@code ArangoIterable} - * - * @deprecated Use {@link #stream()} and {@link Stream#filter(java.util.function.Predicate)} instead. - */ - @Deprecated - ArangoIterable filter(Predicate predicate); - - /** - * Returns the first element or {@code null} if no element exists. - * - * @return first element or {@code null} - * @deprecated Use {@link #stream()} and {@link Stream#findFirst()} instead. - */ - @Deprecated - T first(); - - /** - * Returns the count of elements of this {@code ArangoIterable}. - * - * @return the count of elements - * @deprecated Use {@link #stream()} and {@link Stream#count()} instead. - */ - @Deprecated - long count(); - - /** - * Returns whether any elements of this {@code ArangoIterable} match the provided predicate. - * - * @param predicate a predicate to apply to elements of this {@code ArangoIterable} - * @return {@code true} if any elements of the {@code ArangoIterable} match the provided predicate, otherwise - * {@code false} - * @deprecated Use {@link #stream()} and {@link Stream#anyMatch(java.util.function.Predicate)} instead. - */ - @Deprecated - boolean anyMatch(Predicate predicate); - - /** - * Returns whether all elements of this {@code ArangoIterable} match the provided predicate. - * - * @param predicate a predicate to apply to elements of this {@code ArangoIterable} - * @return {@code true} if all elements of the {@code ArangoIterable} match the provided predicate, otherwise - * {@code false} - * @deprecated Use {@link #stream()} and {@link Stream#allMatch(java.util.function.Predicate)} instead. - */ - @Deprecated - boolean allMatch(Predicate predicate); - - /** - * Returns whether no elements of this {@code ArangoIterable} match the provided predicate. - * - * @param predicate a predicate to apply to elements of this {@code ArangoIterable} - * @return {@code true} if no elements of the {@code ArangoIterable} match the provided predicate, otherwise - * {@code false} - * @deprecated Use {@link #stream()} and {@link Stream#noneMatch(java.util.function.Predicate)} instead. - */ - @Deprecated - boolean noneMatch(Predicate predicate); - - /** - * Iterates over all elements of this {@code ArangoIterable} and adds each to the given target. - * - * @param target the collection to insert into - * @return the filled target - * @deprecated Use {@link #stream()} and {@link Stream#collect} instead. - */ - @Deprecated - > R collectInto(R target); - -} diff --git a/src/main/java/com/arangodb/ArangoRoute.java b/src/main/java/com/arangodb/ArangoRoute.java deleted file mode 100644 index fd32eb6e5..000000000 --- a/src/main/java/com/arangodb/ArangoRoute.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.velocystream.Response; - -/** - * Interface for a specific path to be used to perform arbitrary requests. - * - * @author Mark Vollmary - */ -public interface ArangoRoute extends ArangoSerializationAccessor { - - /** - * Returns a new {@link ArangoRoute} instance for the given path (relative to the current route) that can be used to - * perform arbitrary requests. - * - * @param path The relative URL of the route - * @return {@link ArangoRoute} - */ - ArangoRoute route(String... path); - - /** - * Header that should be sent with each request to the route. - * - * @param key Header key - * @param value Header value (the {@code toString()} method will be called for the value} - * @return {@link ArangoRoute} - */ - ArangoRoute withHeader(String key, Object value); - - /** - * Query parameter that should be sent with each request to the route. - * - * @param key Query parameter key - * @param value Query parameter value (the {@code toString()} method will be called for the value} - * @return {@link ArangoRoute} - */ - ArangoRoute withQueryParam(String key, Object value); - - /** - * The response body. The body will be serialized to {@link com.arangodb.velocypack.VPackSlice}. - * - * @param body The request body - * @return {@link ArangoRoute} - */ - ArangoRoute withBody(Object body); - - /** - * Performs a DELETE request to the given URL and returns the server response. - * - * @return server response - * @throws ArangoDBException - */ - Response delete() throws ArangoDBException; - - /** - * Performs a GET request to the given URL and returns the server response. - * - * @return server response - * @throws ArangoDBException - */ - - Response get() throws ArangoDBException; - - /** - * Performs a HEAD request to the given URL and returns the server response. - * - * @return server response - * @throws ArangoDBException - */ - - Response head() throws ArangoDBException; - - /** - * Performs a PATCH request to the given URL and returns the server response. - * - * @return server response - * @throws ArangoDBException - */ - - Response patch() throws ArangoDBException; - - /** - * Performs a POST request to the given URL and returns the server response. - * - * @return server response - * @throws ArangoDBException - */ - - Response post() throws ArangoDBException; - - /** - * Performs a PUT request to the given URL and returns the server response. - * - * @return server response - * @throws ArangoDBException - */ - - Response put() throws ArangoDBException; - -} diff --git a/src/main/java/com/arangodb/ArangoSerializationAccessor.java b/src/main/java/com/arangodb/ArangoSerializationAccessor.java deleted file mode 100644 index f140f054e..000000000 --- a/src/main/java/com/arangodb/ArangoSerializationAccessor.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; -import com.arangodb.util.ArangoSerialization; - -/** - * @author Mark Vollmary - */ -public interface ArangoSerializationAccessor { - - /** - * Returns driver internal serialization API for serializing and deserializing Java POJOs to/from {@link com.arangodb.velocypack.VPackSlice} - * - * @return ArangoSerialization - */ - ArangoSerialization util(); - - /** - * Returns serialization API for serializing and deserializing Java POJOs to/from {@link com.arangodb.velocypack.VPackSlice} by the given - * type - * - * @param serializer type of serializer - * @return ArangoSerialization - */ - ArangoSerialization util(Serializer serializer); - -} diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java deleted file mode 100644 index ed4eb8ed3..000000000 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ /dev/null @@ -1,923 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async; - -import com.arangodb.*; -import com.arangodb.async.internal.ArangoDBAsyncImpl; -import com.arangodb.async.internal.velocystream.VstCommunicationAsync; -import com.arangodb.async.internal.velocystream.VstConnectionFactoryAsync; -import com.arangodb.entity.*; -import com.arangodb.internal.ArangoContext; -import com.arangodb.internal.ArangoDefaults; -import com.arangodb.internal.InternalArangoDBBuilder; -import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.internal.net.HostHandler; -import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.util.ArangoDeserializerImpl; -import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializerImpl; -import com.arangodb.internal.util.DefaultArangoSerialization; -import com.arangodb.internal.velocystream.VstCommunicationSync; -import com.arangodb.internal.velocystream.VstConnectionFactorySync; -import com.arangodb.model.DBCreateOptions; -import com.arangodb.model.LogOptions; -import com.arangodb.model.UserCreateOptions; -import com.arangodb.model.UserUpdateOptions; -import com.arangodb.util.ArangoDeserializer; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.ArangoSerializer; -import com.arangodb.velocypack.*; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.SSLContext; -import java.io.InputStream; -import java.lang.annotation.Annotation; -import java.util.Collection; -import java.util.concurrent.CompletableFuture; - -/** - * Central access point for applications to communicate with an ArangoDB server. - * - *

    - * Will be instantiated through {@link ArangoDBAsync.Builder} - *

    - * - *
    - * ArangoDBAsync arango = new ArangoDBAsync.Builder().build();
    - * ArangoDBAsync arango = new ArangoDBAsync.Builder().host("127.0.0.1", 8529).build();
    - * 
    - * - * @author Mark Vollmary - */ -public interface ArangoDBAsync extends ArangoSerializationAccessor { - - void shutdown() throws ArangoDBException; - - /** - * Updates the JWT used for requests authorization. It does not change already existing VST connections, since VST - * connections are authenticated during the initialization phase. - * - * @param jwt token to use - */ - void updateJwt(String jwt); - - /** - * Returns a handler of the system database - * - * @return database handler - */ - ArangoDatabaseAsync db(); - - /** - * Returns a handler of the database by the given name - * - * @param name Name of the database - * @return database handler - * @deprecated Use {@link #db(DbName)} instead - */ - @Deprecated - default ArangoDatabaseAsync db(final String name) { - return db(DbName.of(name)); - } - - /** - * Returns a handler of the database by the given name - * - * @param dbName Name of the database - * @return database handler - */ - ArangoDatabaseAsync db(final DbName dbName); - - /** - * @return entry point for accessing client metrics - */ - ArangoMetrics metrics(); - - /** - * Creates a new database - * - * @param name Has to contain a valid database name - * @return true if the database was created successfully. - * @see API - * Documentation - * @deprecated Use {@link #createDatabase(DbName)} instead - */ - @Deprecated - default CompletableFuture createDatabase(final String name) { - return createDatabase(DbName.of(name)); - } - - /** - * Creates a new database - * - * @param dbName database name - * @return true if the database was created successfully. - * @see API - * Documentation - */ - CompletableFuture createDatabase(final DbName dbName); - - /** - * Creates a new database - * - * @param options Creation options - * @return true if the database was created successfully. - * @see API - * Documentation - * @since ArangoDB 3.6.0 - */ - CompletableFuture createDatabase(final DBCreateOptions options); - - /** - * Retrieves a list of all existing databases - * - * @return a list of all existing databases - * @see API - * Documentation - */ - CompletableFuture> getDatabases(); - - /** - * Retrieves a list of all databases the current user can access - * - * @return a list of all databases the current user can access - * @see API - * Documentation - */ - CompletableFuture> getAccessibleDatabases(); - - /** - * List available database to the specified user - * - * @param user The name of the user for which you want to query the databases - * @return - * @see API - * Documentation - */ - CompletableFuture> getAccessibleDatabasesFor(final String user); - - /** - * Returns the server name and version number. - * - * @return the server version, number - * @see API - * Documentation - */ - CompletableFuture getVersion(); - - /** - * Returns the server role. - * - * @return the server role - */ - CompletableFuture getRole(); - - /** - * Create a new user. This user will not have access to any database. You need permission to the _system database in - * order to execute this call. - * - * @param user The name of the user - * @param passwd The user password - * @return information about the user - * @see API Documentation - */ - CompletableFuture createUser(final String user, final String passwd); - - /** - * Create a new user. This user will not have access to any database. You need permission to the _system database in - * order to execute this call. - * - * @param user The name of the user - * @param passwd The user password - * @param options Additional properties of the user, can be null - * @return information about the user - * @see API Documentation - */ - CompletableFuture createUser(final String user, final String passwd, final UserCreateOptions options); - - /** - * Removes an existing user, identified by user. You need access to the _system database. - * - * @param user The name of the user - * @return void - * @see API Documentation - */ - CompletableFuture deleteUser(final String user); - - /** - * Fetches data about the specified user. You can fetch information about yourself or you need permission to the - * _system database in order to execute this call. - * - * @param user The name of the user - * @return information about the user - * @see API Documentation - */ - CompletableFuture getUser(final String user); - - /** - * Fetches data about all users. You can only execute this call if you have access to the _system database. - * - * @return informations about all users - * @see API - * Documentation - */ - CompletableFuture> getUsers(); - - /** - * Partially updates the data of an existing user. The name of an existing user must be specified in user. You can - * only change the password of your self. You need access to the _system database to change the active flag. - * - * @param user The name of the user - * @param options Properties of the user to be changed - * @return information about the user - * @see API Documentation - */ - CompletableFuture updateUser(final String user, final UserUpdateOptions options); - - /** - * Replaces the data of an existing user. The name of an existing user must be specified in user. You can only - * change the password of your self. You need access to the _system database to change the active flag. - * - * @param user The name of the user - * @param options Additional properties of the user, can be null - * @return information about the user - * @see API - * Documentation - */ - CompletableFuture replaceUser(final String user, final UserUpdateOptions options); - - /** - * Sets the default access level for databases for the user user. You need permission to the _system - * database in order to execute this call. - * - * @param user The name of the user - * @param permissions The permissions the user grant - * @return void - * @since ArangoDB 3.2.0 - */ - CompletableFuture grantDefaultDatabaseAccess(final String user, final Permissions permissions); - - /** - * Sets the default access level for collections for the user user. You need permission to the _system - * database in order to execute this call. - * - * @param user The name of the user - * @param permissions The permissions the user grant - * @return void - * @since ArangoDB 3.2.0 - */ - CompletableFuture grantDefaultCollectionAccess(final String user, final Permissions permissions); - - /** - * Generic Execute. Use this method to execute custom FOXX services. - * - * @param request VelocyStream request - * @return VelocyStream response - */ - CompletableFuture execute(final Request request); - - /** - * Returns fatal, error, warning or info log messages from the server's global log. - * - * @param options Additional options, can be null - * @return the log messages - * @see API - * Documentation - * @deprecated use {@link #getLogEntries(LogOptions)} instead - */ - @Deprecated - CompletableFuture getLogs(final LogOptions options); - - /** - * Returns the server logs - * - * @param options Additional options, can be null - * @return the log messages - * @see API - * Documentation - * @since ArangoDB 3.8 - */ - CompletableFuture getLogEntries(final LogOptions options); - - /** - * Returns the server's current loglevel settings. - * - * @return the server's current loglevel settings - */ - CompletableFuture getLogLevel(); - - /** - * Modifies and returns the server's current loglevel settings. - * - * @param entity loglevel settings - * @return the server's current loglevel settings - */ - CompletableFuture setLogLevel(final LogLevelEntity entity); - - /** - * Builder class to build an instance of {@link ArangoDBAsync}. - * - * @author Mark Vollmary - */ - @SuppressWarnings("unused") - class Builder extends InternalArangoDBBuilder { - - private static final Logger logger = LoggerFactory.getLogger(Builder.class); - - public Builder() { - super(); - } - - @Override - public Builder loadProperties(final InputStream in) throws ArangoDBException { - super.loadProperties(in); - return this; - } - - /** - * Adds a host to connect to. Multiple hosts can be added to provide fallbacks. - * - * @param host address of the host - * @param port port of the host - * @return {@link ArangoDBAsync.Builder} - */ - public Builder host(final String host, final int port) { - setHost(host, port); - return this; - } - - /** - * Sets the timeout in milliseconds. It is used as socket timeout when opening a VecloyStream. - * - * @param timeout timeout in milliseconds - * @return {@link ArangoDBAsync.Builder} - */ - public Builder timeout(final Integer timeout) { - setTimeout(timeout); - return this; - } - - /** - * Sets the username to use for authentication. - * - * @param user the user in the database (default: root) - * @return {@link ArangoDBAsync.Builder} - */ - public Builder user(final String user) { - setUser(user); - return this; - } - - /** - * Sets the password for the user for authentication. - * - * @param password the password of the user in the database (default: null) - * @return {@link ArangoDBAsync.Builder} - */ - public Builder password(final String password) { - setPassword(password); - return this; - } - - /** - * Sets the JWT for the user authentication. - * - * @param jwt token to use (default: {@code null}) - * @return {@link ArangoDBAsync.Builder} - */ - public Builder jwt(final String jwt) { - setJwt(jwt); - return this; - } - - /** - * If set to true SSL will be used when connecting to an ArangoDB server. - * - * @param useSsl whether or not use SSL (default: false) - * @return {@link ArangoDBAsync.Builder} - */ - public Builder useSsl(final Boolean useSsl) { - setUseSsl(useSsl); - return this; - } - - /** - * Sets the SSL context to be used when true is passed through {@link #useSsl(Boolean)}. - * - * @param sslContext SSL context to be used - * @return {@link ArangoDBAsync.Builder} - */ - public Builder sslContext(final SSLContext sslContext) { - setSslContext(sslContext); - return this; - } - - /** - * Sets the chunk size when {@link Protocol#VST} is used. - * - * @param chunksize size of a chunk in bytes - * @return {@link ArangoDBAsync.Builder} - */ - public Builder chunksize(final Integer chunksize) { - setChunksize(chunksize); - return this; - } - - /** - * Sets the maximum number of connections the built in connection pool will open. - * - *

    - * In an ArangoDB cluster setup with {@link LoadBalancingStrategy#ROUND_ROBIN} set, this value should be at - * least as high as the number of ArangoDB coordinators in the cluster. - *

    - * - * @param maxConnections max number of connections (default: 1) - * @return {@link ArangoDBAsync.Builder} - */ - public Builder maxConnections(final Integer maxConnections) { - setMaxConnections(maxConnections); - return this; - } - - /** - * Set the maximum time to life of a connection. After this time the connection will be closed automatically. - * - * @param connectionTtl the maximum time to life of a connection. - * @return {@link ArangoDBAsync.Builder} - */ - public Builder connectionTtl(final Long connectionTtl) { - setConnectionTtl(connectionTtl); - return this; - } - - /** - * Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request every - * {@code keepAliveInterval} seconds, to avoid to be closed due to inactivity by the server (or by the external - * environment, eg. firewall, intermediate routers, operating system). - * - * @param keepAliveInterval interval in seconds - * @return {@link ArangoDBAsync.Builder} - */ - public Builder keepAliveInterval(final Integer keepAliveInterval) { - setKeepAliveInterval(keepAliveInterval); - return this; - } - - /** - * Whether or not the driver should acquire a list of available coordinators in an ArangoDB cluster or a single - * server with active failover. - * In case of Active-Failover deployment set to {@code true} to enable automatic master discovery. - * - *

    - * The host list will be used for failover and load balancing. - *

    - * - * @param acquireHostList whether or not automatically acquire a list of available hosts (default: false) - * @return {@link ArangoDBAsync.Builder} - */ - public Builder acquireHostList(final Boolean acquireHostList) { - setAcquireHostList(acquireHostList); - return this; - } - - /** - * Setting the amount of samples kept for queue time metrics - * - * @param responseQueueTimeSamples amount of samples to keep - * @return {@link ArangoDBAsync.Builder} - */ - public Builder responseQueueTimeSamples(final Integer responseQueueTimeSamples) { - setResponseQueueTimeSamples(responseQueueTimeSamples); - return this; - } - - /** - * Sets the load balancing strategy to be used in an ArangoDB cluster setup. - * In case of Active-Failover deployment set to {@link LoadBalancingStrategy#NONE} or not set at all, since that - * would be the default. - * - * @param loadBalancingStrategy the load balancing strategy to be used (default: {@link LoadBalancingStrategy#NONE} - * @return {@link ArangoDBAsync.Builder} - */ - public Builder loadBalancingStrategy(final LoadBalancingStrategy loadBalancingStrategy) { - setLoadBalancingStrategy(loadBalancingStrategy); - return this; - } - - /** - * Register a custom {@link VPackSerializer} for a specific type to be used within the internal serialization - * process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param clazz the type the serializer should be registered for - * @param serializer serializer to register - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerSerializer(final Class clazz, final VPackSerializer serializer) { - vpackBuilder.registerSerializer(clazz, serializer); - return this; - } - - /** - * Register a special serializer for a member class which can only be identified by its enclosing class. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param clazz the type of the enclosing class - * @param serializer serializer to register - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerEnclosingSerializer(final Class clazz, final VPackSerializer serializer) { - vpackBuilder.registerEnclosingSerializer(clazz, serializer); - return this; - } - - /** - * Register a custom {@link VPackDeserializer} for a specific type to be used within the internal serialization - * process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param clazz the type the serializer should be registered for - * @param deserializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerDeserializer(final Class clazz, final VPackDeserializer deserializer) { - vpackBuilder.registerDeserializer(clazz, deserializer); - return this; - } - - /** - * Register a custom {@link VPackInstanceCreator} for a specific type to be used within the internal - * serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param clazz the type the instance creator should be registered for - * @param creator - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerInstanceCreator(final Class clazz, final VPackInstanceCreator creator) { - vpackBuilder.registerInstanceCreator(clazz, creator); - return this; - } - - /** - * Register a custom {@link VPackJsonDeserializer} for a specific type to be used within the internal - * serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param type the type the serializer should be registered for - * @param deserializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonDeserializer(final ValueType type, final VPackJsonDeserializer deserializer) { - vpackParserBuilder.registerDeserializer(type, deserializer); - return this; - } - - /** - * Register a custom {@link VPackJsonDeserializer} for a specific type and attribute name to be used within the - * internal serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param attribute - * @param type the type the serializer should be registered for - * @param deserializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonDeserializer( - final String attribute, - final ValueType type, - final VPackJsonDeserializer deserializer) { - vpackParserBuilder.registerDeserializer(attribute, type, deserializer); - return this; - } - - /** - * Register a custom {@link VPackJsonSerializer} for a specific type to be used within the internal - * serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param clazz the type the serializer should be registered for - * @param serializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonSerializer(final Class clazz, final VPackJsonSerializer serializer) { - vpackParserBuilder.registerSerializer(clazz, serializer); - return this; - } - - /** - * Register a custom {@link VPackJsonSerializer} for a specific type and attribute name to be used within the - * internal serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param attribute - * @param clazz the type the serializer should be registered for - * @param serializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonSerializer( - final String attribute, - final Class clazz, - final VPackJsonSerializer serializer) { - vpackParserBuilder.registerSerializer(attribute, clazz, serializer); - return this; - } - - /** - * Register a custom {@link VPackAnnotationFieldFilter} for a specific type to be used within the internal - * serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param type the type the serializer should be registered for - * @param fieldFilter - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see Reference Documentation - */ - @Deprecated - public Builder annotationFieldFilter( - final Class type, - final VPackAnnotationFieldFilter fieldFilter) { - vpackBuilder.annotationFieldFilter(type, fieldFilter); - return this; - } - - /** - * Register a custom {@link VPackAnnotationFieldNaming} for a specific type to be used within the internal - * serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param type the type the serializer should be registered for - * @param fieldNaming - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom serializers and deserializers by implementing {@link com.fasterxml.jackson.databind.JsonSerializer} and {@link com.fasterxml.jackson.databind.JsonDeserializer}. - * @see
    Reference Documentation - */ - @Deprecated - public Builder annotationFieldNaming( - final Class type, - final VPackAnnotationFieldNaming fieldNaming) { - vpackBuilder.annotationFieldNaming(type, fieldNaming); - return this; - } - - /** - * Register a {@link VPackModule} to be used within the internal serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param module module to register - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see
    Reference Documentation - */ - @Deprecated - public Builder registerModule(final VPackModule module) { - vpackBuilder.registerModule(module); - return this; - } - - /** - * Register a list of {@link VPackModule} to be used within the internal serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param modules modules to register - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see Reference Documentation - */ - @Deprecated - public Builder registerModules(final VPackModule... modules) { - vpackBuilder.registerModules(modules); - return this; - } - - /** - * Register a {@link VPackParserModule} to be used within the internal serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param module module to register - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonModule(final VPackParserModule module) { - vpackParserBuilder.registerModule(module); - return this; - } - - /** - * Register a list of {@link VPackParserModule} to be used within the internal serialization process. - * - *

    - * Attention:can not be used together with {@link #serializer(ArangoSerialization)} - *

    - * - * @param modules modules to register - * @return {@link ArangoDBAsync.Builder} - * @deprecated Use {@link com.arangodb.mapping.ArangoJack} instead and register custom modules. - * @see Reference Documentation - */ - @Deprecated - public Builder registerJsonModules(final VPackParserModule... modules) { - vpackParserBuilder.registerModules(modules); - return this; - } - - /** - * Replace the built-in serializer with the given serializer. - *

    - *
    - * ATTENTION!: Use at your own risk - * - * @param serializer custom serializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated use {@link #serializer(ArangoSerialization)} instead - */ - @Deprecated - public Builder setSerializer(final ArangoSerializer serializer) { - serializer(serializer); - return this; - } - - /** - * Replace the built-in deserializer with the given deserializer. - *

    - *
    - * ATTENTION!: Use at your own risk - * - * @param deserializer custom deserializer - * @return {@link ArangoDBAsync.Builder} - * @deprecated use {@link #serializer(ArangoSerialization)} instead - */ - @Deprecated - public Builder setDeserializer(final ArangoDeserializer deserializer) { - deserializer(deserializer); - return this; - } - - /** - * Replace the built-in serializer/deserializer with the given one. - *

    - *
    - * ATTENTION!: Any registered custom serializer/deserializer or module will be ignored. - * - * @param serialization custom serializer/deserializer - * @return {@link ArangoDBAsync.Builder} - */ - public Builder serializer(final ArangoSerialization serialization) { - setSerializer(serialization); - return this; - } - - /** - * Returns an instance of {@link ArangoDBAsync}. - * - * @return {@link ArangoDBAsync} - */ - public synchronized ArangoDBAsync build() { - if (customSerializer == null) { - logger.warn("Usage of VelocyPack Java serialization is now deprecated for removal. " + - "Future driver versions will only support Jackson serialization (for both JSON and VPACK formats). " + - "Please configure according to: https://www.arangodb.com/docs/stable/drivers/java-reference-serialization.html"); - } - if (hosts.isEmpty()) { - hosts.add(host); - } - final VPack vpacker = vpackBuilder.serializeNullValues(false).build(); - final VPack vpackerNull = vpackBuilder.serializeNullValues(true).build(); - final VPackParser vpackParser = vpackParserBuilder.build(); - final ArangoSerializer serializerTemp = serializer != null ? serializer - : new ArangoSerializerImpl(vpacker, vpackerNull, vpackParser); - final ArangoDeserializer deserializerTemp = deserializer != null ? deserializer - : new ArangoDeserializerImpl(vpackerNull, vpackParser); - final DefaultArangoSerialization internal = new DefaultArangoSerialization(serializerTemp, - deserializerTemp); - final ArangoSerialization custom = customSerializer != null ? customSerializer : internal; - final ArangoSerializationFactory util = new ArangoSerializationFactory(internal, custom); - - final int max = maxConnections != null ? Math.max(1, maxConnections) - : ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT; - final ConnectionFactory syncConnectionFactory = new VstConnectionFactorySync(host, timeout, connectionTtl, - keepAliveInterval, useSsl, sslContext); - final ConnectionFactory asyncConnectionFactory = new VstConnectionFactoryAsync(host, timeout, connectionTtl, - keepAliveInterval, useSsl, sslContext); - final HostResolver syncHostResolver = createHostResolver(createHostList(max, syncConnectionFactory), max, - syncConnectionFactory); - final HostResolver asyncHostResolver = createHostResolver(createHostList(max, asyncConnectionFactory), max, - asyncConnectionFactory); - final HostHandler syncHostHandler = createHostHandler(syncHostResolver); - final HostHandler asyncHostHandler = createHostHandler(asyncHostResolver); - return new ArangoDBAsyncImpl( - asyncBuilder(asyncHostHandler), - util, - syncBuilder(syncHostHandler), - asyncHostResolver, - syncHostResolver, - asyncHostHandler, - syncHostHandler, - new ArangoContext(), - responseQueueTimeSamples, - timeout); - } - - private VstCommunicationAsync.Builder asyncBuilder(final HostHandler hostHandler) { - return new VstCommunicationAsync.Builder(hostHandler).timeout(timeout).user(user).password(password) - .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections) - .connectionTtl(connectionTtl); - } - - private VstCommunicationSync.Builder syncBuilder(final HostHandler hostHandler) { - return new VstCommunicationSync.Builder(hostHandler).timeout(timeout).user(user).password(password) - .jwt(jwt).useSsl(useSsl).sslContext(sslContext).chunksize(chunksize).maxConnections(maxConnections) - .connectionTtl(connectionTtl); - } - - } -} diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java b/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java deleted file mode 100644 index 8f5b73ab9..000000000 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionAsync.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.internal.velocystream; - -import com.arangodb.async.internal.utils.CompletableFutureUtils; -import com.arangodb.internal.net.HostDescription; -import com.arangodb.internal.velocystream.internal.Chunk; -import com.arangodb.internal.velocystream.internal.Message; -import com.arangodb.internal.velocystream.internal.MessageStore; -import com.arangodb.internal.velocystream.internal.VstConnection; - -import javax.net.ssl.SSLContext; -import java.util.Collection; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; - -/** - * @author Mark Vollmary - */ -public class VstConnectionAsync extends VstConnection> { - - private VstConnectionAsync(final HostDescription host, final Integer timeout, final Long ttl, final Integer keepAliveInterval, - final Boolean useSsl, final SSLContext sslContext, final MessageStore messageStore) { - super(host, timeout, ttl, keepAliveInterval, useSsl, sslContext, messageStore); - } - - @Override - public synchronized CompletableFuture write(final Message message, final Collection chunks) { - final CompletableFuture future = new CompletableFuture<>(); - final FutureTask task = new FutureTask<>(() -> { - try { - future.complete(messageStore.get(message.getId())); - } catch (final Exception e) { - future.completeExceptionally(e); - } - return null; - }); - messageStore.storeMessage(message.getId(), task); - super.writeIntern(message, chunks); - if (timeout == null || timeout == 0L) { - return future; - } else { - return CompletableFutureUtils.orTimeout(future, timeout, TimeUnit.MILLISECONDS); - } - } - - @Override - protected void doKeepAlive() { - sendKeepAlive().join(); - } - - public static class Builder { - - private MessageStore messageStore; - private HostDescription host; - private Integer timeout; - private Long ttl; - private Integer keepAliveInterval; - private Boolean useSsl; - private SSLContext sslContext; - - public Builder() { - super(); - } - - public Builder messageStore(final MessageStore messageStore) { - this.messageStore = messageStore; - return this; - } - - public Builder host(final HostDescription host) { - this.host = host; - return this; - } - - public Builder timeout(final Integer timeout) { - this.timeout = timeout; - return this; - } - - public Builder ttl(final Long ttl) { - this.ttl = ttl; - return this; - } - - public Builder keepAliveInterval(final Integer keepAliveInterval) { - this.keepAliveInterval = keepAliveInterval; - return this; - } - - public Builder useSsl(final Boolean useSsl) { - this.useSsl = useSsl; - return this; - } - - public Builder sslContext(final SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - - public VstConnectionAsync build() { - return new VstConnectionAsync(host, timeout, ttl, keepAliveInterval, useSsl, sslContext, messageStore); - } - } - -} diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java b/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java deleted file mode 100644 index bd2380feb..000000000 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstConnectionFactoryAsync.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.internal.velocystream; - -import com.arangodb.internal.net.Connection; -import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.internal.net.HostDescription; -import com.arangodb.internal.velocystream.internal.MessageStore; - -import javax.net.ssl.SSLContext; - -/** - * @author Mark Vollmary - */ -public class VstConnectionFactoryAsync implements ConnectionFactory { - - private final VstConnectionAsync.Builder builder; - - public VstConnectionFactoryAsync(final HostDescription host, final Integer timeout, final Long connectionTtl, - final Integer keepAliveInterval, final Boolean useSsl, final SSLContext sslContext) { - super(); - builder = new VstConnectionAsync.Builder().timeout(timeout).ttl(connectionTtl) - .keepAliveInterval(keepAliveInterval).useSsl(useSsl) - .sslContext(sslContext); - } - - @Override - public Connection create(final HostDescription host) { - return builder.messageStore(new MessageStore()).host(host).build(); - } - -} diff --git a/src/main/java/com/arangodb/entity/BaseDocument.java b/src/main/java/com/arangodb/entity/BaseDocument.java deleted file mode 100644 index 2d6fe1967..000000000 --- a/src/main/java/com/arangodb/entity/BaseDocument.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.arangodb.internal.DocumentFields; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class BaseDocument implements Serializable { - - private static final long serialVersionUID = -1824742667228719116L; - - @Id - protected String id; - @Key - protected String key; - @Rev - protected String revision; - protected Map properties; - - public BaseDocument() { - super(); - properties = new HashMap<>(); - } - - public BaseDocument(final String key) { - this(); - this.key = key; - } - - public BaseDocument(final Map properties) { - this(); - final Object tmpId = properties.remove(DocumentFields.ID); - if (tmpId != null) { - id = tmpId.toString(); - } - final Object tmpKey = properties.remove(DocumentFields.KEY); - if (tmpKey != null) { - key = tmpKey.toString(); - } - final Object tmpRev = properties.remove(DocumentFields.REV); - if (tmpRev != null) { - revision = tmpRev.toString(); - } - this.properties = properties; - } - - public String getId() { - return id; - } - - public void setId(final String id) { - this.id = id; - } - - public String getKey() { - return key; - } - - public void setKey(final String key) { - this.key = key; - } - - public String getRevision() { - return revision; - } - - public void setRevision(final String revision) { - this.revision = revision; - } - - public Map getProperties() { - return properties; - } - - public void setProperties(final Map properties) { - this.properties = properties; - } - - public void addAttribute(final String key, final Object value) { - properties.put(key, value); - } - - public void updateAttribute(final String key, final Object value) { - if (properties.containsKey(key)) { - properties.put(key, value); - } - } - - public Object getAttribute(final String key) { - return properties.get(key); - } - - @Override - public String toString() { - return "BaseDocument [documentRevision=" + - revision + - ", documentHandle=" + - id + - ", documentKey=" + - key + - ", properties=" + - properties + - "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - result = prime * result + ((key == null) ? 0 : key.hashCode()); - result = prime * result + ((properties == null) ? 0 : properties.hashCode()); - result = prime * result + ((revision == null) ? 0 : revision.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final BaseDocument other = (BaseDocument) obj; - if (id == null) { - if (other.id != null) { - return false; - } - } else if (!id.equals(other.id)) { - return false; - } - if (key == null) { - if (other.key != null) { - return false; - } - } else if (!key.equals(other.key)) { - return false; - } - if (properties == null) { - if (other.properties != null) { - return false; - } - } else if (!properties.equals(other.properties)) { - return false; - } - if (revision == null) { - return other.revision == null; - } else return revision.equals(other.revision); - } - -} diff --git a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java b/src/main/java/com/arangodb/entity/BaseEdgeDocument.java deleted file mode 100644 index c76831b0a..000000000 --- a/src/main/java/com/arangodb/entity/BaseEdgeDocument.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.arangodb.internal.DocumentFields; - -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class BaseEdgeDocument extends BaseDocument { - - private static final long serialVersionUID = 6904923804449368783L; - - @From - private String from; - @To - private String to; - - public BaseEdgeDocument() { - super(); - } - - public BaseEdgeDocument(final String from, final String to) { - super(); - this.from = from; - this.to = to; - } - - public BaseEdgeDocument(final String key, final String from, final String to) { - super(key); - this.from = from; - this.to = to; - } - - public BaseEdgeDocument(final Map properties) { - super(properties); - final Object tmpFrom = properties.remove(DocumentFields.FROM); - if (tmpFrom != null) { - from = tmpFrom.toString(); - } - final Object tmpTo = properties.remove(DocumentFields.TO); - if (tmpTo != null) { - to = tmpTo.toString(); - } - } - - public String getFrom() { - return from; - } - - public void setFrom(final String from) { - this.from = from; - } - - public String getTo() { - return to; - } - - public void setTo(final String to) { - this.to = to; - } - - @Override - public String toString() { - return "BaseDocument [documentRevision=" + - revision + - ", documentHandle=" + - id + - ", documentKey=" + - key + - ", from=" + - from + - ", to=" + - to + - ", properties=" + - properties + - "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((from == null) ? 0 : from.hashCode()); - result = prime * result + ((to == null) ? 0 : to.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final BaseEdgeDocument other = (BaseEdgeDocument) obj; - if (from == null) { - if (other.from != null) { - return false; - } - } else if (!from.equals(other.from)) { - return false; - } - if (to == null) { - return other.to == null; - } else return to.equals(other.to); - } - -} diff --git a/src/main/java/com/arangodb/entity/DocumentField.java b/src/main/java/com/arangodb/entity/DocumentField.java deleted file mode 100644 index 23341da94..000000000 --- a/src/main/java/com/arangodb/entity/DocumentField.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author Mark Vollmary - * @deprecated Use {@link Id}, {@link Key}, {@link Rev}, {@link From} or {@link To} instead. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD}) -@Deprecated -public @interface DocumentField { - - @Deprecated - enum Type { - - /** - * @deprecated Use {@link Id} instead. - */ - @Deprecated - ID("_id"), - - /** - * @deprecated Use {@link Key} instead. - */ - @Deprecated - KEY("_key"), - - /** - * @deprecated Use {@link Rev} instead. - */ - @Deprecated - REV("_rev"), - - /** - * @deprecated Use {@link From} instead. - */ - @Deprecated - FROM("_from"), - - /** - * @deprecated Use {@link To} instead. - */ - @Deprecated - TO("_to"); - - private final String serializeName; - - Type(final String serializeName) { - this.serializeName = serializeName; - } - - public String getSerializeName() { - return serializeName; - } - } - - Type value(); - -} diff --git a/src/main/java/com/arangodb/entity/LogEntity.java b/src/main/java/com/arangodb/entity/LogEntity.java deleted file mode 100644 index fe4e52ea8..000000000 --- a/src/main/java/com/arangodb/entity/LogEntity.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import java.util.List; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public class LogEntity implements Entity { - - private List lid; - private List level; - private List timestamp; - private List text; - private Long totalAmount; - - /** - * @return a list of log entry identifiers. Each log message is uniquely identified by its @LIT{lid} and the - * identifiers are in ascending order - */ - public List getLid() { - return lid; - } - - /** - * @return a list of the log-levels for all log entries - */ - public List getLevel() { - return level; - } - - /** - * @return a list of the timestamps as seconds since 1970-01-01 for all log entries - */ - public List getTimestamp() { - return timestamp; - } - - /** - * @return a list of the texts of all log entries - */ - public List getText() { - return text; - } - - /** - * @return the total amount of log entries before pagination - */ - public Long getTotalAmount() { - return totalAmount; - } - -} diff --git a/src/main/java/com/arangodb/entity/MinReplicationFactor.java b/src/main/java/com/arangodb/entity/MinReplicationFactor.java deleted file mode 100644 index 5a1bfa915..000000000 --- a/src/main/java/com/arangodb/entity/MinReplicationFactor.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2019 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import com.arangodb.model.CollectionCreateOptions; - -/** - * @author Heiko Kernbach - * @deprecated use {@link CollectionCreateOptions#writeConcern(Integer)} instead - */ -@Deprecated -public class MinReplicationFactor { - - private Integer minReplicationFactor; - - public MinReplicationFactor() { - super(); - } - - public Integer getMinReplicationFactor() { - return minReplicationFactor; - } - - public void setMinReplicationFactor(final Integer minReplicationFactor) { - this.minReplicationFactor = minReplicationFactor; - } - -} \ No newline at end of file diff --git a/src/main/java/com/arangodb/entity/PathEntity.java b/src/main/java/com/arangodb/entity/PathEntity.java deleted file mode 100644 index 52f25840e..000000000 --- a/src/main/java/com/arangodb/entity/PathEntity.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import java.util.Collection; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -@Deprecated -public class PathEntity implements Entity { - - private Collection edges; - private Collection vertices; - - public PathEntity() { - super(); - } - - public Collection getEdges() { - return edges; - } - - public void setEdges(final Collection edges) { - this.edges = edges; - } - - public Collection getVertices() { - return vertices; - } - - public void setVertices(final Collection vertices) { - this.vertices = vertices; - } - -} diff --git a/src/main/java/com/arangodb/entity/ReplicationFactor.java b/src/main/java/com/arangodb/entity/ReplicationFactor.java deleted file mode 100644 index b228f3f66..000000000 --- a/src/main/java/com/arangodb/entity/ReplicationFactor.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -/** - * @author Mark Vollmary - */ -public class ReplicationFactor { - - private Integer replicationFactor; - private Boolean satellite; - - public ReplicationFactor() { - super(); - } - - public Integer getReplicationFactor() { - return replicationFactor; - } - - public void setReplicationFactor(final Integer replicationFactor) { - this.replicationFactor = replicationFactor; - } - - public Boolean getSatellite() { - return satellite; - } - - public void setSatellite(final Boolean satellite) { - this.satellite = satellite; - } - -} diff --git a/src/main/java/com/arangodb/entity/TraversalEntity.java b/src/main/java/com/arangodb/entity/TraversalEntity.java deleted file mode 100644 index 2d7f9a52a..000000000 --- a/src/main/java/com/arangodb/entity/TraversalEntity.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity; - -import java.util.Collection; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -@Deprecated -public class TraversalEntity implements Entity { - - private Collection vertices; - private Collection> paths; - - public TraversalEntity() { - super(); - } - - public Collection getVertices() { - return vertices; - } - - public void setVertices(final Collection vertices) { - this.vertices = vertices; - } - - public Collection> getPaths() { - return paths; - } - - public void setPaths(final Collection> paths) { - this.paths = paths; - } - -} diff --git a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerEntity.java b/src/main/java/com/arangodb/entity/arangosearch/AnalyzerEntity.java deleted file mode 100644 index 5b5e5c019..000000000 --- a/src/main/java/com/arangodb/entity/arangosearch/AnalyzerEntity.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity.arangosearch; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * @author Michele Rastelli - * @deprecated use typed analyzers {@link com.arangodb.entity.arangosearch.analyzer} - */ -@Deprecated -public class AnalyzerEntity { - - private Collection features; - private AnalyzerType type; - private String name; - private Map properties; - - public AnalyzerEntity() { - } - - public Set getFeatures() { - return features != null ? new HashSet<>(features) : null; - } - - public void setFeatures(Set features) { - this.features = features; - } - - public AnalyzerType getType() { - return type; - } - - public void setType(AnalyzerType type) { - this.type = type; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Map getProperties() { - return properties; - } - - public void setProperties(Map properties) { - this.properties = properties; - } - -} diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java deleted file mode 100644 index 7353cba66..000000000 --- a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity.arangosearch; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; - -/** - * @author Mark Vollmary - * @author Heiko Kernbach - * @author Michele Rastelli - * @see API Documentation - */ -public class ArangoSearchProperties { - - private Long consolidationIntervalMsec; - private Long commitIntervalMsec; - private Long cleanupIntervalStep; - private ConsolidationPolicy consolidationPolicy; - private final Collection primarySorts; - private final Collection links; - private ArangoSearchCompression primarySortCompression; - private final Collection storedValues; - - public ArangoSearchProperties() { - super(); - links = new ArrayList<>(); - primarySorts = new ArrayList<>(); - storedValues = new ArrayList<>(); - } - - public Long getCommitIntervalMsec() { - return commitIntervalMsec; - } - - public void setCommitIntervalMsec(final Long commitIntervalMsec) { - this.commitIntervalMsec = commitIntervalMsec; - } - - public Long getConsolidationIntervalMsec() { - return consolidationIntervalMsec; - } - - public void setConsolidationIntervalMsec(final Long consolidationIntervalMsec) { - this.consolidationIntervalMsec = consolidationIntervalMsec; - } - - public Long getCleanupIntervalStep() { - return cleanupIntervalStep; - } - - public void setCleanupIntervalStep(final Long cleanupIntervalStep) { - this.cleanupIntervalStep = cleanupIntervalStep; - } - - public ConsolidationPolicy getConsolidationPolicy() { - return consolidationPolicy; - } - - public void setConsolidationPolicy(final ConsolidationPolicy consolidationPolicy) { - this.consolidationPolicy = consolidationPolicy; - } - - public Collection getLinks() { - return links; - } - - public void addLink(final CollectionLink... links) { - this.links.addAll(Arrays.asList(links)); - } - - public Collection getPrimarySort() { - return primarySorts; - } - - public void addPrimarySort(final PrimarySort... primarySorts) { - this.primarySorts.addAll(Arrays.asList(primarySorts)); - } - - /** - * @return Defines how to compress the primary sort data (introduced in v3.7.0). ArangoDB v3.5 and v3.6 always - * compress the index using LZ4. - * @since ArangoDB 3.7 - */ - public ArangoSearchCompression getPrimarySortCompression() { - return primarySortCompression; - } - - public void setPrimarySortCompression(ArangoSearchCompression primarySortCompression) { - this.primarySortCompression = primarySortCompression; - } - - /** - * @return An array of objects to describe which document attributes to store in the View index. It can then cover - * search queries, which means the data can be taken from the index directly and accessing the storage engine can be - * avoided. - * @since ArangoDB 3.7 - */ - public Collection getStoredValues() { - return storedValues; - } - - public void addStoredValues(final StoredValue... storedValues) { - this.storedValues.addAll(Arrays.asList(storedValues)); - } - -} diff --git a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java deleted file mode 100644 index b0cb50a0a..000000000 --- a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationPolicy.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.entity.arangosearch; - -/** - * @author Mark Vollmary - */ -public class ConsolidationPolicy { - - private ConsolidationType type; - private Double threshold; - private Long segmentThreshold; - - public ConsolidationPolicy() { - } - - public static ConsolidationPolicy of(final ConsolidationType type) { - return new ConsolidationPolicy().type(type); - } - - public ConsolidationPolicy type(final ConsolidationType type) { - this.type = type; - return this; - } - - /** - * @param threshold Select a given segment for "consolidation" if and only if the formula based on type (as defined above) - * evaluates to true, valid value range [0.0, 1.0] (default: 0.85) - * @return policy - */ - public ConsolidationPolicy threshold(final Double threshold) { - this.threshold = threshold; - return this; - } - - /** - * @param segmentThreshold Apply the "consolidation" operation if and only if (default: 300): {segmentThreshold} < - * number_of_segments - * @return policy - */ - public ConsolidationPolicy segmentThreshold(final Long segmentThreshold) { - this.segmentThreshold = segmentThreshold; - return this; - } - - public ConsolidationType getType() { - return type; - } - - public Double getThreshold() { - return threshold; - } - - public Long getSegmentThreshold() { - return segmentThreshold; - } - -} diff --git a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java b/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java deleted file mode 100644 index 978a6a0d5..000000000 --- a/src/main/java/com/arangodb/entity/arangosearch/ConsolidationType.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.arangodb.entity.arangosearch; - -public enum ConsolidationType { - - BYTES_ACCUM, TIER - -} \ No newline at end of file diff --git a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java b/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java deleted file mode 100644 index d6bf26381..000000000 --- a/src/main/java/com/arangodb/entity/arangosearch/FieldLink.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.arangodb.entity.arangosearch; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; - -public class FieldLink { - - private final String name; - private final Collection analyzers; - private Boolean includeAllFields; - private Boolean trackListPositions; - private StoreValuesType storeValues; - private final Collection fields; - - private FieldLink(final String name) { - super(); - this.name = name; - fields = new ArrayList<>(); - analyzers = new ArrayList<>(); - } - - /** - * Creates an instance of {@code FieldLink} on the given field name - * - * @param name Name of a field - * @return new instance of {@code FieldLink} - */ - public static FieldLink on(final String name) { - return new FieldLink(name); - } - - /** - * @param analyzers The list of analyzers to be used for indexing of string values (default: ["identity"]). - * @return link - */ - public FieldLink analyzers(final String... analyzers) { - this.analyzers.addAll(Arrays.asList(analyzers)); - return this; - } - - /** - * @param includeAllFields The flag determines whether or not to index all fields on a particular level of depth (default: - * false). - * @return link - */ - public FieldLink includeAllFields(final Boolean includeAllFields) { - this.includeAllFields = includeAllFields; - return this; - } - - /** - * @param trackListPositions The flag determines whether or not values in a lists should be treated separate (default: false). - * @return link - */ - public FieldLink trackListPositions(final Boolean trackListPositions) { - this.trackListPositions = trackListPositions; - return this; - } - - /** - * @param storeValues How should the view track the attribute values, this setting allows for additional value retrieval - * optimizations (default "none"). - * @return link - */ - public FieldLink storeValues(final StoreValuesType storeValues) { - this.storeValues = storeValues; - return this; - } - - /** - * @param fields A list of linked fields - * @return link - */ - public FieldLink fields(final FieldLink... fields) { - this.fields.addAll(Arrays.asList(fields)); - return this; - } - - public String getName() { - return name; - } - - public Collection getAnalyzers() { - return analyzers; - } - - public Boolean getIncludeAllFields() { - return includeAllFields; - } - - public Boolean getTrackListPositions() { - return trackListPositions; - } - - public StoreValuesType getStoreValues() { - return storeValues; - } - - public Collection getFields() { - return fields; - } - -} \ No newline at end of file diff --git a/src/main/java/com/arangodb/internal/ArangoExecutor.java b/src/main/java/com/arangodb/internal/ArangoExecutor.java deleted file mode 100644 index 1dff75c10..000000000 --- a/src/main/java/com/arangodb/internal/ArangoExecutor.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.QueueTimeMetrics; -import com.arangodb.entity.Entity; -import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; -import com.arangodb.velocypack.exception.VPackException; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public abstract class ArangoExecutor { - - @SuppressWarnings("unchecked") - protected T createResult(final Type type, final Response response) { - if (type != Void.class && response.getBody() != null) { - if (isInternal(type)) { - return (T) util.get(Serializer.INTERNAL).deserialize(response.getBody(), type); - } else { - return (T) util.get(Serializer.CUSTOM).deserialize(response.getBody(), type); - } - } else { - return null; - } - } - - private boolean isInternal(final Type type) { - if (type instanceof ParameterizedType) { - ParameterizedType pType = ((ParameterizedType) type); - Type rawType = pType.getRawType(); - - if (rawType instanceof Class && ( - Map.class.isAssignableFrom((Class) rawType) || Iterable.class.isAssignableFrom((Class) rawType) - )) { - for (Type arg : pType.getActualTypeArguments()) { - if (!isInternal(arg)) { - return false; - } - } - return true; - } - } - - return type instanceof Class && Entity.class.isAssignableFrom((Class) type); - } - - private final DocumentCache documentCache; - private final QueueTimeMetricsImpl qtMetrics; - private final ArangoSerializationFactory util; - private final String timeoutS; - - protected ArangoExecutor(final ArangoSerializationFactory util, final DocumentCache documentCache, - final QueueTimeMetricsImpl qtMetrics, final int timeoutMs) { - super(); - this.documentCache = documentCache; - this.qtMetrics = qtMetrics; - this.util = util; - timeoutS = timeoutMs >= 1000 ? Integer.toString(timeoutMs / 1000) : null; - } - - public DocumentCache documentCache() { - return documentCache; - } - - public interface ResponseDeserializer { - T deserialize(Response response) throws VPackException; - } - - protected final void interceptResponse(Response response) { - String queueTime = response.getMeta().get("X-Arango-Queue-Time-Seconds"); - if (queueTime != null) { - qtMetrics.add(Double.parseDouble(queueTime)); - } - } - - protected final Request interceptRequest(Request request) { - request.putHeaderParam("X-Arango-Queue-Time-Seconds", timeoutS); - return request; - } - - public QueueTimeMetrics getQueueTimeMetrics() { - return qtMetrics; - } -} diff --git a/src/main/java/com/arangodb/internal/ArangoRouteImpl.java b/src/main/java/com/arangodb/internal/ArangoRouteImpl.java deleted file mode 100644 index b14fba224..000000000 --- a/src/main/java/com/arangodb/internal/ArangoRouteImpl.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.ArangoDBException; -import com.arangodb.ArangoRoute; -import com.arangodb.velocystream.RequestType; -import com.arangodb.velocystream.Response; - -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class ArangoRouteImpl extends InternalArangoRoute - implements ArangoRoute { - - protected ArangoRouteImpl(final ArangoDatabaseImpl db, final String path, final Map headerParam) { - super(db, path, headerParam); - } - - @Override - public ArangoRoute route(final String... path) { - final String[] fullPath = new String[path.length + 1]; - fullPath[0] = this.path; - System.arraycopy(path, 0, fullPath, 1, path.length); - return new ArangoRouteImpl(db, String.join("/", fullPath), headerParam); - } - - @Override - public ArangoRoute withHeader(final String key, final Object value) { - _withHeader(key, value); - return this; - } - - @Override - public ArangoRoute withQueryParam(final String key, final Object value) { - _withQueryParam(key, value); - return this; - } - - @Override - public ArangoRoute withBody(final Object body) { - _withBody(body); - return this; - } - - private Response request(final RequestType requestType) { - return executor.execute(createRequest(requestType), response -> response); - } - - @Override - public Response delete() throws ArangoDBException { - return request(RequestType.DELETE); - } - - @Override - public Response get() throws ArangoDBException { - return request(RequestType.GET); - } - - @Override - public Response head() throws ArangoDBException { - return request(RequestType.HEAD); - } - - @Override - public Response patch() throws ArangoDBException { - return request(RequestType.PATCH); - } - - @Override - public Response post() throws ArangoDBException { - return request(RequestType.POST); - } - - @Override - public Response put() throws ArangoDBException { - return request(RequestType.PUT); - } - -} diff --git a/src/main/java/com/arangodb/internal/DocumentCache.java b/src/main/java/com/arangodb/internal/DocumentCache.java deleted file mode 100644 index e548be08f..000000000 --- a/src/main/java/com/arangodb/internal/DocumentCache.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.ArangoDBException; -import com.arangodb.entity.*; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.*; -import java.util.Map.Entry; - -/** - * @author Mark Vollmary - */ -public class DocumentCache { - - private final Map, Map> cache; - - public DocumentCache() { - super(); - cache = new HashMap<>(); - } - - public void setValues(final Object doc, final Map values) throws ArangoDBException { - try { - final Map fields = getFields(doc.getClass()); - for (final Entry value : values.entrySet()) { - final Field field = fields.get(value.getKey()); - if (field != null) { - field.set(doc, value.getValue()); - } - } - } catch (final IllegalArgumentException | IllegalAccessException e) { - throw new ArangoDBException(e); - } - } - - private Map getFields(final Class clazz) { - Map fields = new HashMap<>(); - if (!isTypeRestricted(clazz)) { - fields = cache.get(clazz); - if (fields == null) { - fields = createFields(clazz); - cache.put(clazz, fields); - } - } - return fields; - } - - private boolean isTypeRestricted(final Class type) { - return Map.class.isAssignableFrom(type) || Collection.class.isAssignableFrom(type); - } - - private Map createFields(final Class clazz) { - final Map fields = new HashMap<>(); - Class tmp = clazz; - final Collection values = new ArrayList<>(DocumentFields.values()); - while (tmp != null && tmp != Object.class && values.size() > 0) { - final Field[] declaredFields = tmp.getDeclaredFields(); - for (int i = 0; i < declaredFields.length && values.size() > 0; i++) { - findAnnotation(values, fields, declaredFields[i]); - } - tmp = tmp.getSuperclass(); - } - return fields; - } - - private void findAnnotation( - final Collection values, - final Map fields, - final Field field) { - - for (Annotation annotation : field.getAnnotations()) { - if (annotation != null && !field.isSynthetic() && !Modifier.isStatic(field.getModifiers()) - && String.class.isAssignableFrom(field.getType())) { - String value = null; - if (annotation instanceof DocumentField) { - value = ((DocumentField) annotation).value().getSerializeName(); - } else if (annotation instanceof Id) { - value = DocumentFields.ID; - } else if (annotation instanceof Key) { - value = DocumentFields.KEY; - } else if (annotation instanceof Rev) { - value = DocumentFields.REV; - } else if (annotation instanceof From) { - value = DocumentFields.FROM; - } else if (annotation instanceof To) { - value = DocumentFields.TO; - } - - if (values.contains(value)) { - field.setAccessible(true); - fields.put(value, field); - values.remove(value); - } - } - } - } -} diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java deleted file mode 100644 index a30525543..000000000 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ /dev/null @@ -1,705 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.ArangoDBException; -import com.arangodb.DbName; -import com.arangodb.entity.*; -import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; -import com.arangodb.internal.util.DocumentUtil; -import com.arangodb.internal.util.RequestUtils; -import com.arangodb.model.*; -import com.arangodb.util.ArangoSerializer; -import com.arangodb.velocypack.Type; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; - -import java.util.*; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -public abstract class InternalArangoCollection, D extends InternalArangoDatabase, E extends ArangoExecutor> - extends ArangoExecuteable { - - private static final String COLLECTION = "collection"; - - protected static final String PATH_API_COLLECTION = "/_api/collection"; - private static final String PATH_API_DOCUMENT = "/_api/document"; - private static final String PATH_API_INDEX = "/_api/index"; - private static final String PATH_API_IMPORT = "/_api/import"; - private static final String PATH_API_USER = "/_api/user"; - - private static final String MERGE_OBJECTS = "mergeObjects"; - private static final String IGNORE_REVS = "ignoreRevs"; - private static final String RETURN_NEW = "returnNew"; - private static final String NEW = "new"; - private static final String RETURN_OLD = "returnOld"; - private static final String OVERWRITE = "overwrite"; - private static final String OVERWRITE_MODE = "overwriteMode"; - private static final String OLD = "old"; - private static final String SILENT = "silent"; - - private static final String TRANSACTION_ID = "x-arango-trx-id"; - - private final D db; - protected volatile String name; - - protected InternalArangoCollection(final D db, final String name) { - super(db.executor, db.util, db.context); - this.db = db; - this.name = name; - } - - public D db() { - return db; - } - - public String name() { - return name; - } - - protected Request insertDocumentRequest(final T value, final DocumentCreateOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_DOCUMENT, name); - final DocumentCreateOptions params = (options != null ? options : new DocumentCreateOptions()); - request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.putQueryParam(RETURN_NEW, params.getReturnNew()); - request.putQueryParam(RETURN_OLD, params.getReturnOld()); - request.putQueryParam(SILENT, params.getSilent()); - request.putQueryParam(OVERWRITE, params.getOverwrite()); - request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? params.getOverwriteMode().getValue() : null); - request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - - request.setBody(util(Serializer.CUSTOM).serialize(value)); - - return request; - } - - protected ResponseDeserializer> insertDocumentResponseDeserializer( - final T value, final DocumentCreateOptions options) { - return response -> { - final VPackSlice body = response.getBody(); - final DocumentCreateEntity doc = util().deserialize(body, DocumentCreateEntity.class); - final VPackSlice newDoc = body.get(NEW); - if (newDoc.isObject()) { - doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, value.getClass())); - } - final VPackSlice oldDoc = body.get(OLD); - if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, value.getClass())); - } - if (options == null || Boolean.TRUE != options.getSilent()) { - final Map values = new HashMap<>(); - values.put(DocumentFields.ID, doc.getId()); - values.put(DocumentFields.KEY, doc.getKey()); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - } - return doc; - }; - } - - protected Request insertDocumentsRequest(final Collection values, final DocumentCreateOptions params) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_DOCUMENT, name); - request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.putQueryParam(RETURN_NEW, params.getReturnNew()); - request.putQueryParam(RETURN_OLD, params.getReturnOld()); - request.putQueryParam(SILENT, params.getSilent()); - request.putQueryParam(OVERWRITE, params.getOverwrite()); - request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? params.getOverwriteMode().getValue() : null); - request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - - request.setBody(util(Serializer.CUSTOM) - .serialize(values, new ArangoSerializer.Options().serializeNullValues(false).stringAsJson(true))); - return request; - } - - @SuppressWarnings("unchecked") - protected ResponseDeserializer>> insertDocumentsResponseDeserializer( - final Collection values, final DocumentCreateOptions params) { - return response -> { - Class type = null; - if (Boolean.TRUE == params.getReturnNew()) { - if (!values.isEmpty()) { - type = (Class) values.iterator().next().getClass(); - } - } - final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); - final Collection> docs = new ArrayList<>(); - final Collection errors = new ArrayList<>(); - final Collection documentsAndErrors = new ArrayList<>(); - final VPackSlice body = response.getBody(); - if (body.isArray()) { - for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).isTrue()) { - final ErrorEntity error = util().deserialize(next, ErrorEntity.class); - errors.add(error); - documentsAndErrors.add(error); - } else { - final DocumentCreateEntity doc = util().deserialize(next, DocumentCreateEntity.class); - final VPackSlice newDoc = next.get(NEW); - if (newDoc.isObject()) { - doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, type)); - } - final VPackSlice oldDoc = next.get(OLD); - if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, type)); - } - docs.add(doc); - documentsAndErrors.add(doc); - } - } - } - multiDocument.setDocuments(docs); - multiDocument.setErrors(errors); - multiDocument.setDocumentsAndErrors(documentsAndErrors); - return multiDocument; - }; - } - - protected Request importDocumentsRequest(final String values, final DocumentImportOptions options) { - return importDocumentsRequest(options).putQueryParam("type", ImportType.auto).setBody(util().serialize(values)); - } - - protected Request importDocumentsRequest(final Collection values, final DocumentImportOptions options) { - return importDocumentsRequest(options).putQueryParam("type", ImportType.list).setBody(util(Serializer.CUSTOM) - .serialize(values, new ArangoSerializer.Options().serializeNullValues(false).stringAsJson(true))); - } - - protected Request importDocumentsRequest(final DocumentImportOptions options) { - final DocumentImportOptions params = options != null ? options : new DocumentImportOptions(); - return request(db.dbName(), RequestType.POST, PATH_API_IMPORT).putQueryParam(COLLECTION, name) - .putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()) - .putQueryParam("fromPrefix", params.getFromPrefix()).putQueryParam("toPrefix", params.getToPrefix()) - .putQueryParam(OVERWRITE, params.getOverwrite()).putQueryParam("onDuplicate", params.getOnDuplicate()) - .putQueryParam("complete", params.getComplete()).putQueryParam("details", params.getDetails()); - } - - protected Request getDocumentRequest(final String key, final DocumentReadOptions options) { - final Request request = request(db.dbName(), RequestType.GET, PATH_API_DOCUMENT, - DocumentUtil.createDocumentHandle(name, key)); - final DocumentReadOptions params = (options != null ? options : new DocumentReadOptions()); - request.putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()); - request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - if (params.getAllowDirtyRead() == Boolean.TRUE) { - RequestUtils.allowDirtyRead(request); - } - return request; - } - - protected Request getDocumentsRequest(final Collection keys, final DocumentReadOptions options) { - final DocumentReadOptions params = (options != null ? options : new DocumentReadOptions()); - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, name) - .putQueryParam("onlyget", true) - .putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()) - .putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()).setBody(util().serialize(keys)) - .putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - if (params.getAllowDirtyRead() == Boolean.TRUE) { - RequestUtils.allowDirtyRead(request); - } - return request; - } - - protected ResponseDeserializer> getDocumentsResponseDeserializer( - final Class type, final DocumentReadOptions options) { - return response -> { - final MultiDocumentEntity multiDocument = new MultiDocumentEntity<>(); - final Collection docs = new ArrayList<>(); - final Collection errors = new ArrayList<>(); - final Collection documentsAndErrors = new ArrayList<>(); - final VPackSlice body = response.getBody(); - for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).isTrue()) { - final ErrorEntity error = util().deserialize(next, ErrorEntity.class); - errors.add(error); - documentsAndErrors.add(error); - } else { - final T doc = util(Serializer.CUSTOM).deserialize(next, type); - docs.add(doc); - documentsAndErrors.add(doc); - } - } - multiDocument.setDocuments(docs); - multiDocument.setErrors(errors); - multiDocument.setDocumentsAndErrors(documentsAndErrors); - return multiDocument; - }; - } - - protected Request replaceDocumentRequest( - final String key, final T value, final DocumentReplaceOptions options) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, - DocumentUtil.createDocumentHandle(name, key)); - final DocumentReplaceOptions params = (options != null ? options : new DocumentReplaceOptions()); - request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.putQueryParam(IGNORE_REVS, params.getIgnoreRevs()); - request.putQueryParam(RETURN_NEW, params.getReturnNew()); - request.putQueryParam(RETURN_OLD, params.getReturnOld()); - request.putQueryParam(SILENT, params.getSilent()); - request.setBody(util(Serializer.CUSTOM).serialize(value)); - return request; - } - - protected ResponseDeserializer> replaceDocumentResponseDeserializer( - final T value, final DocumentReplaceOptions options) { - return response -> { - final VPackSlice body = response.getBody(); - final DocumentUpdateEntity doc = util().deserialize(body, DocumentUpdateEntity.class); - final VPackSlice newDoc = body.get(NEW); - if (newDoc.isObject()) { - doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, value.getClass())); - } - final VPackSlice oldDoc = body.get(OLD); - if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, value.getClass())); - } - if (options == null || Boolean.TRUE != options.getSilent()) { - final Map values = new HashMap<>(); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - } - return doc; - }; - } - - protected Request replaceDocumentsRequest(final Collection values, final DocumentReplaceOptions params) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_DOCUMENT, name); - request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.putQueryParam(IGNORE_REVS, params.getIgnoreRevs()); - request.putQueryParam(RETURN_NEW, params.getReturnNew()); - request.putQueryParam(RETURN_OLD, params.getReturnOld()); - request.putQueryParam(SILENT, params.getSilent()); - request.setBody(util(Serializer.CUSTOM) - .serialize(values, new ArangoSerializer.Options().serializeNullValues(false).stringAsJson(true))); - return request; - } - - @SuppressWarnings("unchecked") - protected ResponseDeserializer>> replaceDocumentsResponseDeserializer( - final Collection values, final DocumentReplaceOptions params) { - return response -> { - Class type = null; - if (Boolean.TRUE == params.getReturnNew() || Boolean.TRUE == params.getReturnOld()) { - if (!values.isEmpty()) { - type = (Class) values.iterator().next().getClass(); - } - } - final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); - final Collection> docs = new ArrayList<>(); - final Collection errors = new ArrayList<>(); - final Collection documentsAndErrors = new ArrayList<>(); - final VPackSlice body = response.getBody(); - if (body.isArray()) { - for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).isTrue()) { - final ErrorEntity error = util().deserialize(next, ErrorEntity.class); - errors.add(error); - documentsAndErrors.add(error); - } else { - final DocumentUpdateEntity doc = util().deserialize(next, DocumentUpdateEntity.class); - final VPackSlice newDoc = next.get(NEW); - if (newDoc.isObject()) { - doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, type)); - } - final VPackSlice oldDoc = next.get(OLD); - if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, type)); - } - docs.add(doc); - documentsAndErrors.add(doc); - } - } - } - multiDocument.setDocuments(docs); - multiDocument.setErrors(errors); - multiDocument.setDocumentsAndErrors(documentsAndErrors); - return multiDocument; - }; - } - - protected Request updateDocumentRequest(final String key, final T value, final DocumentUpdateOptions options) { - final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_DOCUMENT, - DocumentUtil.createDocumentHandle(name, key)); - final DocumentUpdateOptions params = (options != null ? options : new DocumentUpdateOptions()); - request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.putQueryParam(ArangoRequestParam.KEEP_NULL, params.getKeepNull()); - request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); - request.putQueryParam(IGNORE_REVS, params.getIgnoreRevs()); - request.putQueryParam(RETURN_NEW, params.getReturnNew()); - request.putQueryParam(RETURN_OLD, params.getReturnOld()); - request.putQueryParam(SILENT, params.getSilent()); - request.setBody(util(Serializer.CUSTOM).serialize(value, new ArangoSerializer.Options() - .serializeNullValues(params.getSerializeNull() == null || params.getSerializeNull()))); - return request; - } - - protected ResponseDeserializer> updateDocumentResponseDeserializer( - final T value, final DocumentUpdateOptions options, final Class returnType) { - return response -> { - final VPackSlice body = response.getBody(); - final DocumentUpdateEntity doc = util().deserialize(body, DocumentUpdateEntity.class); - final VPackSlice newDoc = body.get(NEW); - if (newDoc.isObject()) { - doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, returnType)); - } - final VPackSlice oldDoc = body.get(OLD); - if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, returnType)); - } - if (options == null || Boolean.TRUE != options.getSilent()) { - final Map values = new HashMap<>(); - values.put(DocumentFields.REV, doc.getRev()); - executor.documentCache().setValues(value, values); - } - return doc; - }; - } - - protected Request updateDocumentsRequest(final Collection values, final DocumentUpdateOptions params) { - final Request request = request(db.dbName(), RequestType.PATCH, PATH_API_DOCUMENT, name); - final Boolean keepNull = params.getKeepNull(); - request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.putQueryParam(ArangoRequestParam.KEEP_NULL, keepNull); - request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); - request.putQueryParam(IGNORE_REVS, params.getIgnoreRevs()); - request.putQueryParam(RETURN_NEW, params.getReturnNew()); - request.putQueryParam(RETURN_OLD, params.getReturnOld()); - request.putQueryParam(SILENT, params.getSilent()); - request.setBody(util(Serializer.CUSTOM).serialize(values, new ArangoSerializer.Options() - .serializeNullValues(params.getSerializeNull() == null || params.getSerializeNull()) - .stringAsJson(true))); - return request; - } - - @SuppressWarnings("unchecked") - protected ResponseDeserializer>> updateDocumentsResponseDeserializer( - final Class returnType) { - return response -> { - final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); - final Collection> docs = new ArrayList<>(); - final Collection errors = new ArrayList<>(); - final Collection documentsAndErrors = new ArrayList<>(); - final VPackSlice body = response.getBody(); - if (body.isArray()) { - for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).isTrue()) { - final ErrorEntity error = util().deserialize(next, ErrorEntity.class); - errors.add(error); - documentsAndErrors.add(error); - } else { - final DocumentUpdateEntity doc = util().deserialize(next, DocumentUpdateEntity.class); - final VPackSlice newDoc = next.get(NEW); - if (newDoc.isObject()) { - doc.setNew(util(Serializer.CUSTOM).deserialize(newDoc, returnType)); - } - final VPackSlice oldDoc = next.get(OLD); - if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, returnType)); - } - docs.add(doc); - documentsAndErrors.add(doc); - } - } - } - multiDocument.setDocuments(docs); - multiDocument.setErrors(errors); - multiDocument.setDocumentsAndErrors(documentsAndErrors); - return multiDocument; - }; - } - - protected Request deleteDocumentRequest(final String key, final DocumentDeleteOptions options) { - final Request request = request(db.dbName(), RequestType.DELETE, PATH_API_DOCUMENT, - DocumentUtil.createDocumentHandle(name, key)); - final DocumentDeleteOptions params = (options != null ? options : new DocumentDeleteOptions()); - request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.putQueryParam(RETURN_OLD, params.getReturnOld()); - request.putQueryParam(SILENT, params.getSilent()); - return request; - } - - protected ResponseDeserializer> deleteDocumentResponseDeserializer( - final Class type) { - return response -> { - final VPackSlice body = response.getBody(); - final DocumentDeleteEntity doc = util().deserialize(body, DocumentDeleteEntity.class); - final VPackSlice oldDoc = body.get(OLD); - if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, type)); - } - return doc; - }; - } - - protected Request deleteDocumentsRequest(final Collection keys, final DocumentDeleteOptions options) { - final Request request = request(db.dbName(), RequestType.DELETE, PATH_API_DOCUMENT, name); - final DocumentDeleteOptions params = (options != null ? options : new DocumentDeleteOptions()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); - request.putQueryParam(RETURN_OLD, params.getReturnOld()); - request.putQueryParam(SILENT, params.getSilent()); - request.setBody(util().serialize(keys)); - return request; - } - - protected ResponseDeserializer>> deleteDocumentsResponseDeserializer( - final Class type) { - return response -> { - final MultiDocumentEntity> multiDocument = new MultiDocumentEntity<>(); - final Collection> docs = new ArrayList<>(); - final Collection errors = new ArrayList<>(); - final Collection documentsAndErrors = new ArrayList<>(); - final VPackSlice body = response.getBody(); - if (body.isArray()) { - for (final Iterator iterator = body.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice next = iterator.next(); - if (next.get(ArangoResponseField.ERROR).isTrue()) { - final ErrorEntity error = util().deserialize(next, ErrorEntity.class); - errors.add(error); - documentsAndErrors.add(error); - } else { - final DocumentDeleteEntity doc = util().deserialize(next, DocumentDeleteEntity.class); - final VPackSlice oldDoc = next.get(OLD); - if (oldDoc.isObject()) { - doc.setOld(util(Serializer.CUSTOM).deserialize(oldDoc, type)); - } - docs.add(doc); - documentsAndErrors.add(doc); - } - } - } - multiDocument.setDocuments(docs); - multiDocument.setErrors(errors); - multiDocument.setDocumentsAndErrors(documentsAndErrors); - return multiDocument; - }; - } - - protected Request documentExistsRequest(final String key, final DocumentExistsOptions options) { - final Request request = request(db.dbName(), RequestType.HEAD, PATH_API_DOCUMENT, - DocumentUtil.createDocumentHandle(name, key)); - final DocumentExistsOptions params = (options != null ? options : new DocumentExistsOptions()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - request.putHeaderParam(ArangoRequestParam.IF_MATCH, params.getIfMatch()); - request.putHeaderParam(ArangoRequestParam.IF_NONE_MATCH, params.getIfNoneMatch()); - return request; - } - - protected Request getIndexRequest(final String id) { - return request(db.dbName(), RequestType.GET, PATH_API_INDEX, createIndexId(id)); - } - - protected Request deleteIndexRequest(final String id) { - return request(db.dbName(), RequestType.DELETE, PATH_API_INDEX, createIndexId(id)); - } - - protected ResponseDeserializer deleteIndexResponseDeserializer() { - return response -> response.getBody().get("id").getAsString(); - } - - private String createIndexId(final String id) { - final String index; - if (id.matches(DocumentUtil.REGEX_ID)) { - index = id; - } else if (id.matches(DocumentUtil.REGEX_KEY)) { - index = name + "/" + id; - } else { - throw new ArangoDBException(String.format("index id %s is not valid.", id)); - } - return index; - } - - @Deprecated - protected Request createHashIndexRequest(final Iterable fields, final HashIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); - request.putQueryParam(COLLECTION, name); - request.setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new HashIndexOptions(), fields))); - return request; - } - - @Deprecated - protected Request createSkiplistIndexRequest(final Iterable fields, final SkiplistIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); - request.putQueryParam(COLLECTION, name); - request.setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new SkiplistIndexOptions(), fields))); - return request; - } - - protected Request createPersistentIndexRequest( - final Iterable fields, final PersistentIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); - request.putQueryParam(COLLECTION, name); - request.setBody(util().serialize( - OptionsBuilder.build(options != null ? options : new PersistentIndexOptions(), fields))); - return request; - } - - protected Request createGeoIndexRequest(final Iterable fields, final GeoIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); - request.putQueryParam(COLLECTION, name); - request.setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new GeoIndexOptions(), fields))); - return request; - } - - protected Request createFulltextIndexRequest(final Iterable fields, final FulltextIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); - request.putQueryParam(COLLECTION, name); - request.setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new FulltextIndexOptions(), fields))); - return request; - } - - protected Request createTtlIndexRequest(final Iterable fields, final TtlIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); - request.putQueryParam(COLLECTION, name); - request.setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new TtlIndexOptions(), fields))); - return request; - } - - protected Request createZKDIndexRequest( - final Iterable fields, final ZKDIndexOptions options) { - final Request request = request(db.dbName(), RequestType.POST, PATH_API_INDEX); - request.putQueryParam(COLLECTION, name); - request.setBody(util().serialize(OptionsBuilder.build(options != null ? options : - new ZKDIndexOptions().fieldValueTypes(ZKDIndexOptions.FieldValueTypes.DOUBLE), fields))); - return request; - } - - protected Request getIndexesRequest() { - final Request request = request(db.dbName(), RequestType.GET, PATH_API_INDEX); - request.putQueryParam(COLLECTION, name); - return request; - } - - protected ResponseDeserializer> getIndexesResponseDeserializer() { - return response -> util().deserialize(response.getBody().get("indexes"), new Type>() { - }.getType()); - } - - protected Request truncateRequest(final CollectionTruncateOptions options) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "truncate"); - final CollectionTruncateOptions params = (options != null ? options : new CollectionTruncateOptions()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - return request; - } - - protected Request countRequest(final CollectionCountOptions options) { - final Request request = request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name, "count"); - final CollectionCountOptions params = (options != null ? options : new CollectionCountOptions()); - request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); - return request; - } - - protected Request dropRequest(final Boolean isSystem) { - return request(db.dbName(), RequestType.DELETE, PATH_API_COLLECTION, name).putQueryParam("isSystem", isSystem); - } - - protected Request loadRequest() { - return request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "load"); - } - - protected Request unloadRequest() { - return request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "unload"); - } - - protected Request getInfoRequest() { - return request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name); - } - - protected Request getPropertiesRequest() { - return request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name, "properties"); - } - - protected Request changePropertiesRequest(final CollectionPropertiesOptions options) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "properties"); - request.setBody(util().serialize(options != null ? options : new CollectionPropertiesOptions())); - return request; - } - - protected Request renameRequest(final String newName) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "rename"); - request.setBody(util().serialize(OptionsBuilder.build(new CollectionRenameOptions(), newName))); - return request; - } - - protected Request responsibleShardRequest(final T value) { - final Request request = request(db.dbName(), RequestType.PUT, PATH_API_COLLECTION, name, "responsibleShard"); - request.setBody(util(Serializer.CUSTOM).serialize(value)); - return request; - } - - protected Request getRevisionRequest() { - return request(db.dbName(), RequestType.GET, PATH_API_COLLECTION, name, "revision"); - } - - protected Request grantAccessRequest(final String user, final Permissions permissions) { - return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - db.dbName().get(), name).setBody(util().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); - } - - protected Request resetAccessRequest(final String user) { - return request(DbName.SYSTEM, RequestType.DELETE, PATH_API_USER, user, ArangoRequestParam.DATABASE, - db.dbName().get(), name); - } - - protected Request getPermissionsRequest(final String user) { - return request(DbName.SYSTEM, RequestType.GET, PATH_API_USER, user, ArangoRequestParam.DATABASE, - db.dbName().get(), name); - } - - protected ResponseDeserializer getPermissionsResponseDeserialzer() { - return response -> { - final VPackSlice body = response.getBody(); - if (body != null) { - final VPackSlice result = body.get(ArangoResponseField.RESULT); - if (!result.isNone()) { - return util().deserialize(result, Permissions.class); - } - } - return null; - }; - } - -} diff --git a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java b/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java deleted file mode 100644 index 6abc81bfa..000000000 --- a/src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java +++ /dev/null @@ -1,405 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.ArangoDB; -import com.arangodb.ArangoDBException; -import com.arangodb.entity.LoadBalancingStrategy; -import com.arangodb.internal.net.Connection; -import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.internal.net.DirtyReadHostHandler; -import com.arangodb.internal.net.ExtendedHostResolver; -import com.arangodb.internal.net.FallbackHostHandler; -import com.arangodb.internal.net.Host; -import com.arangodb.internal.net.HostDescription; -import com.arangodb.internal.net.HostHandler; -import com.arangodb.internal.net.HostResolver; -import com.arangodb.internal.net.RandomHostHandler; -import com.arangodb.internal.net.RoundRobinHostHandler; -import com.arangodb.internal.net.SimpleHostResolver; -import com.arangodb.internal.util.HostUtils; -import com.arangodb.internal.velocypack.VPackDriverModule; -import com.arangodb.util.ArangoDeserializer; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.ArangoSerializer; -import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPackParser; -import org.apache.http.client.HttpRequestRetryHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLContext; -import java.io.IOException; -import java.io.InputStream; -import java.util.*; - - -/** - * @author Mark Vollmary - */ -public abstract class InternalArangoDBBuilder { - - private static final Logger LOG = LoggerFactory.getLogger(InternalArangoDBBuilder.class); - - private static final String PROPERTY_KEY_HOSTS = "arangodb.hosts"; - private static final String PROPERTY_KEY_HOST = "arangodb.host"; - private static final String PROPERTY_KEY_PORT = "arangodb.port"; - private static final String PROPERTY_KEY_TIMEOUT = "arangodb.timeout"; - private static final String PROPERTY_KEY_USER = "arangodb.user"; - private static final String PROPERTY_KEY_PASSWORD = "arangodb.password"; - private static final String PROPERTY_KEY_JWT = "arangodb.jwt"; - private static final String PROPERTY_KEY_USE_SSL = "arangodb.usessl"; - private static final String PROPERTY_KEY_COOKIE_SPEC = "arangodb.httpCookieSpec"; - private static final String PROPERTY_KEY_V_STREAM_CHUNK_CONTENT_SIZE = "arangodb.chunksize"; - private static final String PROPERTY_KEY_MAX_CONNECTIONS = "arangodb.connections.max"; - private static final String PROPERTY_KEY_CONNECTION_TTL = "arangodb.connections.ttl"; - private static final String PROPERTY_KEEP_ALIVE_INTERVAL = "arangodb.connections.keepAlive.interval"; - private static final String PROPERTY_KEY_ACQUIRE_HOST_LIST = "arangodb.acquireHostList"; - private static final String PROPERTY_KEY_ACQUIRE_HOST_LIST_INTERVAL = "arangodb.acquireHostList.interval"; - private static final String PROPERTY_KEY_LOAD_BALANCING_STRATEGY = "arangodb.loadBalancingStrategy"; - private static final String PROPERTY_KEY_RESPONSE_QUEUE_TIME_SAMPLES = "arangodb.metrics.responseQueueTimeSamples"; - private static final String DEFAULT_PROPERTY_FILE = "/arangodb.properties"; - - protected final List hosts; - protected HostDescription host; - protected Integer timeout; - protected String user; - protected String password; - protected String jwt; - protected Boolean useSsl; - protected String httpCookieSpec; - protected HttpRequestRetryHandler httpRequestRetryHandler; - protected SSLContext sslContext; - protected HostnameVerifier hostnameVerifier; - protected Integer chunksize; - protected Integer maxConnections; - protected Long connectionTtl; - protected Integer keepAliveInterval; - protected final VPack.Builder vpackBuilder; - protected final VPackParser.Builder vpackParserBuilder; - protected ArangoSerializer serializer; - protected ArangoDeserializer deserializer; - protected Boolean acquireHostList; - protected Integer acquireHostListInterval; - protected LoadBalancingStrategy loadBalancingStrategy; - protected ArangoSerialization customSerializer; - protected Integer responseQueueTimeSamples; - - - public InternalArangoDBBuilder() { - super(); - vpackBuilder = new VPack.Builder(); - vpackParserBuilder = new VPackParser.Builder(); - vpackBuilder.registerModule(new VPackDriverModule()); - vpackParserBuilder.registerModule(new VPackDriverModule()); - host = new HostDescription(ArangoDefaults.DEFAULT_HOST, ArangoDefaults.DEFAULT_PORT); - hosts = new ArrayList<>(); - user = ArangoDefaults.DEFAULT_USER; - loadProperties(ArangoDB.class.getResourceAsStream(DEFAULT_PROPERTY_FILE)); - } - - public InternalArangoDBBuilder loadProperties(final InputStream in) throws ArangoDBException { - - final Properties properties = new Properties(); - - if (in != null) { - - try { - properties.load(in); - } catch (final IOException e) { - throw new ArangoDBException(e); - } - } - - loadProperties(properties); - - return this; - - } - - protected void loadProperties(final Properties properties) { - loadHosts(properties, this.hosts); - final String host = loadHost(properties, this.host.getHost()); - final int port = loadPort(properties, this.host.getPort()); - this.host = new HostDescription(host, port); - timeout = loadTimeout(properties, timeout); - user = loadUser(properties, user); - password = loadPassword(properties, password); - jwt = loadJwt(properties, jwt); - useSsl = loadUseSsl(properties, useSsl); - httpCookieSpec = loadhttpCookieSpec(properties, httpCookieSpec); - chunksize = loadChunkSize(properties, chunksize); - maxConnections = loadMaxConnections(properties, maxConnections); - connectionTtl = loadConnectionTtl(properties, connectionTtl); - keepAliveInterval = loadKeepAliveInterval(properties, keepAliveInterval); - acquireHostList = loadAcquireHostList(properties, acquireHostList); - acquireHostListInterval = loadAcquireHostListInterval(properties, acquireHostListInterval); - loadBalancingStrategy = loadLoadBalancingStrategy(properties, loadBalancingStrategy); - responseQueueTimeSamples = loadResponseQueueTimeSamples(properties, responseQueueTimeSamples); - } - - protected void setHost(final String host, final int port) { - hosts.add(new HostDescription(host, port)); - } - - protected void setTimeout(final Integer timeout) { - this.timeout = timeout; - } - - protected void setUser(final String user) { - this.user = user; - } - - protected void setPassword(final String password) { - this.password = password; - } - - protected void setJwt(final String jwt) { - this.jwt = jwt; - } - - protected void setUseSsl(final Boolean useSsl) { - this.useSsl = useSsl; - } - - protected void setSslContext(final SSLContext sslContext) { - this.sslContext = sslContext; - } - - protected void setHostnameVerifier(final HostnameVerifier hostnameVerifier) { - this.hostnameVerifier = hostnameVerifier; - } - - protected void setHttpRequestRetryHandler(final HttpRequestRetryHandler httpRequestRetryHandler) { - this.httpRequestRetryHandler = httpRequestRetryHandler; - } - - protected void setChunksize(final Integer chunksize) { - this.chunksize = chunksize; - } - - protected void setMaxConnections(final Integer maxConnections) { - this.maxConnections = maxConnections; - } - - protected void setConnectionTtl(final Long connectionTtl) { - this.connectionTtl = connectionTtl; - } - - protected void setKeepAliveInterval(final Integer keepAliveInterval) { - this.keepAliveInterval = keepAliveInterval; - } - - protected void setAcquireHostList(final Boolean acquireHostList) { - this.acquireHostList = acquireHostList; - } - - protected void setAcquireHostListInterval(final Integer acquireHostListInterval) { - this.acquireHostListInterval = acquireHostListInterval; - } - - protected void setLoadBalancingStrategy(final LoadBalancingStrategy loadBalancingStrategy) { - this.loadBalancingStrategy = loadBalancingStrategy; - } - - protected void setResponseQueueTimeSamples(final Integer responseQueueTimeSamples) { - this.responseQueueTimeSamples = responseQueueTimeSamples; - } - - protected void serializer(final ArangoSerializer serializer) { - this.serializer = serializer; - } - - protected void deserializer(final ArangoDeserializer deserializer) { - this.deserializer = deserializer; - } - - protected void setSerializer(final ArangoSerialization serializer) { - this.customSerializer = serializer; - } - - private static void loadHosts(final Properties properties, final Collection hosts) { - final String hostsProp = properties.getProperty(PROPERTY_KEY_HOSTS); - if (hostsProp != null) { - final String[] hostsSplit = hostsProp.split(","); - for (final String host : hostsSplit) { - final String[] split = host.split(":"); - if (split.length != 2 || !split[1].matches("[0-9]+")) { - throw new ArangoDBException(String.format( - "Could not load property-value arangodb.hosts=%s. Expected format ip:port,ip:port,...", - hostsProp)); - } else { - hosts.add(new HostDescription(split[0], Integer.parseInt(split[1]))); - } - } - } - } - - protected HostHandler createHostHandler(final HostResolver hostResolver) { - - final HostHandler hostHandler; - - if (loadBalancingStrategy != null) { - switch (loadBalancingStrategy) { - case ONE_RANDOM: - hostHandler = new RandomHostHandler(hostResolver, new FallbackHostHandler(hostResolver)); - break; - case ROUND_ROBIN: - hostHandler = new RoundRobinHostHandler(hostResolver); - break; - case NONE: - default: - hostHandler = new FallbackHostHandler(hostResolver); - break; - } - } else { - hostHandler = new FallbackHostHandler(hostResolver); - } - - LOG.debug("HostHandler is " + hostHandler.getClass().getSimpleName()); - - return new DirtyReadHostHandler(hostHandler, new RoundRobinHostHandler(hostResolver)); - } - - protected HostResolver createHostResolver(final Collection hosts, final int maxConnections, final ConnectionFactory connectionFactory) { - - if (acquireHostList != null && acquireHostList) { - LOG.debug("acquireHostList -> Use ExtendedHostResolver"); - return new ExtendedHostResolver(new ArrayList<>(hosts), maxConnections, connectionFactory, acquireHostListInterval); - } else { - LOG.debug("Use SimpleHostResolver"); - return new SimpleHostResolver(new ArrayList<>(hosts)); - } - - } - - private static String loadHost(final Properties properties, final String currentValue) { - final String host = getProperty(properties, PROPERTY_KEY_HOST, currentValue, ArangoDefaults.DEFAULT_HOST); - if (host.contains(":")) { - throw new ArangoDBException(String.format( - "Could not load property-value arangodb.host=%s. Expect only ip. Do you mean arangodb.hosts=ip:port ?", - host)); - } - return host; - } - - private static Integer loadPort(final Properties properties, final int currentValue) { - return Integer.parseInt(getProperty(properties, PROPERTY_KEY_PORT, currentValue, ArangoDefaults.DEFAULT_PORT)); - } - - private static Integer loadTimeout(final Properties properties, final Integer currentValue) { - return Integer - .parseInt(getProperty(properties, PROPERTY_KEY_TIMEOUT, currentValue, ArangoDefaults.DEFAULT_TIMEOUT)); - } - - private static String loadUser(final Properties properties, final String currentValue) { - return getProperty(properties, PROPERTY_KEY_USER, currentValue, ArangoDefaults.DEFAULT_USER); - } - - private static String loadPassword(final Properties properties, final String currentValue) { - return getProperty(properties, PROPERTY_KEY_PASSWORD, currentValue, null); - } - - private static String loadJwt(final Properties properties, final String currentValue) { - return getProperty(properties, PROPERTY_KEY_JWT, currentValue, null); - } - - private static Boolean loadUseSsl(final Properties properties, final Boolean currentValue) { - return Boolean.parseBoolean( - getProperty(properties, PROPERTY_KEY_USE_SSL, currentValue, ArangoDefaults.DEFAULT_USE_SSL)); - } - - private static String loadhttpCookieSpec(final Properties properties, final String currentValue) { - return getProperty(properties, PROPERTY_KEY_COOKIE_SPEC, currentValue, ""); - } - - private static Integer loadChunkSize(final Properties properties, final Integer currentValue) { - return Integer.parseInt(getProperty(properties, PROPERTY_KEY_V_STREAM_CHUNK_CONTENT_SIZE, currentValue, - ArangoDefaults.CHUNK_DEFAULT_CONTENT_SIZE)); - } - - private static Integer loadMaxConnections(final Properties properties, final Integer currentValue) { - return Integer.parseInt(getProperty(properties, PROPERTY_KEY_MAX_CONNECTIONS, currentValue, - ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT)); - } - - private static Long loadConnectionTtl(final Properties properties, final Long currentValue) { - final String ttl = getProperty(properties, PROPERTY_KEY_CONNECTION_TTL, currentValue, - ArangoDefaults.CONNECTION_TTL_VST_DEFAULT); - return ttl != null ? Long.parseLong(ttl) : null; - } - - private static Integer loadKeepAliveInterval(final Properties properties, final Integer currentValue) { - final String keepAliveInterval = getProperty(properties, PROPERTY_KEEP_ALIVE_INTERVAL, currentValue, - null); - return keepAliveInterval != null ? Integer.parseInt(keepAliveInterval) : null; - } - - private static Boolean loadAcquireHostList(final Properties properties, final Boolean currentValue) { - return Boolean.parseBoolean(getProperty(properties, PROPERTY_KEY_ACQUIRE_HOST_LIST, currentValue, - ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST)); - } - - private static int loadAcquireHostListInterval(final Properties properties, final Integer currentValue) { - return Integer.parseInt(getProperty(properties, PROPERTY_KEY_ACQUIRE_HOST_LIST_INTERVAL, currentValue, - ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST_INTERVAL)); - } - - private static int loadResponseQueueTimeSamples(final Properties properties, final Integer currentValue) { - return Integer.parseInt(getProperty(properties, PROPERTY_KEY_RESPONSE_QUEUE_TIME_SAMPLES, currentValue, - ArangoDefaults.DEFAULT_RESPONSE_QUEUE_TIME_SAMPLES)); - } - - private static LoadBalancingStrategy loadLoadBalancingStrategy( - final Properties properties, - final LoadBalancingStrategy currentValue) { - return LoadBalancingStrategy.valueOf(getProperty(properties, PROPERTY_KEY_LOAD_BALANCING_STRATEGY, currentValue, - ArangoDefaults.DEFAULT_LOAD_BALANCING_STRATEGY).toUpperCase(Locale.ENGLISH)); - } - - protected static String getProperty( - final Properties properties, - final String key, - final T currentValue, - final T defaultValue) { - - String overrideDefaultValue = null; - - if (currentValue != null) { - overrideDefaultValue = currentValue.toString(); - } else if (defaultValue != null) { - overrideDefaultValue = defaultValue.toString(); - } - - return properties.getProperty(key, overrideDefaultValue); - } - - protected Collection createHostList( - final int maxConnections, - final ConnectionFactory connectionFactory) { - final Collection hostList = new ArrayList<>(); - for (final HostDescription host : hosts) { - hostList.add(HostUtils.createHost(host, maxConnections, connectionFactory)); - } - return hostList; - } -} diff --git a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java b/src/main/java/com/arangodb/internal/InternalArangoDatabase.java deleted file mode 100644 index 933b5c175..000000000 --- a/src/main/java/com/arangodb/internal/InternalArangoDatabase.java +++ /dev/null @@ -1,514 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.DbName; -import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.AnalyzerEntity; -import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; -import com.arangodb.internal.ArangoExecutor.ResponseDeserializer; -import com.arangodb.internal.util.ArangoSerializationFactory; -import com.arangodb.internal.util.ArangoSerializationFactory.Serializer; -import com.arangodb.internal.util.RequestUtils; -import com.arangodb.model.*; -import com.arangodb.model.arangosearch.AnalyzerDeleteOptions; -import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import com.arangodb.model.arangosearch.ArangoSearchOptionsBuilder; -import com.arangodb.util.ArangoSerializer; -import com.arangodb.velocypack.Type; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.exception.VPackException; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -public abstract class InternalArangoDatabase, EXECUTOR extends ArangoExecutor> - extends ArangoExecuteable { - - protected static final String PATH_API_DATABASE = "/_api/database"; - private static final String PATH_API_VERSION = "/_api/version"; - private static final String PATH_API_ENGINE = "/_api/engine"; - private static final String PATH_API_CURSOR = "/_api/cursor"; - private static final String PATH_API_TRANSACTION = "/_api/transaction"; - private static final String PATH_API_BEGIN_STREAM_TRANSACTION = "/_api/transaction/begin"; - private static final String PATH_API_AQLFUNCTION = "/_api/aqlfunction"; - private static final String PATH_API_EXPLAIN = "/_api/explain"; - private static final String PATH_API_QUERY = "/_api/query"; - private static final String PATH_API_QUERY_CACHE = "/_api/query-cache"; - private static final String PATH_API_QUERY_CACHE_PROPERTIES = "/_api/query-cache/properties"; - private static final String PATH_API_QUERY_PROPERTIES = "/_api/query/properties"; - private static final String PATH_API_QUERY_CURRENT = "/_api/query/current"; - private static final String PATH_API_QUERY_SLOW = "/_api/query/slow"; - private static final String PATH_API_TRAVERSAL = "/_api/traversal"; - private static final String PATH_API_ADMIN_ROUTING_RELOAD = "/_admin/routing/reload"; - private static final String PATH_API_USER = "/_api/user"; - - private static final String TRANSACTION_ID = "x-arango-trx-id"; - - private final DbName dbName; - private final A arango; - - protected InternalArangoDatabase(final A arango, final DbName dbName) { - super(arango.executor, arango.util, arango.context); - this.arango = arango; - this.dbName = dbName; - } - - public A arango() { - return arango; - } - - public DbName dbName() { - return dbName; - } - - protected ResponseDeserializer> getDatabaseResponseDeserializer() { - return arango.getDatabaseResponseDeserializer(); - } - - protected Request getAccessibleDatabasesRequest() { - return request(dbName, RequestType.GET, PATH_API_DATABASE, "user"); - } - - protected Request getVersionRequest() { - return request(dbName, RequestType.GET, PATH_API_VERSION); - } - - protected Request getEngineRequest() { - return request(dbName, RequestType.GET, PATH_API_ENGINE); - } - - protected Request createCollectionRequest(final String name, final CollectionCreateOptions options) { - - VPackSlice body = util() - .serialize(OptionsBuilder.build(options != null ? options : new CollectionCreateOptions(), name)); - - return request(dbName, RequestType.POST, InternalArangoCollection.PATH_API_COLLECTION).setBody(body); - } - - protected Request getCollectionsRequest(final CollectionsReadOptions options) { - final Request request; - request = request(dbName, RequestType.GET, InternalArangoCollection.PATH_API_COLLECTION); - final CollectionsReadOptions params = (options != null ? options : new CollectionsReadOptions()); - request.putQueryParam("excludeSystem", params.getExcludeSystem()); - return request; - } - - protected ResponseDeserializer> getCollectionsResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { - }.getType()); - }; - } - - protected Request dropRequest() { - return request(DbName.SYSTEM, RequestType.DELETE, PATH_API_DATABASE, dbName.get()); - } - - protected ResponseDeserializer createDropResponseDeserializer() { - return response -> response.getBody().get(ArangoResponseField.RESULT).getAsBoolean(); - } - - protected Request grantAccessRequest(final String user, final Permissions permissions) { - return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - dbName.get()).setBody(util().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); - } - - protected Request resetAccessRequest(final String user) { - return request(DbName.SYSTEM, RequestType.DELETE, PATH_API_USER, user, ArangoRequestParam.DATABASE, - dbName.get()); - } - - protected Request updateUserDefaultCollectionAccessRequest(final String user, final Permissions permissions) { - return request(DbName.SYSTEM, RequestType.PUT, PATH_API_USER, user, ArangoRequestParam.DATABASE, - dbName.get(), "*").setBody(util().serialize(OptionsBuilder.build(new UserAccessOptions(), permissions))); - } - - protected Request getPermissionsRequest(final String user) { - return request(DbName.SYSTEM, RequestType.GET, PATH_API_USER, user, ArangoRequestParam.DATABASE, - dbName.get()); - } - - protected ResponseDeserializer getPermissionsResponseDeserialzer() { - return response -> { - final VPackSlice body = response.getBody(); - if (body != null) { - final VPackSlice result = body.get(ArangoResponseField.RESULT); - if (!result.isNone()) { - return util().deserialize(result, Permissions.class); - } - } - return null; - }; - } - - protected Request queryRequest( - final String query, final Map bindVars, final AqlQueryOptions options) { - final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); - final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR) - .setBody(util().serialize(OptionsBuilder - .build(opt, query, bindVars != null ? - util(ArangoSerializationFactory.Serializer.CUSTOM).serialize(bindVars, new ArangoSerializer.Options().serializeNullValues(true)) : - null))); - if (opt.getAllowDirtyRead() == Boolean.TRUE) { - RequestUtils.allowDirtyRead(request); - } - request.putHeaderParam(TRANSACTION_ID, opt.getStreamTransactionId()); - return request; - } - - protected Request queryNextRequest(final String id, final AqlQueryOptions options, Map meta) { - - final Request request = request(dbName, RequestType.POST, PATH_API_CURSOR, id); - - if (meta != null) { - request.getHeaderParam().putAll(meta); - } - - final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); - - if (opt.getAllowDirtyRead() == Boolean.TRUE) { - RequestUtils.allowDirtyRead(request); - } - request.putHeaderParam(TRANSACTION_ID, opt.getStreamTransactionId()); - return request; - } - - protected Request queryCloseRequest(final String id, final AqlQueryOptions options, Map meta) { - - final Request request = request(dbName, RequestType.DELETE, PATH_API_CURSOR, id); - - if (meta != null) { - request.getHeaderParam().putAll(meta); - } - - final AqlQueryOptions opt = options != null ? options : new AqlQueryOptions(); - - if (opt.getAllowDirtyRead() == Boolean.TRUE) { - RequestUtils.allowDirtyRead(request); - } - request.putHeaderParam(TRANSACTION_ID, opt.getStreamTransactionId()); - return request; - } - - protected Request explainQueryRequest( - final String query, - final Map bindVars, - final AqlQueryExplainOptions options - ) { - - final AqlQueryExplainOptions opt = options != null ? options : new AqlQueryExplainOptions(); - - return request(dbName, RequestType.POST, PATH_API_EXPLAIN) - .setBody(util().serialize(OptionsBuilder.build( - opt, - query, - bindVars != null ? util(ArangoSerializationFactory.Serializer.CUSTOM).serialize( - bindVars, - new ArangoSerializer.Options().serializeNullValues(true)) : null))); - } - - protected Request parseQueryRequest(final String query) { - return request(dbName, RequestType.POST, PATH_API_QUERY) - .setBody(util().serialize(OptionsBuilder.build(new AqlQueryParseOptions(), query))); - } - - protected Request clearQueryCacheRequest() { - return request(dbName, RequestType.DELETE, PATH_API_QUERY_CACHE); - } - - protected Request getQueryCachePropertiesRequest() { - return request(dbName, RequestType.GET, PATH_API_QUERY_CACHE_PROPERTIES); - } - - protected Request setQueryCachePropertiesRequest(final QueryCachePropertiesEntity properties) { - return request(dbName, RequestType.PUT, PATH_API_QUERY_CACHE_PROPERTIES).setBody(util().serialize(properties)); - } - - protected Request getQueryTrackingPropertiesRequest() { - return request(dbName, RequestType.GET, PATH_API_QUERY_PROPERTIES); - } - - protected Request setQueryTrackingPropertiesRequest(final QueryTrackingPropertiesEntity properties) { - return request(dbName, RequestType.PUT, PATH_API_QUERY_PROPERTIES).setBody(util().serialize(properties)); - } - - protected Request getCurrentlyRunningQueriesRequest() { - return request(dbName, RequestType.GET, PATH_API_QUERY_CURRENT); - } - - protected Request getSlowQueriesRequest() { - return request(dbName, RequestType.GET, PATH_API_QUERY_SLOW); - } - - protected Request clearSlowQueriesRequest() { - return request(dbName, RequestType.DELETE, PATH_API_QUERY_SLOW); - } - - protected Request killQueryRequest(final String id) { - return request(dbName, RequestType.DELETE, PATH_API_QUERY, id); - } - - protected Request createAqlFunctionRequest( - final String name, final String code, final AqlFunctionCreateOptions options) { - return request(dbName, RequestType.POST, PATH_API_AQLFUNCTION).setBody(util().serialize( - OptionsBuilder.build(options != null ? options : new AqlFunctionCreateOptions(), name, code))); - } - - protected Request deleteAqlFunctionRequest(final String name, final AqlFunctionDeleteOptions options) { - final Request request = request(dbName, RequestType.DELETE, PATH_API_AQLFUNCTION, name); - final AqlFunctionDeleteOptions params = options != null ? options : new AqlFunctionDeleteOptions(); - request.putQueryParam("group", params.getGroup()); - return request; - } - - protected ResponseDeserializer deleteAqlFunctionResponseDeserializer() { - return response -> { - // compatibility with ArangoDB < 3.4 - // https://www.arangodb.com/docs/stable/release-notes-upgrading-changes34.html - Integer count = null; - final VPackSlice body = response.getBody(); - if (body.isObject()) { - final VPackSlice deletedCount = body.get("deletedCount"); - if (deletedCount.isInteger()) { - count = deletedCount.getAsInt(); - } - } - return count; - }; - } - - protected Request getAqlFunctionsRequest(final AqlFunctionGetOptions options) { - final Request request = request(dbName, RequestType.GET, PATH_API_AQLFUNCTION); - final AqlFunctionGetOptions params = options != null ? options : new AqlFunctionGetOptions(); - request.putQueryParam("namespace", params.getNamespace()); - return request; - } - - protected ResponseDeserializer> getAqlFunctionsResponseDeserializer() { - return response -> { - final VPackSlice body = response.getBody(); - // compatibility with ArangoDB < 3.4 - // https://www.arangodb.com/docs/stable/release-notes-upgrading-changes34.html - final VPackSlice result = body.isArray() ? body : body.get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { - }.getType()); - }; - } - - protected Request createGraphRequest( - final String name, final Collection edgeDefinitions, final GraphCreateOptions options) { - return request(dbName, RequestType.POST, InternalArangoGraph.PATH_API_GHARIAL).setBody(util().serialize( - OptionsBuilder.build(options != null ? options : new GraphCreateOptions(), name, edgeDefinitions))); - } - - protected ResponseDeserializer createGraphResponseDeserializer() { - return response -> util().deserialize(response.getBody().get("graph"), GraphEntity.class); - } - - protected Request getGraphsRequest() { - return request(dbName, RequestType.GET, InternalArangoGraph.PATH_API_GHARIAL); - } - - protected ResponseDeserializer> getGraphsResponseDeserializer() { - return response -> util().deserialize(response.getBody().get("graphs"), new Type>() { - }.getType()); - } - - protected Request transactionRequest(final String action, final TransactionOptions options) { - return request(dbName, RequestType.POST, PATH_API_TRANSACTION).setBody( - util().serialize(OptionsBuilder.build(options != null ? options : new TransactionOptions(), action))); - } - - protected ResponseDeserializer transactionResponseDeserializer(final Class type) { - return response -> { - final VPackSlice body = response.getBody(); - if (body != null) { - final VPackSlice result = body.get(ArangoResponseField.RESULT); - if (!result.isNone() && !result.isNull()) { - return util(Serializer.CUSTOM).deserialize(result, type); - } - } - return null; - }; - } - - protected Request beginStreamTransactionRequest(final StreamTransactionOptions options) { - return request(dbName, RequestType.POST, PATH_API_BEGIN_STREAM_TRANSACTION) - .setBody(util().serialize(options != null ? options : new StreamTransactionOptions())); - } - - protected Request abortStreamTransactionRequest(String id) { - return request(dbName, RequestType.DELETE, PATH_API_TRANSACTION, id); - } - - protected Request getStreamTransactionsRequest() { - return request(dbName, RequestType.GET, PATH_API_TRANSACTION); - } - - protected Request getStreamTransactionRequest(String id) { - return request(dbName, RequestType.GET, PATH_API_TRANSACTION, id); - } - - protected ResponseDeserializer> transactionsResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get("transactions"); - return util().deserialize(result, new Type>() { - }.getType()); - }; - } - - protected Request commitStreamTransactionRequest(String id) { - return request(dbName, RequestType.PUT, PATH_API_TRANSACTION, id); - } - - protected ResponseDeserializer streamTransactionResponseDeserializer() { - return response -> util() - .deserialize(response.getBody().get(ArangoResponseField.RESULT), StreamTransactionEntity.class); - } - - protected Request getInfoRequest() { - return request(dbName, RequestType.GET, PATH_API_DATABASE, "current"); - } - - protected ResponseDeserializer getInfoResponseDeserializer() { - return response -> util().deserialize(response.getBody().get(ArangoResponseField.RESULT), DatabaseEntity.class); - } - - protected Request executeTraversalRequest(final TraversalOptions options) { - return request(dbName, RequestType.POST, PATH_API_TRAVERSAL) - .setBody(util().serialize(options != null ? options : new TransactionOptions())); - } - - protected ResponseDeserializer> executeTraversalResponseDeserializer( - final Class vertexClass, final Class edgeClass) { - return response -> { - final TraversalEntity result = new TraversalEntity<>(); - final VPackSlice visited = response.getBody().get(ArangoResponseField.RESULT).get("visited"); - result.setVertices(deserializeVertices(vertexClass, visited)); - - final Collection> paths = new ArrayList<>(); - for (final Iterator iterator = visited.get("paths").arrayIterator(); iterator.hasNext(); ) { - final PathEntity path = new PathEntity<>(); - final VPackSlice next = iterator.next(); - path.setEdges(deserializeEdges(edgeClass, next)); - path.setVertices(deserializeVertices(vertexClass, next)); - paths.add(path); - } - result.setPaths(paths); - return result; - }; - } - - protected Collection deserializeVertices(final Class vertexClass, final VPackSlice vpack) - throws VPackException { - final Collection vertices = new ArrayList<>(); - for (final Iterator iterator = vpack.get("vertices").arrayIterator(); iterator.hasNext(); ) { - vertices.add(util(Serializer.CUSTOM).deserialize(iterator.next(), vertexClass)); - } - return vertices; - } - - protected Collection deserializeEdges(final Class edgeClass, final VPackSlice next) - throws VPackException { - final Collection edges = new ArrayList<>(); - for (final Iterator iteratorEdge = next.get("edges").arrayIterator(); iteratorEdge.hasNext(); ) { - edges.add(util(Serializer.CUSTOM).deserialize(iteratorEdge.next(), edgeClass)); - } - return edges; - } - - protected Request reloadRoutingRequest() { - return request(dbName, RequestType.POST, PATH_API_ADMIN_ROUTING_RELOAD); - } - - protected Request getViewsRequest() { - return request(dbName, RequestType.GET, InternalArangoView.PATH_API_VIEW); - } - - protected ResponseDeserializer> getViewsResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { - }.getType()); - }; - } - - protected Request createViewRequest(final String name, final ViewType type) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW) - .setBody(util().serialize(OptionsBuilder.build(new ViewCreateOptions(), name, type))); - } - - protected Request createArangoSearchRequest(final String name, final ArangoSearchCreateOptions options) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_VIEW).setBody(util().serialize( - ArangoSearchOptionsBuilder.build(options != null ? options : new ArangoSearchCreateOptions(), name))); - } - - protected Request getAnalyzerRequest(final String name) { - return request(dbName, RequestType.GET, InternalArangoView.PATH_API_ANALYZER, name); - } - - protected Request getAnalyzersRequest() { - return request(dbName, RequestType.GET, InternalArangoView.PATH_API_ANALYZER); - } - - protected ResponseDeserializer> getAnalyzersResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { - }.getType()); - }; - } - - protected ResponseDeserializer> getSearchAnalyzersResponseDeserializer() { - return response -> { - final VPackSlice result = response.getBody().get(ArangoResponseField.RESULT); - return util().deserialize(result, new Type>() { - }.getType()); - }; - } - - protected Request createAnalyzerRequest(final AnalyzerEntity options) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_ANALYZER) - .setBody(util().serialize(options)); - } - - protected Request createAnalyzerRequest(final SearchAnalyzer options) { - return request(dbName, RequestType.POST, InternalArangoView.PATH_API_ANALYZER) - .setBody(util().serialize(options)); - } - - protected Request deleteAnalyzerRequest(final String name, final AnalyzerDeleteOptions options) { - Request request = request(dbName, RequestType.DELETE, InternalArangoView.PATH_API_ANALYZER, name); - request.putQueryParam("force", options != null ? options.getForce() : null); - return request; - } - -} diff --git a/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java b/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java deleted file mode 100644 index 93ede0a1b..000000000 --- a/src/main/java/com/arangodb/internal/cursor/AbstractArangoIterable.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.cursor; - -import com.arangodb.ArangoIterable; -import com.arangodb.ArangoIterator; -import com.arangodb.Function; -import com.arangodb.Predicate; - -import java.util.Collection; -import java.util.Iterator; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -/** - * @author Mark Vollmary - */ -public abstract class AbstractArangoIterable implements ArangoIterable { - - @Override - public Stream stream() { - return StreamSupport.stream(spliterator(), false); - } - - @Override - public ArangoIterable map(final Function mapper) { - return new ArangoMappingIterable<>(this, mapper); - } - - @Override - public ArangoIterable filter(final Predicate predicate) { - return new ArangoFilterIterable<>(this, predicate); - } - - @Override - public T first() { - final ArangoIterator iterator = iterator(); - return iterator.hasNext() ? iterator.next() : null; - } - - @Override - public long count() { - long count = 0L; - for (final Iterator iterator = iterator(); iterator.hasNext(); iterator.next()) { - count++; - } - return count; - } - - @Override - public boolean anyMatch(final Predicate predicate) { - boolean match = false; - for (final T t : this) { - if (predicate.test(t)) { - match = true; - break; - } - } - return match; - } - - @Override - public boolean allMatch(final Predicate predicate) { - boolean match = false; - for (final T t : this) { - match = predicate.test(t); - if (!match) { - break; - } - } - return match; - } - - @Override - public boolean noneMatch(final Predicate predicate) { - boolean match = false; - for (final T t : this) { - match = !predicate.test(t); - if (!match) { - break; - } - } - return match; - } - - @Override - public > R collectInto(final R target) { - for (final T t : this) { - target.add(t); - } - return target; - } - -} diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoFilterIterable.java b/src/main/java/com/arangodb/internal/cursor/ArangoFilterIterable.java deleted file mode 100644 index bb0ff1054..000000000 --- a/src/main/java/com/arangodb/internal/cursor/ArangoFilterIterable.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.cursor; - -import com.arangodb.ArangoIterable; -import com.arangodb.ArangoIterator; -import com.arangodb.Consumer; -import com.arangodb.Predicate; - -/** - * @author Mark Vollmary - */ -@Deprecated -public class ArangoFilterIterable extends AbstractArangoIterable implements ArangoIterable { - - private final ArangoIterable iterable; - private final Predicate predicate; - - protected ArangoFilterIterable(final ArangoIterable iterable, final Predicate predicate) { - super(); - this.iterable = iterable; - this.predicate = predicate; - } - - @Override - public ArangoIterator iterator() { - return new ArangoFilterIterator<>(iterable.iterator(), predicate); - } - - @Override - public void foreach(final Consumer action) { - for (final T t : iterable) { - if (predicate.test(t)) { - action.accept(t); - } - } - } - -} diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoFilterIterator.java b/src/main/java/com/arangodb/internal/cursor/ArangoFilterIterator.java deleted file mode 100644 index 7c65f9d22..000000000 --- a/src/main/java/com/arangodb/internal/cursor/ArangoFilterIterator.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.cursor; - -import com.arangodb.ArangoIterator; -import com.arangodb.Predicate; - -import java.util.NoSuchElementException; - -/** - * @author Mark Vollmary - */ -public class ArangoFilterIterator implements ArangoIterator { - - private final ArangoIterator iterator; - private final Predicate predicate; - private T next; - - protected ArangoFilterIterator(final ArangoIterator iterator, final Predicate predicate) { - super(); - this.iterator = iterator; - this.predicate = predicate; - next = null; - } - - @Override - public boolean hasNext() { - if (next != null) { - return true; - } - while (iterator.hasNext()) { - next = iterator.next(); - if (predicate.test(next)) { - return true; - } - } - next = null; - return false; - } - - @Override - public T next() { - if (next == null && !hasNext()) { - throw new NoSuchElementException(); - } - final T tmp = next; - next = null; - return tmp; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoMappingIterable.java b/src/main/java/com/arangodb/internal/cursor/ArangoMappingIterable.java deleted file mode 100644 index c1b818c2b..000000000 --- a/src/main/java/com/arangodb/internal/cursor/ArangoMappingIterable.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.cursor; - -import com.arangodb.ArangoIterable; -import com.arangodb.ArangoIterator; -import com.arangodb.Consumer; -import com.arangodb.Function; - -/** - * @author Mark Vollmary - */ -@Deprecated -public class ArangoMappingIterable extends AbstractArangoIterable implements ArangoIterable { - - private final ArangoIterable iterable; - private final Function mapper; - - protected ArangoMappingIterable(final ArangoIterable iterable, final Function mapper) { - super(); - this.iterable = iterable; - this.mapper = mapper; - } - - @Override - public ArangoIterator iterator() { - return new ArangoMappingIterator<>(iterable.iterator(), mapper); - } - - @Override - public void foreach(final Consumer action) { - for (final R t : iterable) { - action.accept(mapper.apply(t)); - } - } - -} diff --git a/src/main/java/com/arangodb/internal/cursor/ArangoMappingIterator.java b/src/main/java/com/arangodb/internal/cursor/ArangoMappingIterator.java deleted file mode 100644 index e3594a1cc..000000000 --- a/src/main/java/com/arangodb/internal/cursor/ArangoMappingIterator.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.cursor; - -import com.arangodb.ArangoIterator; -import com.arangodb.Function; - -/** - * @author Mark Vollmary - */ -public class ArangoMappingIterator implements ArangoIterator { - - private final ArangoIterator iterator; - private final Function mapper; - - public ArangoMappingIterator(final ArangoIterator iterator, final Function mapper) { - super(); - this.iterator = iterator; - this.mapper = mapper; - } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public T next() { - return mapper.apply(iterator.next()); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - -} diff --git a/src/main/java/com/arangodb/internal/http/CURLLogger.java b/src/main/java/com/arangodb/internal/http/CURLLogger.java deleted file mode 100644 index 941769fe4..000000000 --- a/src/main/java/com/arangodb/internal/http/CURLLogger.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.http; - -import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.RequestType; -import org.apache.http.auth.Credentials; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map.Entry; - -/** - * @author Mark Vollmary - */ -public final class CURLLogger { - - private static final Logger LOGGER = LoggerFactory.getLogger(CURLLogger.class); - - private CURLLogger() { - } - - public static void log( - final String url, - final Request request, - final Credentials credentials, - final String jwt, - final ArangoSerialization util) { - final RequestType requestType = request.getRequestType(); - final boolean includeBody = (requestType == RequestType.POST || requestType == RequestType.PUT - || requestType == RequestType.PATCH || requestType == RequestType.DELETE) && request.getBody() != null; - final StringBuilder buffer = new StringBuilder(); - if (includeBody) { - buffer.append("\n"); - buffer.append("cat <<-___EOB___ | "); - } - buffer.append("curl -X ").append(requestType); - buffer.append(" --dump -"); - if (request.getHeaderParam().size() > 0) { - for (final Entry header : request.getHeaderParam().entrySet()) { - buffer.append(" -H '").append(header.getKey()).append(":").append(header.getValue()).append("'"); - } - } - if (credentials != null) { - buffer.append(" -u ").append(credentials.getUserPrincipal().getName()).append(":") - .append(credentials.getPassword()); - } - if (jwt != null) { - buffer.append(" -H ").append("'Authorization: Bearer ").append(jwt).append("'"); - } - if (includeBody) { - buffer.append(" -d @-"); - } - buffer.append(" '").append(url).append("'"); - if (includeBody) { - buffer.append("\n"); - buffer.append((String) util.deserialize(request.getBody(), String.class)); - buffer.append("\n"); - buffer.append("___EOB___"); - } - LOGGER.debug("[CURL] {}", buffer); - } -} diff --git a/src/main/java/com/arangodb/internal/http/HttpConnection.java b/src/main/java/com/arangodb/internal/http/HttpConnection.java deleted file mode 100644 index 7cc380e22..000000000 --- a/src/main/java/com/arangodb/internal/http/HttpConnection.java +++ /dev/null @@ -1,392 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.http; - -import com.arangodb.ArangoDBException; -import com.arangodb.DbName; -import com.arangodb.Protocol; -import com.arangodb.internal.net.Connection; -import com.arangodb.internal.net.HostDescription; -import com.arangodb.internal.util.IOUtils; -import com.arangodb.internal.util.ResponseUtils; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.ArangoSerializer.Options; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; -import org.apache.http.*; -import org.apache.http.auth.AuthenticationException; -import org.apache.http.auth.Credentials; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.HttpRequestRetryHandler; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.*; -import org.apache.http.client.utils.URLEncodedUtils; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.ConnectionKeepAliveStrategy; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.auth.BasicScheme; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.apache.http.message.BasicHeaderElementIterator; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.protocol.HTTP; -import org.apache.http.ssl.SSLContexts; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLContext; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.TimeUnit; - -import static org.apache.http.HttpHeaders.AUTHORIZATION; - -/** - * @author Mark Vollmary - */ -public class HttpConnection implements Connection { - - private static final Logger LOGGER = LoggerFactory.getLogger(HttpCommunication.class); - private static final ContentType CONTENT_TYPE_APPLICATION_JSON_UTF8 = ContentType.create("application/json", - "utf-8"); - private static final ContentType CONTENT_TYPE_VPACK = ContentType.create("application/x-velocypack"); - - // max safe UTF-8 json string length, so that it can be converted to byte array - private static final int MAX_JSON_LENGTH = (Integer.MAX_VALUE - 8) / 4; - - public static class Builder { - private String user; - private String password; - private ArangoSerialization util; - private Boolean useSsl; - private String httpCookieSpec; - private Protocol contentType; - private HostDescription host; - private Long ttl; - private SSLContext sslContext; - private HostnameVerifier hostnameVerifier; - private Integer timeout; - private HttpRequestRetryHandler httpRequestRetryHandler; - - public Builder user(final String user) { - this.user = user; - return this; - } - - public Builder password(final String password) { - this.password = password; - return this; - } - - public Builder serializationUtil(final ArangoSerialization util) { - this.util = util; - return this; - } - - public Builder useSsl(final Boolean useSsl) { - this.useSsl = useSsl; - return this; - } - - public Builder httpCookieSpec(String httpCookieSpec) { - this.httpCookieSpec = httpCookieSpec; - return this; - } - - public Builder contentType(final Protocol contentType) { - this.contentType = contentType; - return this; - } - - public Builder host(final HostDescription host) { - this.host = host; - return this; - } - - public Builder ttl(final Long ttl) { - this.ttl = ttl; - return this; - } - - public Builder sslContext(final SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - - public Builder hostnameVerifier(final HostnameVerifier hostnameVerifier) { - this.hostnameVerifier = hostnameVerifier; - return this; - } - - public Builder timeout(final Integer timeout) { - this.timeout = timeout; - return this; - } - - public Builder httpRequestRetryHandler(final HttpRequestRetryHandler httpRequestRetryHandler) { - this.httpRequestRetryHandler = httpRequestRetryHandler; - return this; - } - - public HttpConnection build() { - return new HttpConnection(host, timeout, user, password, useSsl, sslContext, hostnameVerifier, util, - contentType, ttl, httpCookieSpec, httpRequestRetryHandler); - } - } - - private final PoolingHttpClientConnectionManager cm; - private final CloseableHttpClient client; - private final String user; - private final String password; - private volatile String jwt = null; - private final ArangoSerialization util; - private final Boolean useSsl; - private final Protocol contentType; - private final HostDescription host; - - private HttpConnection(final HostDescription host, final Integer timeout, final String user, final String password, - final Boolean useSsl, final SSLContext sslContext, final HostnameVerifier hostnameVerifier, final ArangoSerialization util, final Protocol contentType, - final Long ttl, final String httpCookieSpec, final HttpRequestRetryHandler httpRequestRetryHandler) { - super(); - this.host = host; - this.user = user; - this.password = password; - this.useSsl = useSsl; - this.util = util; - this.contentType = contentType; - final RegistryBuilder registryBuilder = RegistryBuilder - .create(); - if (Boolean.TRUE == useSsl) { - registryBuilder.register("https", new SSLConnectionSocketFactory( - sslContext != null ? sslContext : SSLContexts.createSystemDefault(), - hostnameVerifier != null ? hostnameVerifier : SSLConnectionSocketFactory.getDefaultHostnameVerifier() - )); - } else { - registryBuilder.register("http", new PlainConnectionSocketFactory()); - } - cm = new PoolingHttpClientConnectionManager(registryBuilder.build()); - cm.setDefaultMaxPerRoute(1); - cm.setMaxTotal(1); - final RequestConfig.Builder requestConfig = RequestConfig.custom(); - if (timeout != null && timeout >= 0) { - requestConfig.setConnectTimeout(timeout); - requestConfig.setConnectionRequestTimeout(timeout); - requestConfig.setSocketTimeout(timeout); - } - - if (httpCookieSpec != null && httpCookieSpec.length() > 1) { - requestConfig.setCookieSpec(httpCookieSpec); - } - - final ConnectionKeepAliveStrategy keepAliveStrategy = (response, context) -> HttpConnection.this.getKeepAliveDuration(response); - final HttpClientBuilder builder = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig.build()) - .setConnectionManager(cm).setKeepAliveStrategy(keepAliveStrategy) - .setRetryHandler(httpRequestRetryHandler != null ? httpRequestRetryHandler : new DefaultHttpRequestRetryHandler()); - if (ttl != null) { - builder.setConnectionTimeToLive(ttl, TimeUnit.MILLISECONDS); - } - client = builder.build(); - } - - private long getKeepAliveDuration(final HttpResponse response) { - final HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE)); - while (it.hasNext()) { - final HeaderElement he = it.nextElement(); - final String param = he.getName(); - final String value = he.getValue(); - if (value != null && "timeout".equalsIgnoreCase(param)) { - try { - return Long.parseLong(value) * 1000L; - } catch (final NumberFormatException ignore) { - } - } - } - return 30L * 1000L; - } - - @Override - public void close() throws IOException { - cm.shutdown(); - client.close(); - } - - private static String buildUrl(final String baseUrl, final Request request) { - StringBuilder sb = new StringBuilder().append(baseUrl); - DbName dbName = request.getDbName(); - if (dbName != null && !dbName.get().isEmpty()) { - sb.append("/_db/").append(dbName.getEncoded()); - } - sb.append(request.getRequest()); - if (!request.getQueryParam().isEmpty()) { - if (request.getRequest().contains("?")) { - sb.append("&"); - } else { - sb.append("?"); - } - final String paramString = URLEncodedUtils.format(toList(request.getQueryParam()), "utf-8"); - sb.append(paramString); - } - return sb.toString(); - } - - private HttpRequestBase buildHttpRequestBase(final Request request, final String url) { - final HttpRequestBase httpRequest; - switch (request.getRequestType()) { - case POST: - httpRequest = requestWithBody(new HttpPost(url), request); - break; - case PUT: - httpRequest = requestWithBody(new HttpPut(url), request); - break; - case PATCH: - httpRequest = requestWithBody(new HttpPatch(url), request); - break; - case DELETE: - httpRequest = requestWithBody(new HttpDeleteWithBody(url), request); - break; - case HEAD: - httpRequest = new HttpHead(url); - break; - case GET: - default: - httpRequest = new HttpGet(url); - break; - } - return httpRequest; - } - - private HttpRequestBase requestWithBody(final HttpEntityEnclosingRequestBase httpRequest, final Request request) { - final VPackSlice body = request.getBody(); - if (body != null) { - if (contentType == Protocol.HTTP_VPACK) { - httpRequest.setEntity(new ByteArrayEntity( - Arrays.copyOfRange(body.getBuffer(), body.getStart(), body.getStart() + body.getByteSize()), - CONTENT_TYPE_VPACK)); - } else { - String json = body.toString(); - if (json.length() > MAX_JSON_LENGTH) { - LOGGER.warn("Json string length is greater than safe threshold (" + MAX_JSON_LENGTH + "). " + - "This could cause memory allocation errors."); - } - httpRequest.setEntity(new StringEntity(json, CONTENT_TYPE_APPLICATION_JSON_UTF8)); - } - } - return httpRequest; - } - - private String buildBaseUrl(final HostDescription host) { - return (Boolean.TRUE == useSsl ? "https://" : "http://") + host.getHost() + ":" + host.getPort(); - } - - private static List toList(final Map parameters) { - final ArrayList paramList = new ArrayList<>(parameters.size()); - for (final Entry param : parameters.entrySet()) { - if (param.getValue() != null) { - paramList.add(new BasicNameValuePair(param.getKey(), param.getValue())); - } - } - return paramList; - } - - public Response execute(final Request request) throws ArangoDBException, IOException { - final String url = buildUrl(buildBaseUrl(host), request); - final HttpRequestBase httpRequest = buildHttpRequestBase(request, url); - httpRequest.setHeader("User-Agent", "Mozilla/5.0 (compatible; ArangoDB-JavaDriver/1.1; +http://mt.orz.at/)"); - if (contentType == Protocol.HTTP_VPACK) { - httpRequest.setHeader("Accept", "application/x-velocypack"); - } - addHeader(request, httpRequest); - Credentials credentials = null; - if (jwt != null) { - httpRequest.addHeader(AUTHORIZATION, "Bearer " + jwt); - } else if (user != null) { - credentials = new UsernamePasswordCredentials(user, password != null ? password : ""); - try { - httpRequest.addHeader(new BasicScheme().authenticate(credentials, httpRequest, null)); - } catch (final AuthenticationException e) { - throw new ArangoDBException(e); - } - } - if (LOGGER.isDebugEnabled()) { - CURLLogger.log(url, request, credentials, jwt, util); - } - Response response; - response = buildResponse(client.execute(httpRequest)); - checkError(response); - return response; - } - - private static void addHeader(final Request request, final HttpRequestBase httpRequest) { - for (final Entry header : request.getHeaderParam().entrySet()) { - httpRequest.addHeader(header.getKey(), header.getValue()); - } - } - - public Response buildResponse(final CloseableHttpResponse httpResponse) - throws UnsupportedOperationException, IOException { - final Response response = new Response(); - response.setResponseCode(httpResponse.getStatusLine().getStatusCode()); - final HttpEntity entity = httpResponse.getEntity(); - if (entity != null && entity.getContent() != null) { - if (contentType == Protocol.HTTP_VPACK) { - final byte[] content = IOUtils.toByteArray(entity.getContent()); - if (content.length > 0) { - response.setBody(new VPackSlice(content)); - } - } else { - final String content = IOUtils.toString(entity.getContent()); - if (!content.isEmpty()) { - response.setBody( - util.serialize(content, new Options().stringAsJson(true).serializeNullValues(true))); - } - } - } - final Header[] headers = httpResponse.getAllHeaders(); - final Map meta = response.getMeta(); - for (final Header header : headers) { - meta.put(header.getName(), header.getValue()); - } - return response; - } - - protected void checkError(final Response response) throws ArangoDBException { - ResponseUtils.checkError(util, response); - } - - @Override - public void setJwt(String jwt) { - this.jwt = jwt; - } - -} diff --git a/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java b/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java deleted file mode 100644 index 0461cd098..000000000 --- a/src/main/java/com/arangodb/internal/http/HttpConnectionFactory.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.http; - -import com.arangodb.Protocol; -import com.arangodb.internal.net.Connection; -import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.internal.net.HostDescription; -import com.arangodb.util.ArangoSerialization; -import org.apache.http.client.HttpRequestRetryHandler; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLContext; - -/** - * @author Mark Vollmary - */ -public class HttpConnectionFactory implements ConnectionFactory { - - private final HttpConnection.Builder builder; - - public HttpConnectionFactory(final Integer timeout, final String user, final String password, final Boolean useSsl, - final SSLContext sslContext, final HostnameVerifier hostnameVerifier, - final ArangoSerialization util, final Protocol protocol, final Long connectionTtl, - final String httpCookieSpec, final HttpRequestRetryHandler httpRequestRetryHandler) { - super(); - builder = new HttpConnection.Builder().timeout(timeout).user(user).password(password).useSsl(useSsl) - .sslContext(sslContext).hostnameVerifier(hostnameVerifier).serializationUtil(util).contentType(protocol) - .ttl(connectionTtl).httpCookieSpec(httpCookieSpec).httpRequestRetryHandler(httpRequestRetryHandler); - - } - - @Override - public Connection create(final HostDescription host) { - return builder.host(host).build(); - } - -} diff --git a/src/main/java/com/arangodb/internal/http/HttpDeleteWithBody.java b/src/main/java/com/arangodb/internal/http/HttpDeleteWithBody.java deleted file mode 100644 index 080e01974..000000000 --- a/src/main/java/com/arangodb/internal/http/HttpDeleteWithBody.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.http; - -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; - -import java.net.URI; - -/** - * @author Mark Vollmary - */ -public class HttpDeleteWithBody extends HttpEntityEnclosingRequestBase { - public final static String METHOD_NAME = "DELETE"; - - public HttpDeleteWithBody(final String uri) { - super(); - setURI(URI.create(uri)); - } - - @Override - public String getMethod() { - return METHOD_NAME; - } - -} diff --git a/src/main/java/com/arangodb/internal/mapping/ArangoAnnotationIntrospector.java b/src/main/java/com/arangodb/internal/mapping/ArangoAnnotationIntrospector.java deleted file mode 100644 index 33dab6a91..000000000 --- a/src/main/java/com/arangodb/internal/mapping/ArangoAnnotationIntrospector.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.mapping; - - -import com.arangodb.entity.DocumentField; -import com.arangodb.velocypack.annotations.Expose; -import com.arangodb.velocypack.annotations.SerializedName; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.PropertyName; -import com.fasterxml.jackson.databind.introspect.Annotated; -import com.fasterxml.jackson.databind.introspect.AnnotatedMember; -import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; -import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; - -/** - * @author Michele Rastelli - */ -public class ArangoAnnotationIntrospector extends JacksonAnnotationIntrospector { - - @Override - public JsonProperty.Access findPropertyAccess(Annotated m) { - if (!(m instanceof AnnotatedMember)) { - return super.findPropertyAccess(m); - } - - final Expose expose = m.getAnnotation(Expose.class); - if (expose != null) { - final boolean serialize = expose.serialize(); - final boolean deserialize = expose.deserialize(); - - if (serialize && deserialize) { - return JsonProperty.Access.READ_WRITE; - } else if (serialize) { - return JsonProperty.Access.READ_ONLY; - } else if (deserialize) { - return JsonProperty.Access.WRITE_ONLY; - } - } - - return super.findPropertyAccess(m); - } - - @Override - public boolean hasIgnoreMarker(AnnotatedMember m) { - final Expose expose = m.getAnnotation(Expose.class); - if (expose != null && !expose.serialize() && !expose.deserialize()) { - return true; - } - return super.hasIgnoreMarker(m); - } - - @Override - public PropertyName findNameForSerialization(Annotated a) { - PropertyName name = findPropertyName(a); - if (name != null) { - return name; - } else { - return super.findNameForSerialization(a); - } - } - - @Override - public PropertyName findNameForDeserialization(Annotated a) { - PropertyName name = findPropertyName(a); - if (name != null) { - return name; - } else { - return super.findNameForDeserialization(a); - } - } - - @Override - public String findImplicitPropertyName(AnnotatedMember member) { - String name = findParameterName(member); - if (name != null) { - return name; - } else { - return super.findImplicitPropertyName(member); - } - } - - private String findParameterName(Annotated a) { - if (!(a instanceof AnnotatedParameter)) { - return null; - } - - final SerializedName serializedName = a.getAnnotation(SerializedName.class); - if (serializedName != null) { - return serializedName.value(); - } - - return null; - } - - private PropertyName findPropertyName(Annotated a) { - if (!(a instanceof AnnotatedMember)) { - return null; - } - - final DocumentField documentField = a.getAnnotation(DocumentField.class); - if (documentField != null) { - return PropertyName.construct(documentField.value().getSerializeName()); - } - - final SerializedName serializedName = a.getAnnotation(SerializedName.class); - if (serializedName != null) { - return PropertyName.construct(serializedName.value()); - } - - return null; - } - -} - diff --git a/src/main/java/com/arangodb/internal/mapping/VPackDeserializers.java b/src/main/java/com/arangodb/internal/mapping/VPackDeserializers.java deleted file mode 100644 index a30d9d0cf..000000000 --- a/src/main/java/com/arangodb/internal/mapping/VPackDeserializers.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.mapping; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.jackson.dataformat.velocypack.internal.VPackParser; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.internal.util.DateUtil; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; - -import java.io.IOException; -import java.text.ParseException; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class VPackDeserializers { - - public static final JsonDeserializer VPACK = new JsonDeserializer() { - @Override - public VPackSlice deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException, JsonProcessingException { - if (p instanceof VPackParser) { - final VPackSlice vpack = ((VPackParser) p).getVPack(); - // consume each element - if (vpack.isArray() || vpack.isObject()) { - for (int i = 0; i < vpack.size() + 1; i++) { - p.nextToken(); - } - } - return vpack; - } - return new VPackSlice(p.getBinaryValue()); - } - }; - - public static final JsonDeserializer UTIL_DATE = new JsonDeserializer() { - @Override - public java.util.Date deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException, JsonProcessingException { - try { - return DateUtil.parse(p.getValueAsString()); - } catch (final ParseException e) { - throw new IOException(e); - } - } - }; - - public static final JsonDeserializer SQL_DATE = new JsonDeserializer() { - @Override - public java.sql.Date deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException, JsonProcessingException { - try { - return new java.sql.Date(DateUtil.parse(p.getValueAsString()).getTime()); - } catch (final ParseException e) { - throw new IOException(e); - } - } - }; - - public static final JsonDeserializer SQL_TIMESTAMP = new JsonDeserializer() { - @Override - public java.sql.Timestamp deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException, JsonProcessingException { - try { - return new java.sql.Timestamp(DateUtil.parse(p.getValueAsString()).getTime()); - } catch (final ParseException e) { - throw new IOException(e); - } - } - }; - - public static final JsonDeserializer BASE_DOCUMENT = new JsonDeserializer() { - @SuppressWarnings("unchecked") - @Override - public BaseDocument deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException, JsonProcessingException { - return new BaseDocument(p.readValueAs(Map.class)); - } - }; - - public static final JsonDeserializer BASE_EDGE_DOCUMENT = new JsonDeserializer() { - @SuppressWarnings("unchecked") - @Override - public BaseEdgeDocument deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException, JsonProcessingException { - return new BaseEdgeDocument(p.readValueAs(Map.class)); - } - }; - -} diff --git a/src/main/java/com/arangodb/internal/mapping/VPackSerializers.java b/src/main/java/com/arangodb/internal/mapping/VPackSerializers.java deleted file mode 100644 index eb4b4ad8f..000000000 --- a/src/main/java/com/arangodb/internal/mapping/VPackSerializers.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - - -package com.arangodb.internal.mapping; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.internal.DocumentFields; -import com.arangodb.jackson.dataformat.velocypack.internal.VPackGenerator; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.internal.util.DateUtil; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -import java.io.IOException; -import java.sql.Date; -import java.sql.Timestamp; -import java.util.HashMap; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class VPackSerializers { - - public static final JsonSerializer VPACK = new JsonSerializer() { - @Override - public void serialize(final VPackSlice value, final JsonGenerator gen, final SerializerProvider serializers) - throws IOException { - if (gen instanceof VPackGenerator) { - ((VPackGenerator) gen).writeVPack(value); - } else { - gen.writeBinary(value.toByteArray()); - } - } - }; - - public static final JsonSerializer UTIL_DATE = new JsonSerializer() { - @Override - public void serialize(final java.util.Date value, final JsonGenerator gen, final SerializerProvider serializers) - throws IOException, JsonProcessingException { - gen.writeString(DateUtil.format(value)); - } - }; - - public static final JsonSerializer SQL_DATE = new JsonSerializer() { - @Override - public void serialize(final Date value, final JsonGenerator gen, final SerializerProvider serializers) - throws IOException, JsonProcessingException { - gen.writeString(DateUtil.format(value)); - } - }; - - public static final JsonSerializer SQL_TIMESTAMP = new JsonSerializer() { - @Override - public void serialize(final Timestamp value, final JsonGenerator gen, final SerializerProvider serializers) - throws IOException, JsonProcessingException { - gen.writeString(DateUtil.format(value)); - } - }; - - public static final JsonSerializer BASE_DOCUMENT = new JsonSerializer() { - @Override - public void serialize(final BaseDocument value, final JsonGenerator gen, final SerializerProvider serializers) - throws IOException { - final Map doc = new HashMap<>(); - doc.putAll(value.getProperties()); - doc.put(DocumentFields.ID, value.getId()); - doc.put(DocumentFields.KEY, value.getKey()); - doc.put(DocumentFields.REV, value.getRevision()); - gen.writeObject(doc); - } - }; - - public static final JsonSerializer BASE_EDGE_DOCUMENT = new JsonSerializer() { - @Override - public void serialize( - final BaseEdgeDocument value, - final JsonGenerator gen, - final SerializerProvider serializers) throws IOException { - final Map doc = new HashMap<>(); - doc.putAll(value.getProperties()); - doc.put(DocumentFields.ID, value.getId()); - doc.put(DocumentFields.KEY, value.getKey()); - doc.put(DocumentFields.REV, value.getRevision()); - doc.put(DocumentFields.FROM, value.getFrom()); - doc.put(DocumentFields.TO, value.getTo()); - gen.writeObject(doc); - } - }; - -} diff --git a/src/main/java/com/arangodb/internal/util/ArangoDeserializerImpl.java b/src/main/java/com/arangodb/internal/util/ArangoDeserializerImpl.java deleted file mode 100644 index 79fa9025b..000000000 --- a/src/main/java/com/arangodb/internal/util/ArangoDeserializerImpl.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.util; - -import com.arangodb.ArangoDBException; -import com.arangodb.util.ArangoDeserializer; -import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPackParser; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.exception.VPackException; - -import java.lang.reflect.Type; - -/** - * @author Mark Vollmary - */ -public class ArangoDeserializerImpl implements ArangoDeserializer { - - private final VPack vpacker; - private final VPackParser vpackParser; - - public ArangoDeserializerImpl(final VPack vpacker, final VPackParser vpackParser) { - super(); - this.vpacker = vpacker; - this.vpackParser = vpackParser; - } - - @Override - @SuppressWarnings("unchecked") - public T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException { - try { - final T doc; - if (type == String.class && !vpack.isString() && !vpack.isNull()) { - doc = (T) vpackParser.toJson(vpack, true); - } else { - doc = vpacker.deserialize(vpack, type); - } - return doc; - } catch (final VPackException e) { - throw new ArangoDBException(e); - } - } -} diff --git a/src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java b/src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java deleted file mode 100644 index 035c2dc92..000000000 --- a/src/main/java/com/arangodb/internal/util/ArangoSerializationFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.util; - -import com.arangodb.util.ArangoSerialization; - -/** - * @author Mark Vollmary - */ -public class ArangoSerializationFactory { - - public enum Serializer { - INTERNAL, CUSTOM - } - - private final ArangoSerialization interal; - private final ArangoSerialization custom; - - public ArangoSerializationFactory(final ArangoSerialization interal, final ArangoSerialization custom) { - super(); - this.interal = interal; - this.custom = custom; - } - - public ArangoSerialization get(final Serializer serializer) { - switch (serializer) { - case CUSTOM: - return custom; - case INTERNAL: - default: - return interal; - } - } - -} diff --git a/src/main/java/com/arangodb/internal/util/ArangoSerializerImpl.java b/src/main/java/com/arangodb/internal/util/ArangoSerializerImpl.java deleted file mode 100644 index 7561622ce..000000000 --- a/src/main/java/com/arangodb/internal/util/ArangoSerializerImpl.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.util; - -import com.arangodb.ArangoDBException; -import com.arangodb.util.ArangoSerializer; -import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPack.SerializeOptions; -import com.arangodb.velocypack.VPackParser; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.exception.VPackException; - -import java.util.Iterator; - -/** - * @author Mark Vollmary - */ -public class ArangoSerializerImpl implements ArangoSerializer { - - private final VPack vpacker; - private final VPack vpackerNull; - private final VPackParser vpackParser; - - public ArangoSerializerImpl(final VPack vpacker, final VPack vpackerNull, final VPackParser vpackParser) { - super(); - this.vpacker = vpacker; - this.vpackerNull = vpackerNull; - this.vpackParser = vpackParser; - } - - @Override - public VPackSlice serialize(final Object entity) throws ArangoDBException { - return serialize(entity, new ArangoSerializer.Options()); - } - - @SuppressWarnings("unchecked") - @Override - public VPackSlice serialize(final Object entity, final Options options) throws ArangoDBException { - if (options.getType() == null) { - options.type(entity.getClass()); - } - try { - final VPackSlice vpack; - final Class type = entity.getClass(); - final boolean serializeNullValues = options.isSerializeNullValues(); - if (String.class.isAssignableFrom(type)) { - vpack = vpackParser.fromJson((String) entity, serializeNullValues); - } else if (options.isStringAsJson() && Iterable.class.isAssignableFrom(type)) { - final Iterator iterator = ((Iterable) entity).iterator(); - if (iterator.hasNext() && String.class.isAssignableFrom(iterator.next().getClass())) { - vpack = vpackParser.fromJson((Iterable) entity, serializeNullValues); - } else { - final VPack vp = serializeNullValues ? vpackerNull : vpacker; - vpack = vp.serialize(entity, - new SerializeOptions().type(options.getType()).additionalFields(options.getAdditionalFields())); - } - } else { - final VPack vp = serializeNullValues ? vpackerNull : vpacker; - vpack = vp.serialize(entity, - new SerializeOptions().type(options.getType()).additionalFields(options.getAdditionalFields())); - } - return vpack; - } catch (final VPackException e) { - throw new ArangoDBException(e); - } - } - -} diff --git a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java b/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java deleted file mode 100644 index f77f2ee49..000000000 --- a/src/main/java/com/arangodb/internal/util/DefaultArangoSerialization.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.util; - -import com.arangodb.ArangoDBException; -import com.arangodb.util.ArangoDeserializer; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.ArangoSerializer; -import com.arangodb.velocypack.VPackSlice; - -import java.lang.reflect.Type; - -/** - * @author Mark Vollmary - */ -public class DefaultArangoSerialization implements ArangoSerialization { - - private final ArangoSerializer serializer; - private final ArangoDeserializer deserializer; - - public DefaultArangoSerialization(final ArangoSerializer serializer, final ArangoDeserializer deserializer) { - super(); - this.serializer = serializer; - this.deserializer = deserializer; - } - - @Override - public VPackSlice serialize(final Object entity) throws ArangoDBException { - return serializer.serialize(entity); - } - - @Override - public VPackSlice serialize(final Object entity, final Options options) throws ArangoDBException { - return serializer.serialize(entity, options); - } - - @Override - public T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException { - return deserializer.deserialize(vpack, type); - } - -} diff --git a/src/main/java/com/arangodb/internal/util/IOUtils.java b/src/main/java/com/arangodb/internal/util/IOUtils.java deleted file mode 100644 index c2985c4f6..000000000 --- a/src/main/java/com/arangodb/internal/util/IOUtils.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.util; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; - -/** - * @author Mark Vollmary - */ -public final class IOUtils { - - private static final Logger LOGGER = LoggerFactory.getLogger(IOUtils.class); - - private IOUtils() { - } - - public static String toString(final InputStream input) throws IOException { - return toString(input, "utf-8"); - } - - public static String toString(final InputStream input, final String encode) throws IOException { - try { - final StringBuilder buffer = new StringBuilder(8012); - final InputStreamReader in = new InputStreamReader(new BufferedInputStream(input), encode); - final char[] cbuf = new char[8012]; - int len; - while ((len = in.read(cbuf)) != -1) { - buffer.append(cbuf, 0, len); - } - return buffer.toString(); - } catch (final UnsupportedEncodingException e) { - throw new RuntimeException(e); - } finally { - if (input != null) { - try { - input.close(); - } catch (final IOException e) { - // TODO - } - } - } - } - - public static byte[] toByteArray(final InputStream input) throws IOException { - final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - int nRead; - final byte[] data = new byte[8012]; - while ((nRead = input.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, nRead); - } - buffer.flush(); - return buffer.toByteArray(); - } - -} diff --git a/src/main/java/com/arangodb/internal/util/ResponseUtils.java b/src/main/java/com/arangodb/internal/util/ResponseUtils.java deleted file mode 100644 index 0cc5e38cb..000000000 --- a/src/main/java/com/arangodb/internal/util/ResponseUtils.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.util; - -import com.arangodb.ArangoDBException; -import com.arangodb.entity.ErrorEntity; -import com.arangodb.internal.ArangoErrors; -import com.arangodb.internal.net.ArangoDBRedirectException; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocypack.exception.VPackParserException; -import com.arangodb.velocystream.Response; - -import java.util.concurrent.TimeoutException; - -/** - * @author Mark Vollmary - */ -public final class ResponseUtils { - - private static final int ERROR_STATUS = 300; - private static final int ERROR_INTERNAL = 503; - private static final String HEADER_ENDPOINT = "X-Arango-Endpoint"; - - private ResponseUtils() { - super(); - } - - public static void checkError(final ArangoSerialization util, final Response response) throws ArangoDBException { - try { - final int responseCode = response.getResponseCode(); - if (responseCode >= ERROR_STATUS) { - if (responseCode == ERROR_INTERNAL && response.getMeta().containsKey(HEADER_ENDPOINT)) { - throw new ArangoDBRedirectException(String.format("Response Code: %s", responseCode), - response.getMeta().get(HEADER_ENDPOINT)); - } else if (response.getBody() != null) { - final ErrorEntity errorEntity = util.deserialize(response.getBody(), ErrorEntity.class); - ArangoDBException e = new ArangoDBException(errorEntity); - if(ArangoErrors.QUEUE_TIME_VIOLATED.equals(e.getErrorNum())){ - throw new ArangoDBException(new TimeoutException().initCause(e)); - } - throw e; - } else { - throw new ArangoDBException(String.format("Response Code: %s", responseCode), responseCode); - } - } - } catch (final VPackParserException e) { - throw new ArangoDBException(e); - } - } -} diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java deleted file mode 100644 index 3a5a32084..000000000 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java +++ /dev/null @@ -1,333 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocypack; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.entity.CollectionStatus; -import com.arangodb.entity.CollectionType; -import com.arangodb.entity.License; -import com.arangodb.entity.LogLevel; -import com.arangodb.entity.MinReplicationFactor; -import com.arangodb.entity.Permissions; -import com.arangodb.entity.QueryExecutionState; -import com.arangodb.entity.ReplicationFactor; -import com.arangodb.entity.ViewEntity; -import com.arangodb.entity.ViewType; -import com.arangodb.entity.arangosearch.AnalyzerType; -import com.arangodb.entity.arangosearch.ArangoSearchCompression; -import com.arangodb.entity.arangosearch.ArangoSearchProperties; -import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; -import com.arangodb.entity.arangosearch.CollectionLink; -import com.arangodb.entity.arangosearch.ConsolidationPolicy; -import com.arangodb.entity.arangosearch.ConsolidationType; -import com.arangodb.entity.arangosearch.FieldLink; -import com.arangodb.entity.arangosearch.PrimarySort; -import com.arangodb.entity.arangosearch.StoreValuesType; -import com.arangodb.entity.arangosearch.StoredValue; -import com.arangodb.entity.arangosearch.analyzer.*; -import com.arangodb.model.CollectionSchema; -import com.arangodb.model.ZKDIndexOptions; -import com.arangodb.velocypack.VPackDeserializer; -import com.arangodb.velocypack.VPackParser; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocystream.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.Map.Entry; - -/** - * @author Mark Vollmary - */ -public class VPackDeserializers { - - private static final Logger LOGGER = LoggerFactory.getLogger(VPackDeserializers.class); - private static final String DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; - - public static final VPackDeserializer RESPONSE = (parent, vpack, context) -> { - final Response response = new Response(); - response.setVersion(vpack.get(0).getAsInt()); - response.setType(vpack.get(1).getAsInt()); - response.setResponseCode(vpack.get(2).getAsInt()); - if (vpack.size() > 3) { - response.setMeta(context.deserialize(vpack.get(3), Map.class)); - } - return response; - }; - - public static final VPackDeserializer COLLECTION_TYPE = (parent, vpack, context) -> CollectionType.fromType(vpack.getAsInt()); - - public static final VPackDeserializer COLLECTION_STATUS = (parent, vpack, context) -> CollectionStatus.fromStatus(vpack.getAsInt()); - - @SuppressWarnings("unchecked") - public static final VPackDeserializer BASE_DOCUMENT = (parent, vpack, context) -> new BaseDocument((Map) context.deserialize(vpack, Map.class)); - - public static final VPackDeserializer SEARCH_ANALYZER = (parent, vpack, context) -> { - AnalyzerType type = context.deserialize(vpack.get("type"), AnalyzerType.class); - switch (type) { - case identity: - return context.deserialize(vpack, IdentityAnalyzer.class); - case text: - return context.deserialize(vpack, TextAnalyzer.class); - case ngram: - return context.deserialize(vpack, NGramAnalyzer.class); - case delimiter: - return context.deserialize(vpack, DelimiterAnalyzer.class); - case stem: - return context.deserialize(vpack, StemAnalyzer.class); - case norm: - return context.deserialize(vpack, NormAnalyzer.class); - case pipeline: - return context.deserialize(vpack, PipelineAnalyzer.class); - case stopwords: - return context.deserialize(vpack, StopwordsAnalyzer.class); - case aql: - return context.deserialize(vpack, AQLAnalyzer.class); - case geojson: - return context.deserialize(vpack, GeoJSONAnalyzer.class); - case geopoint: - return context.deserialize(vpack, GeoPointAnalyzer.class); - case segmentation: - return context.deserialize(vpack, SegmentationAnalyzer.class); - case collation: - return context.deserialize(vpack, CollationAnalyzer.class); - default: - throw new IllegalArgumentException("Unknown analyzer type: " + type); - } - }; - - @SuppressWarnings("unchecked") - public static final VPackDeserializer BASE_EDGE_DOCUMENT = (parent, vpack, context) -> new BaseEdgeDocument((Map) context.deserialize(vpack, Map.class)); - - public static final VPackDeserializer DATE_STRING = (parent, vpack, context) -> { - try { - return new SimpleDateFormat(DATE_TIME_FORMAT).parse(vpack.getAsString()); - } catch (final ParseException e) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("got ParseException for date string: " + vpack.getAsString()); - } - } - return null; - }; - - public static final VPackDeserializer LOG_LEVEL = (parent, vpack, context) -> LogLevel.fromLevel(vpack.getAsInt()); - - public static final VPackDeserializer LICENSE = (parent, vpack, context) -> License.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH)); - - public static final VPackDeserializer PERMISSIONS = (parent, vpack, context) -> Permissions.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH)); - - public static final VPackDeserializer QUERY_EXECUTION_STATE = (parent, vpack, context) -> QueryExecutionState.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH).replaceAll(" ", "_")); - - public static final VPackDeserializer REPLICATION_FACTOR = (parent, vpack, context) -> { - final ReplicationFactor replicationFactor = new ReplicationFactor(); - if (vpack.isString() && vpack.getAsString().equals("satellite")) { - replicationFactor.setSatellite(true); - } else { - replicationFactor.setReplicationFactor(vpack.getAsInt()); - } - return replicationFactor; - }; - - public static final VPackDeserializer MIN_REPLICATION_FACTOR = (parent, vpack, context) -> { - final MinReplicationFactor minReplicationFactor = new MinReplicationFactor(); - minReplicationFactor.setMinReplicationFactor(vpack.getAsInt()); - return minReplicationFactor; - }; - - public static final VPackDeserializer VIEW_TYPE = (parent, vpack, context) -> "arangosearch".equals(vpack.getAsString()) ? ViewType.ARANGO_SEARCH - : ViewType.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH)); - - public static final VPackDeserializer ARANGO_SEARCH_PROPERTIES = (parent, vpack, context) -> { - final ArangoSearchProperties properties = new ArangoSearchProperties(); - final VPackSlice consolidationIntervalMsec = vpack.get("consolidationIntervalMsec"); - if (consolidationIntervalMsec.isInteger()) { - properties.setConsolidationIntervalMsec(consolidationIntervalMsec.getAsLong()); - } - - final VPackSlice commitIntervalMsec = vpack.get("commitIntervalMsec"); - if (commitIntervalMsec.isInteger()) { - properties.setCommitIntervalMsec(commitIntervalMsec.getAsLong()); - } - - final VPackSlice cleanupIntervalStep = vpack.get("cleanupIntervalStep"); - if (cleanupIntervalStep.isInteger()) { - properties.setCleanupIntervalStep(cleanupIntervalStep.getAsLong()); - } - - final VPackSlice consolidationPolicy = vpack.get("consolidationPolicy"); - if (consolidationPolicy.isObject()) { - properties.setConsolidationPolicy( - context.deserialize(consolidationPolicy, ConsolidationPolicy.class)); - } - - final VPackSlice links = vpack.get("links"); - if (links.isObject()) { - final Iterator> collectionIterator = links.objectIterator(); - for (; collectionIterator.hasNext(); ) { - final Entry entry = collectionIterator.next(); - final VPackSlice value = entry.getValue(); - final CollectionLink link = CollectionLink.on(entry.getKey()); - final VPackSlice analyzers = value.get("analyzers"); - if (analyzers.isArray()) { - final Iterator analyzerIterator = analyzers.arrayIterator(); - for (; analyzerIterator.hasNext(); ) { - link.analyzers(analyzerIterator.next().getAsString()); - } - } - final VPackSlice includeAllFields = value.get("includeAllFields"); - if (includeAllFields.isBoolean()) { - link.includeAllFields(includeAllFields.getAsBoolean()); - } - final VPackSlice trackListPositions = value.get("trackListPositions"); - if (trackListPositions.isBoolean()) { - link.trackListPositions(trackListPositions.getAsBoolean()); - } - final VPackSlice storeValues = value.get("storeValues"); - if (storeValues.isString()) { - link.storeValues(StoreValuesType.valueOf(storeValues.getAsString().toUpperCase(Locale.ENGLISH))); - } - final VPackSlice fields = value.get("fields"); - if (fields.isObject()) { - final Iterator> fieldsIterator = fields.objectIterator(); - for (; fieldsIterator.hasNext(); ) { - link.fields(deserializeField(fieldsIterator.next())); - } - } - properties.addLink(link); - } - } - - final VPackSlice primarySorts = vpack.get("primarySort"); - if (primarySorts.isArray()) { - final Iterator primarySortsIterator = primarySorts.arrayIterator(); - for (; primarySortsIterator.hasNext(); ) { - final VPackSlice entry = primarySortsIterator.next(); - if (entry.isObject()) { - if (entry.get("field").isString() && entry.get("asc").isBoolean()) { - final PrimarySort primarySort = PrimarySort.on(entry.get("field").getAsString()); - primarySort.ascending(entry.get("asc").getAsBoolean()); - properties.addPrimarySort(primarySort); - } - } - } - } - - final VPackSlice primarySortCompression = vpack.get("primarySortCompression"); - if (primarySortCompression.isString()) { - properties.setPrimarySortCompression(ArangoSearchCompression.valueOf(primarySortCompression.getAsString())); - } - - final VPackSlice storedValues = vpack.get("storedValues"); - if (storedValues.isArray()) { - final Iterator storedValueIterator = storedValues.arrayIterator(); - for (; storedValueIterator.hasNext(); ) { - final VPackSlice entry = storedValueIterator.next(); - if (entry.isObject()) { - VPackSlice fields = entry.get("fields"); - VPackSlice compression = entry.get("compression"); - if (fields.isArray() && compression.isString()) { - final Iterator fieldsIterator = fields.arrayIterator(); - List fieldsList = new ArrayList<>(); - fieldsIterator.forEachRemaining(it -> fieldsList.add(it.getAsString())); - properties.addStoredValues(new StoredValue(fieldsList, ArangoSearchCompression.valueOf(compression.getAsString()))); - } - } - } - } - - return properties; - }; - - protected static FieldLink deserializeField(final Entry field) { - final VPackSlice value = field.getValue(); - final FieldLink link = FieldLink.on(field.getKey()); - final VPackSlice analyzers = value.get("analyzers"); - if (analyzers.isArray()) { - final Iterator analyzerIterator = analyzers.arrayIterator(); - for (; analyzerIterator.hasNext(); ) { - link.analyzers(analyzerIterator.next().getAsString()); - } - } - final VPackSlice includeAllFields = value.get("includeAllFields"); - if (includeAllFields.isBoolean()) { - link.includeAllFields(includeAllFields.getAsBoolean()); - } - final VPackSlice trackListPositions = value.get("trackListPositions"); - if (trackListPositions.isBoolean()) { - link.trackListPositions(trackListPositions.getAsBoolean()); - } - final VPackSlice storeValues = value.get("storeValues"); - if (storeValues.isString()) { - link.storeValues(StoreValuesType.valueOf(storeValues.getAsString().toUpperCase(Locale.ENGLISH))); - } - final VPackSlice fields = value.get("fields"); - if (fields.isObject()) { - final Iterator> fieldsIterator = fields.objectIterator(); - for (; fieldsIterator.hasNext(); ) { - link.fields(deserializeField(fieldsIterator.next())); - } - } - return link; - } - - public static final VPackDeserializer ARANGO_SEARCH_PROPERTIES_ENTITY = (parent, vpack, context) -> { - final ViewEntity entity = context.deserialize(vpack, ViewEntity.class); - final ArangoSearchProperties properties = context.deserialize(vpack, ArangoSearchProperties.class); - return new ArangoSearchPropertiesEntity(entity.getId(), - entity.getName(), entity.getType(), properties); - }; - - public static final VPackDeserializer CONSOLIDATE = (parent, vpack, context) -> { - final VPackSlice type = vpack.get("type"); - if (type.isString()) { - final ConsolidationPolicy consolidate = ConsolidationPolicy - .of(ConsolidationType.valueOf(type.getAsString().toUpperCase(Locale.ENGLISH))); - final VPackSlice threshold = vpack.get("threshold"); - if (threshold.isNumber()) { - consolidate.threshold(threshold.getAsDouble()); - } - final VPackSlice segmentThreshold = vpack.get("segmentThreshold"); - if (segmentThreshold.isInteger()) { - consolidate.segmentThreshold(segmentThreshold.getAsLong()); - } - return consolidate; - } - return null; - }; - - public static final VPackDeserializer COLLECTION_VALIDATION = (parent, vpack, context) -> { - VPackParser parser = new VPackParser.Builder().build(); - CollectionSchema collectionValidation = new CollectionSchema(); - collectionValidation.setLevel(CollectionSchema.Level.of(vpack.get("level").getAsString())); - collectionValidation.setRule(parser.toJson(vpack.get("rule"), true)); - collectionValidation.setMessage(vpack.get("message").getAsString()); - return collectionValidation; - }; - - public static final VPackDeserializer ZKD_FIELD_VALUE_TYPES = - (parent, vpack, context) -> ZKDIndexOptions.FieldValueTypes.valueOf(vpack.getAsString().toUpperCase(Locale.ENGLISH)); - - -} diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java b/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java deleted file mode 100644 index 4bd3e84f9..000000000 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDriverModule.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocypack; - -import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.ArangoSearchProperties; -import com.arangodb.entity.arangosearch.ArangoSearchPropertiesEntity; -import com.arangodb.entity.arangosearch.ConsolidationPolicy; -import com.arangodb.entity.arangosearch.ConsolidationType; -import com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer; -import com.arangodb.internal.DocumentFields; -import com.arangodb.internal.velocystream.internal.AuthenticationRequest; -import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; -import com.arangodb.model.CollectionSchema; -import com.arangodb.model.TraversalOptions; -import com.arangodb.model.ZKDIndexOptions; -import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; -import com.arangodb.velocypack.VPackModule; -import com.arangodb.velocypack.VPackParserModule; -import com.arangodb.velocypack.VPackParserSetupContext; -import com.arangodb.velocypack.VPackSetupContext; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; - -import java.lang.annotation.Annotation; -import java.util.Date; - -/** - * @author Mark Vollmary - */ -public class VPackDriverModule implements VPackModule, VPackParserModule { - - @Override - public > void setup(final C context) { - context.fieldNamingStrategy(field -> { - for (Annotation annotation : field.getAnnotations()) { - if(annotation instanceof DocumentField) { - return ((DocumentField) annotation).value().getSerializeName(); - } else if (annotation instanceof Id) { - return DocumentFields.ID; - } else if (annotation instanceof Key) { - return DocumentFields.KEY; - } else if (annotation instanceof Rev) { - return DocumentFields.REV; - } else if (annotation instanceof From) { - return DocumentFields.FROM; - } else if (annotation instanceof To) { - return DocumentFields.TO; - } - } - return field.getName(); - }); - context.registerSerializer(Request.class, VPackSerializers.REQUEST); - context.registerSerializer(AuthenticationRequest.class, VPackSerializers.AUTH_REQUEST); - context.registerSerializer(JwtAuthenticationRequest.class, VPackSerializers.JWT_AUTH_REQUEST); - context.registerSerializer(CollectionType.class, VPackSerializers.COLLECTION_TYPE); - context.registerSerializer(BaseDocument.class, VPackSerializers.BASE_DOCUMENT); - context.registerSerializer(BaseEdgeDocument.class, VPackSerializers.BASE_EDGE_DOCUMENT); - context.registerSerializer(TraversalOptions.Order.class, VPackSerializers.TRAVERSAL_ORDER); - context.registerSerializer(LogLevel.class, VPackSerializers.LOG_LEVEL); - context.registerSerializer(Permissions.class, VPackSerializers.PERMISSIONS); - context.registerSerializer(ReplicationFactor.class, VPackSerializers.REPLICATION_FACTOR); - context.registerSerializer(MinReplicationFactor.class, VPackSerializers.MIN_REPLICATION_FACTOR); - context.registerSerializer(ViewType.class, VPackSerializers.VIEW_TYPE); - context.registerSerializer(ArangoSearchPropertiesOptions.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES_OPTIONS); - context.registerSerializer(ArangoSearchProperties.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES); - context.registerSerializer(ConsolidationType.class, VPackSerializers.CONSOLIDATE_TYPE); - context.registerSerializer(CollectionSchema.class, VPackSerializers.COLLECTION_VALIDATION); - context.registerSerializer(ZKDIndexOptions.FieldValueTypes.class, VPackSerializers.ZKD_FIELD_VALUE_TYPES); - - context.registerDeserializer(Response.class, VPackDeserializers.RESPONSE); - context.registerDeserializer(CollectionType.class, VPackDeserializers.COLLECTION_TYPE); - context.registerDeserializer(CollectionStatus.class, VPackDeserializers.COLLECTION_STATUS); - context.registerDeserializer(BaseDocument.class, VPackDeserializers.BASE_DOCUMENT); - context.registerDeserializer(SearchAnalyzer.class, VPackDeserializers.SEARCH_ANALYZER); - context.registerDeserializer(BaseEdgeDocument.class, VPackDeserializers.BASE_EDGE_DOCUMENT); - context.registerDeserializer(QueryEntity.PROPERTY_STARTED, Date.class, VPackDeserializers.DATE_STRING); - context.registerDeserializer(LogLevel.class, VPackDeserializers.LOG_LEVEL); - context.registerDeserializer(License.class, VPackDeserializers.LICENSE); - context.registerDeserializer(Permissions.class, VPackDeserializers.PERMISSIONS); - context.registerDeserializer(QueryExecutionState.class, VPackDeserializers.QUERY_EXECUTION_STATE); - context.registerDeserializer(ReplicationFactor.class, VPackDeserializers.REPLICATION_FACTOR); - context.registerDeserializer(MinReplicationFactor.class, VPackDeserializers.MIN_REPLICATION_FACTOR); - context.registerDeserializer(ViewType.class, VPackDeserializers.VIEW_TYPE); - context.registerDeserializer(ArangoSearchProperties.class, VPackDeserializers.ARANGO_SEARCH_PROPERTIES); - context.registerDeserializer(ArangoSearchPropertiesEntity.class, VPackDeserializers.ARANGO_SEARCH_PROPERTIES_ENTITY); - context.registerDeserializer(ConsolidationPolicy.class, VPackDeserializers.CONSOLIDATE); - context.registerDeserializer(CollectionSchema.class, VPackDeserializers.COLLECTION_VALIDATION); - context.registerDeserializer(ZKDIndexOptions.FieldValueTypes.class, VPackDeserializers.ZKD_FIELD_VALUE_TYPES); - } - - @Override - public > void setup(final C context) { - - } - -} diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java deleted file mode 100644 index 4d786183d..000000000 --- a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocypack; - -import com.arangodb.entity.*; -import com.arangodb.entity.arangosearch.*; -import com.arangodb.internal.DocumentFields; -import com.arangodb.internal.velocystream.internal.AuthenticationRequest; -import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; -import com.arangodb.model.CollectionSchema; -import com.arangodb.model.TraversalOptions; -import com.arangodb.model.TraversalOptions.Order; -import com.arangodb.model.ZKDIndexOptions; -import com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions; -import com.arangodb.velocypack.*; -import com.arangodb.velocystream.Request; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; - -/** - * @author Mark Vollmary - */ -public class VPackSerializers { - - public static final VPackSerializer REQUEST = (builder, attribute, value, context) -> { - builder.add(attribute, ValueType.ARRAY); - builder.add(value.getVersion()); - builder.add(value.getType()); - builder.add(value.getDbName().get()); - builder.add(value.getRequestType().getType()); - builder.add(value.getRequest()); - builder.add(ValueType.OBJECT); - for (final Entry entry : value.getQueryParam().entrySet()) { - builder.add(entry.getKey(), entry.getValue()); - } - builder.close(); - builder.add(ValueType.OBJECT); - for (final Entry entry : value.getHeaderParam().entrySet()) { - builder.add(entry.getKey(), entry.getValue()); - } - builder.close(); - builder.close(); - }; - - public static final VPackSerializer AUTH_REQUEST = (builder, attribute, value, context) -> { - builder.add(attribute, ValueType.ARRAY); - builder.add(value.getVersion()); - builder.add(value.getType()); - builder.add(value.getEncryption()); - builder.add(value.getUser()); - builder.add(value.getPassword()); - builder.close(); - }; - - public static final VPackSerializer JWT_AUTH_REQUEST = (builder, attribute, value, context) -> { - builder.add(attribute, ValueType.ARRAY); - builder.add(value.getVersion()); - builder.add(value.getType()); - builder.add(value.getEncryption()); - builder.add(value.getToken()); - builder.close(); - }; - - public static final VPackSerializer COLLECTION_TYPE = (builder, attribute, value, context) -> builder.add(attribute, value.getType()); - - public static final VPackSerializer BASE_DOCUMENT = (builder, attribute, value, context) -> { - final Map doc = new HashMap<>(value.getProperties()); - doc.put(DocumentFields.ID, value.getId()); - doc.put(DocumentFields.KEY, value.getKey()); - doc.put(DocumentFields.REV, value.getRevision()); - context.serialize(builder, attribute, doc); - }; - - public static final VPackSerializer BASE_EDGE_DOCUMENT = (builder, attribute, value, context) -> { - final Map doc = new HashMap<>(value.getProperties()); - doc.put(DocumentFields.ID, value.getId()); - doc.put(DocumentFields.KEY, value.getKey()); - doc.put(DocumentFields.REV, value.getRevision()); - doc.put(DocumentFields.FROM, value.getFrom()); - doc.put(DocumentFields.TO, value.getTo()); - context.serialize(builder, attribute, doc); - }; - - public static final VPackSerializer TRAVERSAL_ORDER = (builder, attribute, value, context) -> { - if (Order.preorder_expander == value) { - builder.add(attribute, "preorder-expander"); - } else { - builder.add(attribute, value.name()); - } - }; - - public static final VPackSerializer LOG_LEVEL = (builder, attribute, value, context) -> builder.add(attribute, value.getLevel()); - - public static final VPackSerializer PERMISSIONS = (builder, attribute, value, context) -> builder.add(attribute, value.toString().toLowerCase(Locale.ENGLISH)); - - public static final VPackSerializer REPLICATION_FACTOR = (builder, attribute, value, context) -> { - final Boolean satellite = value.getSatellite(); - if (Boolean.TRUE == satellite) { - builder.add(attribute, "satellite"); - } else if (value.getReplicationFactor() != null) { - builder.add(attribute, value.getReplicationFactor()); - } - }; - - public static final VPackSerializer MIN_REPLICATION_FACTOR = (builder, attribute, value, context) -> { - if (value.getMinReplicationFactor() != null) { - builder.add(attribute, value.getMinReplicationFactor()); - } - }; - - public static final VPackSerializer VIEW_TYPE = (builder, attribute, value, context) -> { - final String type = value == ViewType.ARANGO_SEARCH ? "arangosearch" : value.name().toLowerCase(Locale.ENGLISH); - builder.add(attribute, type); - }; - - public static final VPackSerializer ARANGO_SEARCH_PROPERTIES_OPTIONS = (builder, attribute, value, context) -> { - builder.add(ValueType.OBJECT); - context.serialize(builder, attribute, value.getProperties()); - builder.close(); - }; - - public static final VPackSerializer ARANGO_SEARCH_PROPERTIES = (builder, attribute, value, context) -> { - final Long consolidationIntervalMsec = value.getConsolidationIntervalMsec(); - if (consolidationIntervalMsec != null) { - builder.add("consolidationIntervalMsec", consolidationIntervalMsec); - } - - final Long commitIntervalMsec = value.getCommitIntervalMsec(); - if (commitIntervalMsec != null) { - builder.add("commitIntervalMsec", commitIntervalMsec); - } - - final Long cleanupIntervalStep = value.getCleanupIntervalStep(); - if (cleanupIntervalStep != null) { - builder.add("cleanupIntervalStep", cleanupIntervalStep); - } - context.serialize(builder, "consolidationPolicy", value.getConsolidationPolicy()); - - final Collection links = value.getLinks(); - if (!links.isEmpty()) { - builder.add("links", ValueType.OBJECT); - for (final CollectionLink collectionLink : links) { - builder.add(collectionLink.getName(), ValueType.OBJECT); - final Collection analyzers = collectionLink.getAnalyzers(); - if (!analyzers.isEmpty()) { - builder.add("analyzers", ValueType.ARRAY); - for (final String analyzer : analyzers) { - builder.add(analyzer); - } - builder.close(); - } - final Boolean includeAllFields = collectionLink.getIncludeAllFields(); - if (includeAllFields != null) { - builder.add("includeAllFields", includeAllFields); - } - final Boolean trackListPositions = collectionLink.getTrackListPositions(); - if (trackListPositions != null) { - builder.add("trackListPositions", trackListPositions); - } - final StoreValuesType storeValues = collectionLink.getStoreValues(); - if (storeValues != null) { - builder.add("storeValues", storeValues.name().toLowerCase(Locale.ENGLISH)); - } - serializeFieldLinks(builder, collectionLink.getFields()); - builder.close(); - } - builder.close(); - } - - final Collection primarySorts = value.getPrimarySort(); - if (!primarySorts.isEmpty()) { - builder.add("primarySort", ValueType.ARRAY); // open array - for (final PrimarySort primarySort : primarySorts) { - builder.add(ValueType.OBJECT); // open object - builder.add("field", primarySort.getFieldName()); - builder.add("asc", primarySort.getAscending()); - builder.close(); // close object - } - builder.close(); // close array - } - - final ArangoSearchCompression primarySortCompression = value.getPrimarySortCompression(); - if (primarySortCompression != null) { - builder.add("primarySortCompression", primarySortCompression.getValue()); - } - - final Collection storedValues = value.getStoredValues(); - if (!storedValues.isEmpty()) { - builder.add("storedValues", ValueType.ARRAY); // open array - for (final StoredValue storedValue : storedValues) { - builder.add(ValueType.OBJECT); // open object - builder.add("fields", ValueType.ARRAY); - for (final String field : storedValue.getFields()) { - builder.add(field); - } - builder.close(); - if (storedValue.getCompression() != null) { - builder.add("compression", storedValue.getCompression().getValue()); - } - builder.close(); // close object - } - builder.close(); // close array - } - - }; - - private static void serializeFieldLinks(final VPackBuilder builder, final Collection links) { - if (!links.isEmpty()) { - builder.add("fields", ValueType.OBJECT); - for (final FieldLink fieldLink : links) { - builder.add(fieldLink.getName(), ValueType.OBJECT); - final Collection analyzers = fieldLink.getAnalyzers(); - if (!analyzers.isEmpty()) { - builder.add("analyzers", ValueType.ARRAY); - for (final String analyzer : analyzers) { - builder.add(analyzer); - } - builder.close(); - } - final Boolean includeAllFields = fieldLink.getIncludeAllFields(); - if (includeAllFields != null) { - builder.add("includeAllFields", includeAllFields); - } - final Boolean trackListPositions = fieldLink.getTrackListPositions(); - if (trackListPositions != null) { - builder.add("trackListPositions", trackListPositions); - } - final StoreValuesType storeValues = fieldLink.getStoreValues(); - if (storeValues != null) { - builder.add("storeValues", storeValues.name().toLowerCase(Locale.ENGLISH)); - } - serializeFieldLinks(builder, fieldLink.getFields()); - builder.close(); - } - builder.close(); - } - } - - public static final VPackSerializer CONSOLIDATE_TYPE = (builder, attribute, value, context) -> builder.add(attribute, value.toString().toLowerCase(Locale.ENGLISH)); - - public static final VPackSerializer COLLECTION_VALIDATION = (builder, attribute, value, context) -> { - VPackParser parser = new VPackParser.Builder().build(); - VPackSlice rule = value.getRule() != null ? parser.fromJson(value.getRule(), true) : null; - final Map doc = new HashMap<>(); - doc.put("message", value.getMessage()); - doc.put("level", value.getLevel() != null ? value.getLevel().getValue() : null); - doc.put("rule", rule); - context.serialize(builder, attribute, doc); - }; - - public static final VPackSerializer ZKD_FIELD_VALUE_TYPES = - (builder, attribute, value, context) -> builder.add(attribute, value.name().toLowerCase(Locale.ENGLISH)); - -} diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java deleted file mode 100644 index e01e22bc2..000000000 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream; - -import com.arangodb.ArangoDBException; -import com.arangodb.internal.net.ArangoDBRedirectException; -import com.arangodb.internal.net.HostDescription; -import com.arangodb.internal.net.HostHandle; -import com.arangodb.internal.net.HostHandler; -import com.arangodb.internal.util.HostUtils; -import com.arangodb.internal.velocystream.internal.AuthenticationRequest; -import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; -import com.arangodb.internal.velocystream.internal.Message; -import com.arangodb.internal.velocystream.internal.VstConnectionSync; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.velocypack.exception.VPackParserException; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.SSLContext; - -/** - * @author Mark Vollmary - */ -public class VstCommunicationSync extends VstCommunication { - - private static final Logger LOGGER = LoggerFactory.getLogger(VstCommunicationSync.class); - - public static class Builder { - - private final HostHandler hostHandler; - private Integer timeout; - private Long connectionTtl; - private String user; - private String password; - private String jwt; - private Boolean useSsl; - private SSLContext sslContext; - private Integer chunksize; - private Integer maxConnections; - - public Builder(final HostHandler hostHandler) { - super(); - this.hostHandler = hostHandler; - } - - public Builder(final Builder builder) { - this(builder.hostHandler); - timeout(builder.timeout).user(builder.user).password(builder.password).jwt(builder.jwt) - .useSsl(builder.useSsl).sslContext(builder.sslContext).chunksize(builder.chunksize) - .maxConnections(builder.maxConnections); - } - - public Builder timeout(final Integer timeout) { - this.timeout = timeout; - return this; - } - - public Builder user(final String user) { - this.user = user; - return this; - } - - public Builder password(final String password) { - this.password = password; - return this; - } - - public Builder jwt(final String jwt) { - this.jwt = jwt; - return this; - } - - public Builder useSsl(final Boolean useSsl) { - this.useSsl = useSsl; - return this; - } - - public Builder sslContext(final SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - - public Builder chunksize(final Integer chunksize) { - this.chunksize = chunksize; - return this; - } - - public Builder maxConnections(final Integer maxConnections) { - this.maxConnections = maxConnections; - return this; - } - - public Builder connectionTtl(final Long connectionTtl) { - this.connectionTtl = connectionTtl; - return this; - } - - public VstCommunication build(final ArangoSerialization util) { - return new VstCommunicationSync(hostHandler, timeout, user, password, jwt, useSsl, sslContext, util, chunksize, - maxConnections, connectionTtl); - } - - } - - protected VstCommunicationSync(final HostHandler hostHandler, final Integer timeout, final String user, - final String password, final String jwt, final Boolean useSsl, - final SSLContext sslContext, final ArangoSerialization util, - final Integer chunksize, final Integer maxConnections, final Long ttl) { - super(timeout, user, password, jwt, useSsl, sslContext, util, chunksize, hostHandler); - } - - @Override - protected Response execute(final Request request, final VstConnectionSync connection) throws ArangoDBException { - return execute(request, connection, 0); - } - - @Override - protected Response execute(final Request request, final VstConnectionSync connection, final int attemptCount) throws ArangoDBException { - try { - final Message requestMessage = createMessage(request); - final Message responseMessage = send(requestMessage, connection); - final Response response = createResponse(responseMessage); - checkError(response); - return response; - } catch (final VPackParserException e) { - throw new ArangoDBException(e); - } catch (final ArangoDBRedirectException e) { - if (attemptCount >= 3) { - throw e; - } - final String location = e.getLocation(); - final HostDescription redirectHost = HostUtils.createFromLocation(location); - hostHandler.failIfNotMatch(redirectHost, e); - return execute(request, new HostHandle().setHost(redirectHost), attemptCount + 1); - } - } - - private Message send(final Message message, final VstConnectionSync connection) throws ArangoDBException { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Send Message (id=%s, head=%s, body=%s)", message.getId(), message.getHead(), - message.getBody() != null ? message.getBody() : "{}")); - } - return connection.write(message, buildChunks(message)); - } - - @Override - protected void authenticate(final VstConnectionSync connection) { - Request authRequest; - if (jwt != null) { - authRequest = new JwtAuthenticationRequest(jwt, ENCRYPTION_JWT); - } else { - authRequest = new AuthenticationRequest(user, password != null ? password : "", ENCRYPTION_PLAIN); - } - final Response response = execute(authRequest, connection); - checkError(response); - } - -} diff --git a/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java b/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java deleted file mode 100644 index df88bcc25..000000000 --- a/src/main/java/com/arangodb/internal/velocystream/VstConnectionFactorySync.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream; - -import com.arangodb.internal.net.Connection; -import com.arangodb.internal.net.ConnectionFactory; -import com.arangodb.internal.net.HostDescription; -import com.arangodb.internal.velocystream.internal.MessageStore; -import com.arangodb.internal.velocystream.internal.VstConnectionSync; - -import javax.net.ssl.SSLContext; - -/** - * @author Mark Vollmary - */ -public class VstConnectionFactorySync implements ConnectionFactory { - - private final VstConnectionSync.Builder builder; - - public VstConnectionFactorySync(final HostDescription host, final Integer timeout, final Long connectionTtl, - final Integer keepAliveInterval, final Boolean useSsl, final SSLContext sslContext) { - super(); - builder = new VstConnectionSync.Builder().timeout(timeout).ttl(connectionTtl) - .keepAliveInterval(keepAliveInterval).useSsl(useSsl) - .sslContext(sslContext); - } - - @Override - public Connection create(final HostDescription host) { - return builder.messageStore(new MessageStore()).host(host).build(); - } - -} diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java deleted file mode 100644 index 1716b4cf5..000000000 --- a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnectionSync.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream.internal; - -import com.arangodb.ArangoDBException; -import com.arangodb.internal.net.HostDescription; - -import javax.net.ssl.SSLContext; -import java.util.Collection; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; - -/** - * @author Mark Vollmary - */ -public class VstConnectionSync extends VstConnection { - - public static class Builder { - - private HostDescription host; - private MessageStore messageStore; - private Integer timeout; - private Long ttl; - private Integer keepAliveInterval; - private Boolean useSsl; - private SSLContext sslContext; - - public Builder host(final HostDescription host) { - this.host = host; - return this; - } - - public Builder messageStore(final MessageStore messageStore) { - this.messageStore = messageStore; - return this; - } - - public Builder timeout(final Integer timeout) { - this.timeout = timeout; - return this; - } - - public Builder useSsl(final Boolean useSsl) { - this.useSsl = useSsl; - return this; - } - - public Builder sslContext(final SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - - public Builder ttl(final Long ttl) { - this.ttl = ttl; - return this; - } - - public Builder keepAliveInterval(final Integer keepAliveInterval) { - this.keepAliveInterval = keepAliveInterval; - return this; - } - - public VstConnectionSync build() { - return new VstConnectionSync(host, timeout, ttl, keepAliveInterval, - useSsl, sslContext, messageStore); - } - } - - private VstConnectionSync(final HostDescription host, final Integer timeout, final Long ttl, final Integer keepAliveInterval, - final Boolean useSsl, final SSLContext sslContext, final MessageStore messageStore) { - super(host, timeout, ttl, keepAliveInterval, useSsl, sslContext, messageStore); - } - - @Override - public Message write(final Message message, final Collection chunks) throws ArangoDBException { - final FutureTask task = new FutureTask<>(() -> messageStore.get(message.getId())); - messageStore.storeMessage(message.getId(), task); - super.writeIntern(message, chunks); - try { - return timeout == null || timeout == 0L ? task.get() : task.get(timeout, TimeUnit.MILLISECONDS); - } catch (final Exception e) { - throw new ArangoDBException(e); - } - } - - @Override - protected void doKeepAlive() { - sendKeepAlive(); - } - -} diff --git a/src/main/java/com/arangodb/mapping/ArangoJack.java b/src/main/java/com/arangodb/mapping/ArangoJack.java deleted file mode 100644 index 132a724b2..000000000 --- a/src/main/java/com/arangodb/mapping/ArangoJack.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.mapping; - -import com.arangodb.ArangoDBException; -import com.arangodb.entity.BaseDocument; -import com.arangodb.entity.BaseEdgeDocument; -import com.arangodb.internal.mapping.ArangoAnnotationIntrospector; -import com.arangodb.internal.mapping.VPackDeserializers; -import com.arangodb.internal.mapping.VPackSerializers; -import com.arangodb.jackson.dataformat.velocypack.VPackMapper; -import com.arangodb.util.ArangoSerialization; -import com.arangodb.util.ArangoSerializer; -import com.arangodb.velocypack.VPackParser; -import com.arangodb.velocypack.VPackSlice; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.module.SimpleModule; - -import java.io.IOException; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.Iterator; - -/** - * @author Mark Vollmary - */ -public class ArangoJack implements ArangoSerialization { - - public interface ConfigureFunction { - void configure(ObjectMapper mapper); - } - - private final ObjectMapper vpackMapper; - private final ObjectMapper vpackMapperNull; - private final ObjectMapper jsonMapper; - private final VPackParser vpackParser; - - private static final class ArangoModule extends SimpleModule { - @Override - public void setupModule(SetupContext context) { - super.setupModule(context); - context.insertAnnotationIntrospector(new ArangoAnnotationIntrospector()); - } - } - - static VPackMapper createDefaultMapper() { - final VPackMapper mapper = new VPackMapper(); - mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); - - final SimpleModule module = new ArangoJack.ArangoModule(); - module.addSerializer(VPackSlice.class, VPackSerializers.VPACK); - module.addSerializer(java.util.Date.class, VPackSerializers.UTIL_DATE); - module.addSerializer(java.sql.Date.class, VPackSerializers.SQL_DATE); - module.addSerializer(java.sql.Timestamp.class, VPackSerializers.SQL_TIMESTAMP); - module.addSerializer(BaseDocument.class, VPackSerializers.BASE_DOCUMENT); - module.addSerializer(BaseEdgeDocument.class, VPackSerializers.BASE_EDGE_DOCUMENT); - - module.addDeserializer(VPackSlice.class, VPackDeserializers.VPACK); - module.addDeserializer(java.util.Date.class, VPackDeserializers.UTIL_DATE); - module.addDeserializer(java.sql.Date.class, VPackDeserializers.SQL_DATE); - module.addDeserializer(java.sql.Timestamp.class, VPackDeserializers.SQL_TIMESTAMP); - module.addDeserializer(BaseDocument.class, VPackDeserializers.BASE_DOCUMENT); - module.addDeserializer(BaseEdgeDocument.class, VPackDeserializers.BASE_EDGE_DOCUMENT); - - mapper.registerModule(module); - return mapper; - } - - public ArangoJack() { - this(createDefaultMapper()); - } - - /** - * @param mapper configured VPackMapper to use. A defensive copy is created and used. - */ - public ArangoJack(final VPackMapper mapper) { - super(); - vpackMapper = mapper.copy().setSerializationInclusion(Include.NON_NULL); - vpackMapperNull = mapper.copy().setSerializationInclusion(Include.ALWAYS); - jsonMapper = new ObjectMapper().setSerializationInclusion(Include.NON_NULL); - vpackParser = new VPackParser.Builder().build(); - } - - public void configure(final ArangoJack.ConfigureFunction f) { - f.configure(vpackMapper); - f.configure(vpackMapperNull); - f.configure(jsonMapper); - } - - @Override - public VPackSlice serialize(final Object entity) throws ArangoDBException { - return serialize(entity, new ArangoSerializer.Options()); - } - - @SuppressWarnings("unchecked") - @Override - public VPackSlice serialize(final Object entity, final Options options) throws ArangoDBException { - if (options.getType() == null) { - options.type(entity.getClass()); - } - try { - final VPackSlice vpack; - final Class type = entity.getClass(); - final boolean serializeNullValues = options.isSerializeNullValues(); - if (String.class.isAssignableFrom(type)) { - vpack = vpackParser.fromJson((String) entity, serializeNullValues); - } else if (options.isStringAsJson() && Iterable.class.isAssignableFrom(type)) { - final Iterator iterator = Iterable.class.cast(entity).iterator(); - if (iterator.hasNext() && String.class.isAssignableFrom(iterator.next().getClass())) { - vpack = vpackParser.fromJson((Iterable) entity, serializeNullValues); - } else { - final ObjectMapper vp = serializeNullValues ? vpackMapperNull : vpackMapper; - vpack = new VPackSlice(vp.writeValueAsBytes(entity)); - } - } else { - final ObjectMapper vp = serializeNullValues ? vpackMapperNull : vpackMapper; - vpack = new VPackSlice(vp.writeValueAsBytes(entity)); - } - return vpack; - } catch (final JsonProcessingException e) { - throw new ArangoDBException(e); - } - } - - @SuppressWarnings("unchecked") - @Override - public T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException { - try { - final T doc; - if (type == String.class && !vpack.isString() && !vpack.isNull()) { - final JsonNode node = vpackMapper.readTree( - Arrays.copyOfRange(vpack.getBuffer(), vpack.getStart(), vpack.getStart() + vpack.getByteSize())); - doc = (T) jsonMapper.writeValueAsString(node); - } else { - doc = vpackMapper.readValue(vpack.getBuffer(), vpack.getStart(), vpack.getStart() + vpack.getByteSize(), - (Class) type); - } - return doc; - } catch (final IOException e) { - throw new ArangoDBException(e); - } - } - -} diff --git a/src/main/java/com/arangodb/model/CollectionCreateOptions.java b/src/main/java/com/arangodb/model/CollectionCreateOptions.java deleted file mode 100644 index 8ef7eff6b..000000000 --- a/src/main/java/com/arangodb/model/CollectionCreateOptions.java +++ /dev/null @@ -1,417 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -import com.arangodb.entity.CollectionType; -import com.arangodb.entity.KeyOptions; -import com.arangodb.entity.KeyType; -import com.arangodb.entity.MinReplicationFactor; -import com.arangodb.entity.ReplicationFactor; - -/** - * @author Mark Vollmary - * @see API - * Documentation - */ -public class CollectionCreateOptions { - - private String name; - private Long journalSize; - private final ReplicationFactor replicationFactor; - private final MinReplicationFactor minReplicationFactor; - private Integer writeConcern; - private KeyOptions keyOptions; - private Boolean waitForSync; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Boolean doCompact; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Boolean isVolatile; - private String[] shardKeys; - private Integer numberOfShards; - private Boolean isSystem; - private CollectionType type; - /** - * @deprecated MMFiles only - */ - @Deprecated - private Integer indexBuckets; - private String distributeShardsLike; - - private String shardingStrategy; // cluster option - private String smartJoinAttribute; // enterprise option - - private CollectionSchema schema; - - public CollectionCreateOptions() { - super(); - replicationFactor = new ReplicationFactor(); - minReplicationFactor = new MinReplicationFactor(); - } - - protected String getName() { - return name; - } - - /** - * @param name The name of the collection - * @return options - */ - protected CollectionCreateOptions name(final String name) { - this.name = name; - return this; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public Long getJournalSize() { - return journalSize; - } - - /** - * @param journalSize The maximal size of a journal or datafile in bytes. The value must be at least 1048576 (1 MiB). - * @return options - * @deprecated MMFiles only - */ - @Deprecated - public CollectionCreateOptions journalSize(final Long journalSize) { - this.journalSize = journalSize; - return this; - } - - public Integer getReplicationFactor() { - return replicationFactor.getReplicationFactor(); - } - - /** - * @deprecated use {@link #getWriteConcern()} instead - */ - @Deprecated - public Integer getMinReplicationFactor() { - return minReplicationFactor.getMinReplicationFactor(); - } - - /** - * @param replicationFactor (The default is 1): in a cluster, this attribute determines how many copies of each shard are kept on - * different DBServers. The value 1 means that only one copy (no synchronous replication) is kept. A - * value of k means that k-1 replicas are kept. Any two copies reside on different DBServers. Replication - * between them is synchronous, that is, every write operation to the "leader" copy will be replicated to - * all "follower" replicas, before the write operation is reported successful. If a server fails, this is - * detected automatically and one of the servers holding copies take over, usually without an error being - * reported. - * @return options - */ - public CollectionCreateOptions replicationFactor(final Integer replicationFactor) { - this.replicationFactor.setReplicationFactor(replicationFactor); - return this; - } - - /** - * @param minReplicationFactor (optional, default is 1): in a cluster, this attribute determines how many desired copies of each - * shard are kept on different DBServers. The value 1 means that only one copy (no synchronous - * replication) is kept. A value of k means that desired k-1 replicas are kept. If in a failover scenario - * a shard of a collection has less than minReplicationFactor many insync followers it will go into - * "read-only" mode and will reject writes until enough followers are insync again. In more detail: - * Having `minReplicationFactor == 1` means as soon as a "master-copy" is available of the data writes - * are allowed. Having `minReplicationFactor > 1` requires additional insync copies on follower servers - * to allow writes. - * @return options - * @deprecated use {@link #writeConcern(Integer)} instead - */ - @Deprecated - public CollectionCreateOptions minReplicationFactor(final Integer minReplicationFactor) { - this.minReplicationFactor.setMinReplicationFactor(minReplicationFactor); - return this; - } - - public Integer getWriteConcern() { - return writeConcern; - } - - /** - * @param writeConcern write concern for this collection (default: 1). - * It determines how many copies of each shard are required to be in sync on the different - * DB-Servers. If there are less then these many copies in the cluster a shard will refuse to - * write. Writes to shards with enough up-to-date copies will succeed at the same time however. - * The value of writeConcern can not be larger than replicationFactor. (cluster only) - * @return options - */ - public CollectionCreateOptions writeConcern(final Integer writeConcern) { - this.writeConcern = writeConcern; - return this; - } - - public Boolean getSatellite() { - return replicationFactor.getSatellite(); - } - - /** - * @param satellite If the true the collection is created as a satellite collection. In this case - * {@link #replicationFactor(Integer)} is ignored. - * @return options - */ - public CollectionCreateOptions satellite(final Boolean satellite) { - this.replicationFactor.setSatellite(satellite); - return this; - } - - public KeyOptions getKeyOptions() { - return keyOptions; - } - - /** - * @param allowUserKeys if set to true, then it is allowed to supply own key values in the _key attribute of a document. If - * set to false, then the key generator will solely be responsible for generating keys and supplying own - * key values in the _key attribute of documents is considered an error. - * @param type specifies the type of the key generator. The currently available generators are traditional and - * autoincrement. - * @param increment increment value for autoincrement key generator. Not used for other key generator types. - * @param offset Initial offset value for autoincrement key generator. Not used for other key generator types. - * @return options - */ - public CollectionCreateOptions keyOptions( - final Boolean allowUserKeys, - final KeyType type, - final Integer increment, - final Integer offset) { - this.keyOptions = new KeyOptions(allowUserKeys, type, increment, offset); - return this; - } - - public Boolean getWaitForSync() { - return waitForSync; - } - - /** - * @param waitForSync If true then the data is synchronized to disk before returning from a document create, update, replace - * or removal operation. (default: false) - * @return options - */ - public CollectionCreateOptions waitForSync(final Boolean waitForSync) { - this.waitForSync = waitForSync; - return this; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public Boolean getDoCompact() { - return doCompact; - } - - /** - * @param doCompact whether or not the collection will be compacted (default is true) - * @return options - * @deprecated MMFiles only - */ - @Deprecated - public CollectionCreateOptions doCompact(final Boolean doCompact) { - this.doCompact = doCompact; - return this; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public Boolean getIsVolatile() { - return isVolatile; - } - - /** - * @param isVolatile If true then the collection data is kept in-memory only and not made persistent. Unloading the - * collection will cause the collection data to be discarded. Stopping or re-starting the server will - * also cause full loss of data in the collection. Setting this option will make the resulting collection - * be slightly faster than regular collections because ArangoDB does not enforce any synchronization to - * disk and does not calculate any CRC checksums for datafiles (as there are no datafiles). This option - * should therefore be used for cache-type collections only, and not for data that cannot be re-created - * otherwise. (The default is false) - * @return options - * @deprecated MMFiles only - */ - @Deprecated - public CollectionCreateOptions isVolatile(final Boolean isVolatile) { - this.isVolatile = isVolatile; - return this; - } - - public String[] getShardKeys() { - return shardKeys; - } - - /** - * @param shardKeys (The default is [ "_key" ]): in a cluster, this attribute determines which document attributes are - * used to determine the target shard for documents. Documents are sent to shards based on the values of - * their shard key attributes. The values of all shard key attributes in a document are hashed, and the - * hash value is used to determine the target shard. Note: Values of shard key attributes cannot be - * changed once set. This option is meaningless in a single server setup. - * @return options - */ - public CollectionCreateOptions shardKeys(final String... shardKeys) { - this.shardKeys = shardKeys; - return this; - } - - /** - * @param smartJoinAttribute - * @return options - */ - public CollectionCreateOptions smartJoinAttribute(final String smartJoinAttribute) { - this.smartJoinAttribute = smartJoinAttribute; - return this; - } - - public String getSmartJoinAttribute() { - return smartJoinAttribute; - } - - /** - * @param shardingStrategy - * @return options - */ - public CollectionCreateOptions shardingStrategy(final String shardingStrategy) { - this.shardingStrategy = shardingStrategy; - return this; - } - - public String getShardingStrategy() { - return shardingStrategy; - } - - /** - * @param numberOfShards (The default is 1): in a cluster, this value determines the number of shards to create for the - * collection. In a single server setup, this option is meaningless. - * @return options - */ - public CollectionCreateOptions numberOfShards(final Integer numberOfShards) { - this.numberOfShards = numberOfShards; - return this; - } - - public Integer getNumberOfShards() { - return numberOfShards; - } - - public Boolean getIsSystem() { - return isSystem; - } - - /** - * @param isSystem If true, create a system collection. In this case collection-name should start with an underscore. End - * users should normally create non-system collections only. API implementors may be required to create - * system collections in very special occasions, but normally a regular collection will do. (The default - * is false) - * @return options - */ - public CollectionCreateOptions isSystem(final Boolean isSystem) { - this.isSystem = isSystem; - return this; - } - - public CollectionType getType() { - return type; - } - - /** - * @param type (The default is {@link CollectionType#DOCUMENT}): the type of the collection to create. - * @return options - */ - public CollectionCreateOptions type(final CollectionType type) { - this.type = type; - return this; - } - - /** - * @deprecated MMFiles only - */ - @Deprecated - public Integer getIndexBuckets() { - return indexBuckets; - } - - /** - * @param indexBuckets The number of buckets into which indexes using a hash table are split. The default is 16 and this - * number has to be a power of 2 and less than or equal to 1024. For very large collections one should - * increase this to avoid long pauses when the hash table has to be initially built or resized, since - * buckets are resized individually and can be initially built in parallel. For example, 64 might be a - * sensible value for a collection with 100 000 000 documents. Currently, only the edge index respects - * this value, but other index types might follow in future ArangoDB versions. Changes (see below) are - * applied when the collection is loaded the next time. - * @return options - * @deprecated MMFiles only - */ - @Deprecated - public CollectionCreateOptions indexBuckets(final Integer indexBuckets) { - this.indexBuckets = indexBuckets; - return this; - } - - public String getDistributeShardsLike() { - return distributeShardsLike; - } - - /** - * @param distributeShardsLike (The default is ""): in an enterprise cluster, this attribute binds the specifics of sharding for the - * newly created collection to follow that of a specified existing collection. Note: Using this parameter - * has consequences for the prototype collection. It can no longer be dropped, before sharding imitating - * collections are dropped. Equally, backups and restores of imitating collections alone will generate - * warnings, which can be overridden, about missing sharding prototype. - * @return options - */ - public CollectionCreateOptions distributeShardsLike(final String distributeShardsLike) { - this.distributeShardsLike = distributeShardsLike; - return this; - } - - public CollectionSchema getSchema() { - return schema; - } - - /** - * @param schema - * object that specifies the collection level schema for documents - * @return options - * @since ArangoDB 3.7 - */ - public CollectionCreateOptions schema(final CollectionSchema schema) { - this.schema = schema; - return this; - } - - /** - * @since ArangoDB 3.7 - * @deprecated Use {@link #schema(CollectionSchema)} instead. - */ - @Deprecated - public CollectionCreateOptions setSchema(final CollectionSchema schema) { - this.schema = schema; - return this; - } - -} diff --git a/src/main/java/com/arangodb/model/TraversalOptions.java b/src/main/java/com/arangodb/model/TraversalOptions.java deleted file mode 100644 index 1d7abada7..000000000 --- a/src/main/java/com/arangodb/model/TraversalOptions.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model; - -/** - * @author Mark Vollmary - * @see API Documentation - */ -@Deprecated -public class TraversalOptions { - - public enum Direction { - outbound, inbound, any - } - - public enum ItemOrder { - forward, backward - } - - public enum Strategy { - depthfirst, breadthfirst - } - - public enum UniquenessType { - none, global, path - } - - public enum Order { - preorder, postorder, preorder_expander - } - - private String sort; - private Direction direction; - private Integer minDepth; - private String startVertex; - private String visitor; - private ItemOrder itemOrder; - private Strategy strategy; - private String filter; - private String init; - private Integer maxIterations; - private Integer maxDepth; - private Uniqueness uniqueness; - private Order order; - private String graphName; - private String expander; - private String edgeCollection; - - public String getSort() { - return sort; - } - - /** - * @param sort JavaScript code of a custom comparison function for the edges. The signature of this function is (l, - * r) -> integer (where l and r are edges) and must return -1 if l is smaller than, +1 if l is greater - * than, and 0 if l and r are equal. The reason for this is the following: The order of edges returned - * for a certain vertex is undefined. This is because there is no natural order of edges for a vertex - * with multiple connected edges. To explicitly define the order in which edges on the vertex are - * followed, you can specify an edge comparator function with this attribute. Note that the value here - * has to be a string to conform to the JSON standard, which in turn is parsed as function body on the - * server side. Furthermore note that this attribute is only used for the standard expanders. If you use - * your custom expander you have to do the sorting yourself within the expander code. - * @return options - */ - public TraversalOptions sort(final String sort) { - this.sort = sort; - return this; - } - - public Direction getDirection() { - return direction; - } - - /** - * @param direction direction for traversal - *

    - * if set, must be either "outbound", "inbound", or "any" - *

    - * if not set, the expander attribute must be specified - * @return options - */ - public TraversalOptions direction(final Direction direction) { - this.direction = direction; - return this; - } - - public Integer getMinDepth() { - return minDepth; - } - - /** - * @param minDepth ANDed with any existing filters): visits only nodes in at least the given depth - * @return options - */ - public TraversalOptions minDepth(final Integer minDepth) { - this.minDepth = minDepth; - return this; - } - - public String getStartVertex() { - return startVertex; - } - - /** - * @param startVertex The id of the startVertex, e.g. "users/foo". - * @return options - */ - public TraversalOptions startVertex(final String startVertex) { - this.startVertex = startVertex; - return this; - } - - public String getVisitor() { - return visitor; - } - - /** - * @param visitor JavaScript code of custom visitor function function signature: (config, result, vertex, path, - * connected) -> void The visitor function can do anything, but its return value is ignored. To populate - * a result, use the result variable by reference. Note that the connected argument is only populated - * when the order attribute is set to "preorder-expander". - * @return options - */ - public TraversalOptions visitor(final String visitor) { - this.visitor = visitor; - return this; - } - - public ItemOrder getItemOrder() { - return itemOrder; - } - - /** - * @param itemOrder The item iteration order can be "forward" or "backward" - * @return options - */ - public TraversalOptions itemOrder(final ItemOrder itemOrder) { - this.itemOrder = itemOrder; - return this; - } - - public Strategy getStrategy() { - return strategy; - } - - /** - * @param strategy The traversal strategy can be "depthfirst" or "breadthfirst" - * @return options - */ - public TraversalOptions strategy(final Strategy strategy) { - this.strategy = strategy; - return this; - } - - public String getFilter() { - return filter; - } - - /** - * @param filter default is to include all nodes: body (JavaScript code) of custom filter function function signature: - * (config, vertex, path) -> mixed can return four different string values: - *

    - * "exclude" -> this vertex will not be visited. - *

    - * "prune" -> the edges of this vertex will not be followed. - *

    - * "" or undefined -> visit the vertex and follow it's edges. - *

    - * Array -> containing any combination of the above. - *

    - * If there is at least one "exclude" or "prune" respectivly is contained, it's effect will occur. - * @return options - */ - public TraversalOptions filter(final String filter) { - this.filter = filter; - return this; - } - - public String getInit() { - return init; - } - - /** - * @param init JavaScript code of custom result initialization function function signature: (config, result) -> void - * initialize any values in result with what is required - * @return options - */ - public TraversalOptions init(final String init) { - this.init = init; - return this; - } - - public Integer getMaxIterations() { - return maxIterations; - } - - /** - * @param maxIterations Maximum number of iterations in each traversal. This number can be set to prevent endless loops in - * traversal of cyclic graphs. When a traversal performs as many iterations as the maxIterations value, - * the traversal will abort with an error. If maxIterations is not set, a server-defined value may be - * used. - * @return options - */ - public TraversalOptions maxIterations(final Integer maxIterations) { - this.maxIterations = maxIterations; - return this; - } - - public Integer getMaxDepth() { - return maxDepth; - } - - /** - * @param maxDepth ANDed with any existing filters visits only nodes in at most the given depth. - * @return options - */ - public TraversalOptions maxDepth(final Integer maxDepth) { - this.maxDepth = maxDepth; - return this; - } - - public UniquenessType getVerticesUniqueness() { - return uniqueness != null ? uniqueness.vertices : null; - } - - /** - * @param vertices Specifies uniqueness for vertices can be "none", "global" or "path" - * @return options - */ - public TraversalOptions verticesUniqueness(final UniquenessType vertices) { - getUniqueness().setVertices(vertices); - return this; - } - - public UniquenessType getEdgesUniqueness() { - return uniqueness != null ? uniqueness.edges : null; - } - - /** - * @param edges Specifies uniqueness for edges can be "none", "global" or "path" - * @return options - */ - public TraversalOptions edgesUniqueness(final UniquenessType edges) { - getUniqueness().setEdges(edges); - return this; - } - - public Order getOrder() { - return order; - } - - /** - * @param order The traversal order can be "preorder", "postorder" or "preorder-expander" - * @return options - */ - public TraversalOptions order(final Order order) { - this.order = order; - return this; - } - - public String getGraphName() { - return graphName; - } - - /** - * @param graphName The name of the graph that contains the edges. Either edgeCollection or graphName has to be given. In - * case both values are set the graphName is prefered. - * @return options - */ - public TraversalOptions graphName(final String graphName) { - this.graphName = graphName; - return this; - } - - public String getExpander() { - return expander; - } - - /** - * @param expander JavaScript code of custom expander function must be set if direction attribute is not set function - * signature: (config, vertex, path) -> array expander must return an array of the connections for vertex - * each connection is an object with the attributes edge and vertex - * @return options - */ - public TraversalOptions expander(final String expander) { - this.expander = expander; - return this; - } - - public String getEdgeCollection() { - return edgeCollection; - } - - /** - * @param edgeCollection The name of the collection that contains the edges. - * @return options - */ - public TraversalOptions edgeCollection(final String edgeCollection) { - this.edgeCollection = edgeCollection; - return this; - } - - public static class Uniqueness { - - private UniquenessType vertices; - private UniquenessType edges; - - public UniquenessType getVertices() { - return vertices; - } - - public void setVertices(final UniquenessType vertices) { - this.vertices = vertices; - } - - public UniquenessType getEdges() { - return edges; - } - - public void setEdges(final UniquenessType edges) { - this.edges = edges; - } - } - - private Uniqueness getUniqueness() { - if (uniqueness == null) { - uniqueness = new Uniqueness(); - uniqueness.vertices = UniquenessType.none; - uniqueness.edges = UniquenessType.none; - } - - return uniqueness; - } - -} diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java deleted file mode 100644 index 2fcfe376b..000000000 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.model.arangosearch; - -import com.arangodb.entity.ViewType; -import com.arangodb.entity.arangosearch.*; - -/** - * @author Mark Vollmary - */ -public class ArangoSearchCreateOptions { - - @SuppressWarnings("unused") - private String name; - @SuppressWarnings("unused") - private final ViewType type; - private final ArangoSearchProperties properties; - - public ArangoSearchCreateOptions() { - super(); - type = ViewType.ARANGO_SEARCH; - properties = new ArangoSearchProperties(); - } - - protected ArangoSearchCreateOptions name(final String name) { - this.name = name; - return this; - } - - /** - * @param consolidationIntervalMsec Wait at least this many milliseconds between committing index data changes and making them visible to - * queries (default: 60000, to disable use: 0). For the case where there are a lot of inserts/updates, a - * lower value, until commit, will cause the index not to account for them and memory usage would - * continue to grow. For the case where there are a few inserts/updates, a higher value will impact - * performance and waste disk space for each commit call without any added benefits. - * @return options - */ - public ArangoSearchCreateOptions consolidationIntervalMsec(final Long consolidationIntervalMsec) { - properties.setConsolidationIntervalMsec(consolidationIntervalMsec); - return this; - } - - /** - * @param commitIntervalMsec Wait at least this many milliseconds between committing view data store changes and making documents visible to - * queries (default: 1000, to disable use: 0). For the case where there are a lot of inserts/updates, a lower value, - * until commit, will cause the index not to account for them and memory usage would continue to grow. For the case - * where there are a few inserts/updates, a higher value will impact performance and waste disk space for each - * commit call without any added benefits. Background: For data retrieval ArangoSearch views follow the concept of - * “eventually-consistent”, i.e. eventually all the data in ArangoDB will be matched by corresponding query - * expressions. The concept of ArangoSearch view “commit” operation is introduced to control the upper-bound on the - * time until document addition/removals are actually reflected by corresponding query expressions. Once a “commit” - * operation is complete all documents added/removed prior to the start of the “commit” operation will be reflected - * by queries invoked in subsequent ArangoDB transactions, in-progress ArangoDB transactions will still continue to - * return a repeatable-read state. - * @return options - */ - public ArangoSearchCreateOptions commitIntervalMsec(final Long commitIntervalMsec) { - properties.setCommitIntervalMsec(commitIntervalMsec); - return this; - } - - /** - * @param cleanupIntervalStep Wait at least this many commits between removing unused files in data directory (default: 10, to - * disable use: 0). For the case where the consolidation policies merge segments often (i.e. a lot of - * commit+consolidate), a lower value will cause a lot of disk space to be wasted. For the case where the - * consolidation policies rarely merge segments (i.e. few inserts/deletes), a higher value will impact - * performance without any added benefits. - * @return options - */ - public ArangoSearchCreateOptions cleanupIntervalStep(final Long cleanupIntervalStep) { - properties.setCleanupIntervalStep(cleanupIntervalStep); - return this; - } - - /** - * @param consolidationPolicy - * @return options - */ - public ArangoSearchCreateOptions consolidationPolicy(final ConsolidationPolicy consolidationPolicy) { - properties.setConsolidationPolicy(consolidationPolicy); - return this; - } - - /** - * @param links A list of linked collections - * @return options - */ - public ArangoSearchCreateOptions link(final CollectionLink... links) { - properties.addLink(links); - return this; - } - - /** - * @param primarySorts A list of linked collections - * @return options - */ - public ArangoSearchCreateOptions primarySort(final PrimarySort... primarySorts) { - properties.addPrimarySort(primarySorts); - return this; - } - - /** - * @param primarySortCompression Defines how to compress the primary sort data - * @return options - */ - public ArangoSearchCreateOptions primarySortCompression(final ArangoSearchCompression primarySortCompression) { - properties.setPrimarySortCompression(primarySortCompression); - return this; - } - - /** - * @return options - */ - public ArangoSearchCreateOptions storedValues(final StoredValue... storedValues) { - properties.addStoredValues(storedValues); - return this; - } - -} diff --git a/src/main/java/com/arangodb/util/ArangoCursorInitializer.java b/src/main/java/com/arangodb/util/ArangoCursorInitializer.java deleted file mode 100644 index bc2da8378..000000000 --- a/src/main/java/com/arangodb/util/ArangoCursorInitializer.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2017 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -import com.arangodb.ArangoCursor; -import com.arangodb.entity.CursorEntity; -import com.arangodb.internal.ArangoCursorExecute; -import com.arangodb.internal.InternalArangoDatabase; - -/** - * @author Mark Vollmary - */ -public interface ArangoCursorInitializer { - - ArangoCursor createInstance( - final InternalArangoDatabase db, - final ArangoCursorExecute execute, - final Class type, - final CursorEntity result); - -} diff --git a/src/main/java/com/arangodb/util/ArangoDeserializer.java b/src/main/java/com/arangodb/util/ArangoDeserializer.java deleted file mode 100644 index 55601faff..000000000 --- a/src/main/java/com/arangodb/util/ArangoDeserializer.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -import com.arangodb.ArangoDBException; -import com.arangodb.velocypack.VPackSlice; - -import java.lang.reflect.Type; - -/** - * @author Mark Vollmary - */ -public interface ArangoDeserializer { - - /** - * Deserialize a given VelocyPack to an instance of a given type - * - * @param vpack The VelocyPack to deserialize - * @param type The target type to deserialize to. Use String for raw JSON. - * @return The deserialized VelocyPack - * @throws ArangoDBException - */ - T deserialize(final VPackSlice vpack, final Type type) throws ArangoDBException; - -} diff --git a/src/main/java/com/arangodb/util/ArangoSerializer.java b/src/main/java/com/arangodb/util/ArangoSerializer.java deleted file mode 100644 index ee327d234..000000000 --- a/src/main/java/com/arangodb/util/ArangoSerializer.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -import com.arangodb.ArangoDBException; -import com.arangodb.velocypack.VPackSlice; - -import java.lang.reflect.Type; -import java.util.Collections; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public interface ArangoSerializer { - - class Options { - private Type type; - private boolean serializeNullValues; - private Map additionalFields; - private boolean stringAsJson; - - public Options() { - super(); - serializeNullValues = false; - stringAsJson = false; - additionalFields = Collections.emptyMap(); - } - - /** - * @param type The source type of the Object. - * @return options - */ - public Options type(final Type type) { - this.type = type; - return this; - } - - /** - * @param serializeNullValues Whether or not null values should be excluded from serialization. - * @return options - */ - public Options serializeNullValues(final boolean serializeNullValues) { - this.serializeNullValues = serializeNullValues; - return this; - } - - /** - * @param additionalFields Additional Key/Value pairs to include in the created VelocyPack. - * @return options - */ - public Options additionalFields(final Map additionalFields) { - this.additionalFields = additionalFields; - return this; - } - - /** - * @param stringAsJson Wheter or not String should be interpreted as json - * @return options - */ - public Options stringAsJson(final boolean stringAsJson) { - this.stringAsJson = stringAsJson; - return this; - } - - public Type getType() { - return type; - } - - public boolean isSerializeNullValues() { - return serializeNullValues; - } - - public Map getAdditionalFields() { - return additionalFields; - } - - public boolean isStringAsJson() { - return stringAsJson; - } - - } - - /** - * Serialize a given Object to VelocyPack - * - * @param entity The Object to serialize. If it is from type String, it will be handled as a JSON. - * @return The serialized VelocyPack - * @throws ArangoDBException - */ - VPackSlice serialize(final Object entity) throws ArangoDBException; - - /** - * Serialize a given Object to VelocyPack - * - * @param entity The Object to serialize. If it is from type String, it will be handled as a JSON. - * @param options Additional options - * @return the serialized VelocyPack - * @throws ArangoDBException - */ - VPackSlice serialize(final Object entity, final Options options) throws ArangoDBException; - -} diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/http-reflect-config.json b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/http-reflect-config.json deleted file mode 100644 index 869cd250d..000000000 --- a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/http-reflect-config.json +++ /dev/null @@ -1,29 +0,0 @@ -[ - { - "name": "org.apache.commons.logging.impl.LogFactoryImpl", - "allDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true, - "allPublicClasses": true - }, - { - "name": "org.apache.commons.logging.LogFactory", - "allDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true, - "allPublicClasses": true - }, - { - "name": "org.apache.commons.logging.impl.SimpleLog", - "allDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true, - "allPublicClasses": true - } -] \ No newline at end of file diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties deleted file mode 100644 index 20f45594f..000000000 --- a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/native-image.properties +++ /dev/null @@ -1,3 +0,0 @@ -Args= -H:ReflectionConfigurationResources=${.}/reflect-config.json,${.}/http-reflect-config.json \ - --allow-incomplete-classpath \ - --initialize-at-run-time=org.apache.http.impl.auth.NTLMEngineImpl,org.apache.http.conn.ssl.SSLConnectionSocketFactory diff --git a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json b/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json deleted file mode 100644 index eac1dd6cd..000000000 --- a/src/main/resources/META-INF/native-image/com.arangodb/arangodb-java-driver/reflect-config.json +++ /dev/null @@ -1,1492 +0,0 @@ -[ - { - "name": "com.arangodb.entity.DocumentCreateEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzerProperties", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzerProperties", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.CursorEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.TraversalEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.IndexEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.VertexEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.AqlExecutionExplainEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.AqlParseEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.EdgeDefinition", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.CollectionEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.CursorEntity$Stats", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.MultiDocumentEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzerProperties", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionVariable", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.StopwordsAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.CollectionPropertiesEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.EdgeUpdateEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.QueryCachePropertiesEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.DocumentUpdateEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.GraphEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.GeoJSONAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.AqlFunctionEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.DatabaseEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.EdgeEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.ViewEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.EdgeNgram", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionNode", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.BaseDocument", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.TransactionEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.ArangoDBEngine", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.UserEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.LogEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.ErrorEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzerProperties", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.CursorEntity$Warning", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionStats", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.GeoAnalyzerOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.AqlParseEntity$AstNode", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.ArangoSearchProperties", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.ShardEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionCollection", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.PipelineAnalyzerProperties", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzerProperties", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.DocumentDeleteEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.EdgeDefinition$Options", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.AnalyzerEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.ArangoDBVersion", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.AQLAnalyzerProperties", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.SegmentationAnalyzerProperties", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.BaseEdgeDocument", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.ConsolidationPolicy", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.VertexUpdateEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.NormAnalyzerProperties", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.KeyOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionPlan", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.LogLevelEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.ReplicationFactor", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.DelimiterAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.DocumentEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.NGramAnalyzerProperties", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzerProperties", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.IdentityAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.StreamTransactionEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.GeoPointAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.LogEntriesEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.PathEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.QueryEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.DocumentImportEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.PipelineAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzerProperties", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.MinReplicationFactor", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.StemAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.QueryTrackingPropertiesEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.CollectionRevisionEntity", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.CursorEntity$Extras", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.LogEntriesEntity$Message", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "java.lang.Object", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.CollationAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.TextAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.arangosearch.analyzer.SearchAnalyzer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.entity.AqlExecutionExplainEntity$ExecutionExpression", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.GeoIndexOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.TtlIndexOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.DocumentReadOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.AqlQueryOptions$Optimizer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.DBCreateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.VertexCreateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.AqlFunctionDeleteOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.arangosearch.AnalyzerDeleteOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.AqlQueryOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.FulltextIndexOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.UserUpdateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.StreamTransactionOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.TraversalOptions$Uniqueness", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.DocumentReplaceOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.DatabaseUsersOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.ViewRenameOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.CollectionCreateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.AqlQueryExplainOptions$Options", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.ViewCreateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.VertexCollectionCreateOptions$Options", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.AqlQueryParseOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.UserAccessOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.HashIndexOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.arangosearch.ArangoSearchPropertiesOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.EdgeUpdateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.VertexCollectionCreateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.arangosearch.ArangoSearchCreateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.VertexDeleteOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.EdgeCreateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.GraphCreateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.CollectionsReadOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.TransactionOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.CollectionTruncateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.PersistentIndexOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.SkiplistIndexOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.ZKDIndexOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.CollectionSchema", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.DocumentImportOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.DocumentDeleteOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.AqlQueryOptions$Options", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.EdgeReplaceOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.VertexReplaceOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.DocumentUpdateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.GraphDocumentReadOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.VertexUpdateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.TransactionCollectionOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.LogOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.UserCreateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.CollectionPropertiesOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.DatabaseOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.DocumentCreateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.TraversalOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.GraphCreateOptions$SmartOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.CollectionCountOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.EdgeDeleteOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.IndexOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.CollectionRenameOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.DocumentExistsOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.AqlFunctionGetOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "java.lang.Object", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.AqlFunctionCreateOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.AqlQueryExplainOptions$Optimizer", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.model.AqlQueryExplainOptions", - "allDeclaredFields": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - } -] diff --git a/src/test/java/com/arangodb/ArangoCursorTest.java b/src/test/java/com/arangodb/ArangoCursorTest.java deleted file mode 100644 index 2872451bf..000000000 --- a/src/test/java/com/arangodb/ArangoCursorTest.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.model.AqlQueryOptions; -import com.arangodb.velocypack.VPackSlice; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.*; -import java.util.concurrent.atomic.AtomicLong; -import java.util.stream.Collectors; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoCursorTest extends BaseJunit5 { - - @BeforeAll - static void init() { - initDB(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void first(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final VPackSlice first = cursor.first(); - assertThat(first).isNotNull(); - assertThat(first.isInteger()).isTrue(); - assertThat(first.getAsLong()).isZero(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void firstStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final Optional first = cursor.stream().findFirst(); - assertThat(first.isPresent()).isTrue(); - assertThat(first.get().isInteger()).isTrue(); - assertThat(first.get().getAsLong()).isZero(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void next(ArangoDatabase db) { - - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", new AqlQueryOptions().batchSize(5), VPackSlice.class); - - while (cursor.hasNext()) { - cursor.next(); - } - - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterCount(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final long count = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).count(); - assertThat(count).isEqualTo(50L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterCountStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final long count = cursor.stream().map(VPackSlice::getAsLong).filter(t -> t < 50).count(); - assertThat(count).isEqualTo(50L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapMapFilterCount(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final long count = cursor.map(VPackSlice::getAsLong).map(t -> t * 10).filter(t -> t < 500).count(); - assertThat(count).isEqualTo(50L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapMapFilterFilterCount(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final long count = cursor.map(VPackSlice::getAsLong).map(t -> t * 10).filter(t -> t < 500).filter(t -> t < 250).count(); - assertThat(count).isEqualTo(25L); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterNext(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final long count = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).iterator().next(); - assertThat(count).isZero(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterFirst(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final long count = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).first(); - assertThat(count).isZero(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterCollectIntoList(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final List target = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).collectInto(new ArrayList<>()); - assertThat(target).isNotNull(); - assertThat(target).hasSize(50); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterCollectIntoSet(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final Set target = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).collectInto(new HashSet<>()); - assertThat(target).isNotNull(); - assertThat(target).hasSize(50); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterCollectIntoSetStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final Set target = cursor.stream().map(VPackSlice::getAsLong).filter(t -> t < 50).collect(Collectors.toSet()); - assertThat(target).isNotNull(); - assertThat(target).hasSize(50); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void foreach(ArangoDatabase db) { - final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - cursor.foreach(t -> assertThat(t.getAsLong()).isEqualTo(i.getAndIncrement())); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void forEach(ArangoDatabase db) { - final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - cursor.forEach(t -> assertThat(t.getAsLong()).isEqualTo(i.getAndIncrement())); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapForeach(ArangoDatabase db) { - final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - cursor.map(VPackSlice::getAsLong).foreach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapForeachStream(ArangoDatabase db) { - final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - cursor.stream().map(VPackSlice::getAsLong).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterForeach(ArangoDatabase db) { - final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).foreach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterForEachStream(ArangoDatabase db) { - final AtomicLong i = new AtomicLong(0L); - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - cursor.stream().map(VPackSlice::getAsLong).filter(t -> t < 50).forEach(t -> assertThat(t).isEqualTo(i.getAndIncrement())); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void anyMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.anyMatch(t -> t.getAsLong() == 50L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void anyMatchStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.stream().anyMatch(t -> t.getAsLong() == 50L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapAnyMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.map(VPackSlice::getAsLong).anyMatch(t -> t == 50L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterAnyMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).anyMatch(t -> t == 25L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void noneMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.noneMatch(t -> t.getAsLong() == 100L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void noneMatchStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.stream().noneMatch(t -> t.getAsLong() == 100L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapNoneMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.map(VPackSlice::getAsLong).noneMatch(t -> t == 100L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterNoneMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).noneMatch(t -> t == 50L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void allMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.allMatch(t -> t.getAsLong() < 100L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void allMatchStream(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.stream().allMatch(t -> t.getAsLong() < 100L); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapAllMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.map(VPackSlice::getAsLong).allMatch(t -> t < 100); - assertThat(match).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void mapFilterAllMatch(ArangoDatabase db) { - final ArangoCursor cursor = db.query("FOR i IN 0..99 RETURN i", VPackSlice.class); - final boolean match = cursor.map(VPackSlice::getAsLong).filter(t -> t < 50).allMatch(t -> t < 50); - assertThat(match).isTrue(); - } -} diff --git a/src/test/java/com/arangodb/ArangoRouteTest.java b/src/test/java/com/arangodb/ArangoRouteTest.java deleted file mode 100644 index 6bcd38f41..000000000 --- a/src/test/java/com/arangodb/ArangoRouteTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2018 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.internal.ArangoRequestParam; -import com.arangodb.velocystream.Response; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class ArangoRouteTest extends BaseJunit5 { - - private static final String COLLECTION_NAME = "ArangoRouteTest_collection"; - - @BeforeAll - static void init() { - initCollections(COLLECTION_NAME); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void get(ArangoDatabase db) { - final Response res = db.route("/_api/version").get(); - assertThat(res.getBody().get("version").isString()).isTrue(); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void withHeader(ArangoDatabase db) { - final BaseDocument doc = new BaseDocument(); - db.collection(COLLECTION_NAME).insertDocument(doc); - Throwable thrown = catchThrowable(() -> - db.route("/_api/document", doc.getId()).withHeader(ArangoRequestParam.IF_NONE_MATCH, doc.getRevision()).get()); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(304); - } - - @ParameterizedTest(name = "{index}") - @MethodSource("dbs") - void withParentHeader(ArangoDatabase db) { - final BaseDocument doc = new BaseDocument(); - db.collection(COLLECTION_NAME).insertDocument(doc); - Throwable thrown = catchThrowable(() -> - db.route("/_api/document").withHeader(ArangoRequestParam.IF_NONE_MATCH, doc.getRevision()).route(doc.getId()).get()); - assertThat(thrown).isInstanceOf(ArangoDBException.class); - ArangoDBException e = (ArangoDBException) thrown; - assertThat(e.getResponseCode()).isEqualTo(304); - } - -} diff --git a/src/test/java/com/arangodb/BaseDocumentTest.java b/src/test/java/com/arangodb/BaseDocumentTest.java deleted file mode 100644 index 8bb1ed0c4..000000000 --- a/src/test/java/com/arangodb/BaseDocumentTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb; - -import com.arangodb.entity.BaseDocument; -import com.arangodb.internal.velocypack.VPackDriverModule; -import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPack.Builder; -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.ValueType; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - * @author Michele Rastelli - */ -class BaseDocumentTest { - - @Test - void serialize() { - BaseDocument entity = new BaseDocument(); - entity.setKey("test"); - entity.setRevision("test"); - entity.addAttribute("a", "a"); - - Builder builder = new VPack.Builder(); - builder.registerModule(new VPackDriverModule()); - VPack vpacker = builder.build(); - - VPackSlice vpack = vpacker.serialize(entity); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.size()).isEqualTo(3); - - VPackSlice key = vpack.get("_key"); - assertThat(key.isString()).isTrue(); - assertThat(key.getAsString()).isEqualTo("test"); - - VPackSlice rev = vpack.get("_rev"); - assertThat(rev.isString()).isTrue(); - assertThat(rev.getAsString()).isEqualTo("test"); - - VPackSlice a = vpack.get("a"); - assertThat(a.isString()).isTrue(); - assertThat(a.getAsString()).isEqualTo("a"); - } - - @Test - void deserialize() { - VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("_id", "test/test"); - builder.add("_key", "test"); - builder.add("_rev", "test"); - builder.add("a", "a"); - builder.close(); - - VPack.Builder vbuilder = new VPack.Builder(); - vbuilder.registerModule(new VPackDriverModule()); - VPack vpacker = vbuilder.build(); - - BaseDocument entity = vpacker.deserialize(builder.slice(), BaseDocument.class); - assertThat(entity.getId()).isNotNull(); - assertThat(entity.getId()).isEqualTo("test/test"); - assertThat(entity.getKey()).isNotNull(); - assertThat(entity.getKey()).isEqualTo("test"); - assertThat(entity.getRevision()).isNotNull(); - assertThat(entity.getRevision()).isEqualTo("test"); - assertThat(entity.getProperties()).hasSize(1); - assertThat(String.valueOf(entity.getAttribute("a"))).isEqualTo("a"); - } - -} diff --git a/src/test/java/com/arangodb/async/example/velocypack/VPackExampleTest.java b/src/test/java/com/arangodb/async/example/velocypack/VPackExampleTest.java deleted file mode 100644 index a2a91781b..000000000 --- a/src/test/java/com/arangodb/async/example/velocypack/VPackExampleTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.async.example.velocypack; - -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.ValueType; -import com.arangodb.velocypack.exception.VPackException; -import org.junit.jupiter.api.Test; - - -import java.util.Iterator; -import java.util.Map.Entry; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class VPackExampleTest { - - @Test - void buildObject() throws VPackException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT);// object start - builder.add("foo", 1); // add field "foo" with value 1 - builder.add("bar", 2); // add field "bar" with value 2 - builder.close();// object end - - final VPackSlice slice = builder.slice(); // create slice - assertThat(slice.isObject()).isTrue(); - assertThat(slice.size()).isEqualTo(2); // number of fields - - final VPackSlice foo = slice.get("foo"); // get field "foo" - assertThat(foo.isInteger()).isTrue(); - assertThat(foo.getAsInt()).isEqualTo(1); - - final VPackSlice bar = slice.get("bar"); // get field "bar" - assertThat(bar.isInteger()).isTrue(); - assertThat(bar.getAsInt()).isEqualTo(2); - - // iterate over the fields - for (final Iterator> iterator = slice.objectIterator(); iterator.hasNext(); ) { - final Entry field = iterator.next(); - assertThat(field.getValue().isInteger()).isTrue(); - } - } - - @Test - void buildArray() throws VPackException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.ARRAY); // array start - builder.add(1);// add value 1 - builder.add(2);// add value 2 - builder.add(3);// add value 3 - builder.close(); // array end - - final VPackSlice slice = builder.slice();// create slice - assertThat(slice.isArray()).isTrue(); - assertThat(slice.size()).isEqualTo(3);// number of values - - // iterate over values - for (int i = 0; i < slice.size(); i++) { - final VPackSlice value = slice.get(i); - assertThat(value.isInteger()).isTrue(); - assertThat(value.getAsInt()).isEqualTo(i + 1); - } - - // iterate over values with Iterator - for (final Iterator iterator = slice.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice value = iterator.next(); - assertThat(value.isInteger()).isTrue(); - } - } - - @Test - void buildObjectInObject() throws VPackException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT);// object start - builder.add("foo", ValueType.OBJECT); // add object in field "foo" - builder.add("bar", 2); // add field "bar" with value 2 to object "foo" - builder.close();// object "foo" end - builder.close();// object end - - final VPackSlice slice = builder.slice(); // create slice - assertThat(slice.isObject()).isTrue(); - - final VPackSlice foo = slice.get("foo"); - assertThat(foo.isObject()).isTrue(); - - final VPackSlice bar = foo.get("bar"); // get field "bar" from "foo" - assertThat(bar.isInteger()).isTrue(); - } - -} diff --git a/src/test/java/com/arangodb/example/velocypack/VPackExampleTest.java b/src/test/java/com/arangodb/example/velocypack/VPackExampleTest.java deleted file mode 100644 index dd1d1e421..000000000 --- a/src/test/java/com/arangodb/example/velocypack/VPackExampleTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.example.velocypack; - -import com.arangodb.velocypack.VPackBuilder; -import com.arangodb.velocypack.VPackSlice; -import com.arangodb.velocypack.ValueType; -import com.arangodb.velocypack.exception.VPackException; -import org.junit.jupiter.api.Test; - -import java.util.Iterator; -import java.util.Map.Entry; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class VPackExampleTest { - - @Test - void buildObject() throws VPackException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT);// object start - builder.add("foo", 1); // add field "foo" with value 1 - builder.add("bar", 2); // add field "bar" with value 2 - builder.close();// object end - - final VPackSlice slice = builder.slice(); // create slice - assertThat(slice.isObject()).isTrue(); - assertThat(slice.size()).isEqualTo(2); // number of fields - - final VPackSlice foo = slice.get("foo"); // get field "foo" - assertThat(foo.isInteger()).isTrue(); - assertThat(foo.getAsInt()).isEqualTo(1); - - final VPackSlice bar = slice.get("bar"); // get field "bar" - assertThat(bar.isInteger()).isTrue(); - assertThat(bar.getAsInt()).isEqualTo(2); - - // iterate over the fields - for (final Iterator> iterator = slice.objectIterator(); iterator.hasNext(); ) { - final Entry field = iterator.next(); - assertThat(field.getValue().isInteger()).isTrue(); - } - } - - @Test - void buildArray() throws VPackException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.ARRAY); // array start - builder.add(1);// add value 1 - builder.add(2);// add value 2 - builder.add(3);// add value 3 - builder.close(); // array end - - final VPackSlice slice = builder.slice();// create slice - assertThat(slice.isArray()).isTrue(); - assertThat(slice.size()).isEqualTo(3);// number of values - - // iterate over values - for (int i = 0; i < slice.size(); i++) { - final VPackSlice value = slice.get(i); - assertThat(value.isInteger()).isTrue(); - assertThat(value.getAsInt()).isEqualTo(i + 1); - } - - // iterate over values with Iterator - for (final Iterator iterator = slice.arrayIterator(); iterator.hasNext(); ) { - final VPackSlice value = iterator.next(); - assertThat(value.isInteger()).isTrue(); - } - } - - @Test - void buildObjectInObject() throws VPackException { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT);// object start - builder.add("foo", ValueType.OBJECT); // add object in field "foo" - builder.add("bar", 2); // add field "bar" with value 2 to object "foo" - builder.close();// object "foo" end - builder.close();// object end - - final VPackSlice slice = builder.slice(); // create slice - assertThat(slice.isObject()).isTrue(); - - final VPackSlice foo = slice.get("foo"); - assertThat(foo.isObject()).isTrue(); - - final VPackSlice bar = foo.get("bar"); // get field "bar" from "foo" - assertThat(bar.isInteger()).isTrue(); - } - -} diff --git a/src/test/java/com/arangodb/internal/DocumentCacheTest.java b/src/test/java/com/arangodb/internal/DocumentCacheTest.java deleted file mode 100644 index 474cd6882..000000000 --- a/src/test/java/com/arangodb/internal/DocumentCacheTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal; - -import com.arangodb.entity.BaseDocument; -import org.junit.jupiter.api.Test; - -import java.util.HashMap; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class DocumentCacheTest { - - @Test - void setValues() { - final DocumentCache cache = new DocumentCache(); - final BaseDocument doc = new BaseDocument(); - - assertThat(doc.getId()).isNull(); - assertThat(doc.getKey()).isNull(); - assertThat(doc.getRevision()).isNull(); - - final Map values = new HashMap<>(); - values.put(DocumentFields.ID, "testId"); - values.put(DocumentFields.KEY, "testKey"); - values.put(DocumentFields.REV, "testRev"); - cache.setValues(doc, values); - - assertThat(doc.getId()).isEqualTo("testId"); - assertThat(doc.getKey()).isEqualTo("testKey"); - assertThat(doc.getRevision()).isEqualTo("testRev"); - } - - @Test - void setValuesMap() { - final DocumentCache cache = new DocumentCache(); - final Map map = new HashMap<>(); - - final Map values = new HashMap<>(); - values.put(DocumentFields.ID, "testId"); - values.put(DocumentFields.KEY, "testKey"); - values.put(DocumentFields.REV, "testRev"); - cache.setValues(map, values); - - assertThat(map.isEmpty()).isTrue(); - } -} diff --git a/src/test/java/com/arangodb/internal/velocypack/VPackSerializersTest.java b/src/test/java/com/arangodb/internal/velocypack/VPackSerializersTest.java deleted file mode 100644 index 5c3880ba6..000000000 --- a/src/test/java/com/arangodb/internal/velocypack/VPackSerializersTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocypack; - -import com.arangodb.entity.ViewType; -import com.arangodb.entity.arangosearch.ArangoSearchCompression; -import com.arangodb.entity.arangosearch.ArangoSearchProperties; -import com.arangodb.entity.arangosearch.StoredValue; -import com.arangodb.model.arangosearch.ArangoSearchCreateOptions; -import com.arangodb.velocypack.VPack; -import com.arangodb.velocypack.VPackSlice; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Collections; - -import static org.assertj.core.api.Assertions.assertThat; - -class VPackSerializersTest { - - private VPack vpack; - - @BeforeEach - void init() { - vpack = new VPack.Builder() - .registerSerializer(ArangoSearchProperties.class, VPackSerializers.ARANGO_SEARCH_PROPERTIES) - .build(); - } - - @Test - void serializeArangoSearchProperties() { - final ArangoSearchCreateOptions opts = new ArangoSearchCreateOptions() - .storedValues(new StoredValue(Collections.singletonList("dummy"), ArangoSearchCompression.lz4)); - - final VPackSlice slice = vpack.serialize(opts); - - assertThat(slice.isObject()).isTrue(); - assertThat(slice.get("type").isString()).isTrue(); - assertThat(slice.get("type").getAsString()).isEqualTo(ViewType.ARANGO_SEARCH.name()); - assertThat(slice.get("storedValues")).isNotNull(); - assertThat(slice.get("storedValues").isArray()).isTrue(); - assertThat(slice.get("storedValues").size()).isEqualTo(1); - assertThat(slice.get("storedValues").get(0).isObject()).isTrue(); - assertThat(slice.get("storedValues").get(0).get("fields").isArray()).isTrue(); - assertThat(slice.get("storedValues").get(0).get("fields").size()).isEqualTo(1); - assertThat(slice.get("storedValues").get(0).get("fields").get(0).isString()).isTrue(); - assertThat(slice.get("storedValues").get(0).get("fields").get(0).getAsString()).isEqualTo("dummy"); - assertThat(slice.get("storedValues").get(0).get("compression").isString()).isTrue(); - assertThat(slice.get("storedValues").get(0).get("compression").getAsString()).isEqualTo(ArangoSearchCompression.lz4.name()); - } - - @Test - void serializeArangoSearchPropertiesWithDefaultCompression() { - final ArangoSearchCreateOptions opts = new ArangoSearchCreateOptions() - .storedValues(new StoredValue(Collections.singletonList("dummy"))); - - final VPackSlice slice = vpack.serialize(opts); - - assertThat(slice.get("storedValues").get(0).get("compression").isNone()).isTrue(); - } -} diff --git a/src/test/java/com/arangodb/mapping/VPackSerializeDeserializeTest.java b/src/test/java/com/arangodb/mapping/VPackSerializeDeserializeTest.java deleted file mode 100644 index eed9a8052..000000000 --- a/src/test/java/com/arangodb/mapping/VPackSerializeDeserializeTest.java +++ /dev/null @@ -1,3302 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - - -package com.arangodb.mapping; - -import com.arangodb.velocypack.*; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.Map.Entry; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Mark Vollmary - */ -class VPackSerializeDeserializeTest { - - private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");// ISO 8601 - - static { - DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); - } - - private final ObjectMapper mapper = ArangoJack.createDefaultMapper(); - - public static class TestEntityBoolean { - private boolean a = true; - private boolean b = false; - private Boolean c = Boolean.TRUE; - private Boolean d = Boolean.FALSE; - - public boolean isA() { - return a; - } - - public void setA(final boolean a) { - this.a = a; - } - - public boolean isB() { - return b; - } - - public void setB(final boolean b) { - this.b = b; - } - - public Boolean getC() { - return c; - } - - public void setC(final Boolean c) { - this.c = c; - } - - public Boolean getD() { - return d; - } - - public void setD(final Boolean d) { - this.d = d; - } - } - - @Test - void fromBoolean() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityBoolean())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice a = vpack.get("a"); - assertThat(a.isBoolean()).isTrue(); - assertThat(a.getAsBoolean()).isTrue(); - } - { - final VPackSlice b = vpack.get("b"); - assertThat(b.isBoolean()).isTrue(); - assertThat(b.getAsBoolean()).isFalse(); - } - { - final VPackSlice c = vpack.get("c"); - assertThat(c.isBoolean()).isTrue(); - assertThat(c.getAsBoolean()).isTrue(); - } - { - final VPackSlice d = vpack.get("d"); - assertThat(d.isBoolean()).isTrue(); - assertThat(d.getAsBoolean()).isFalse(); - } - } - - @Test - void toBoolean() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("a", false); - builder.add("b", true); - builder.add("c", Boolean.FALSE); - builder.add("d", Boolean.TRUE); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityBoolean entity = mapper.readValue(vpack.getBuffer(), TestEntityBoolean.class); - assertThat(entity).isNotNull(); - assertThat(entity.a).isFalse(); - assertThat(entity.b).isTrue(); - assertThat(entity.c).isInstanceOf(Boolean.class).isFalse(); - assertThat(entity.d).isInstanceOf(Boolean.class).isTrue(); - } - - public static class TestEntityString { - private String s = "test"; - private Character c1 = 't'; - private char c2 = 't'; - - public String getS() { - return s; - } - - public void setS(final String s) { - this.s = s; - } - - public Character getC1() { - return c1; - } - - public void setC1(final Character c1) { - this.c1 = c1; - } - - public char getC2() { - return c2; - } - - public void setC2(final char c2) { - this.c2 = c2; - } - } - - @Test - void fromStrings() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityString())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice s = vpack.get("s"); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo("test"); - } - { - final VPackSlice c1 = vpack.get("c1"); - assertThat(c1.isString()).isTrue(); - assertThat(c1.getAsChar()).isEqualTo('t'); - } - { - final VPackSlice c2 = vpack.get("c2"); - assertThat(c2.isString()).isTrue(); - assertThat(c2.getAsChar()).isEqualTo('t'); - } - } - - @Test - void toStrings() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("s", "abc"); - builder.add("c1", 'd'); - builder.add("c2", 'd'); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityString entity = mapper.readValue(vpack.getBuffer(), TestEntityString.class); - assertThat(entity).isNotNull(); - assertThat(entity.s).isEqualTo("abc"); - assertThat(entity.c1).isEqualTo(new Character('d')); - } - - public static class TestEntityInteger { - private int i1 = 1; - private Integer i2 = 1; - - public int getI1() { - return i1; - } - - public void setI1(final int i1) { - this.i1 = i1; - } - - public Integer getI2() { - return i2; - } - - public void setI2(final Integer i2) { - this.i2 = i2; - } - } - - @Test - void fromInteger() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityInteger())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice i1 = vpack.get("i1"); - assertThat(i1.isInteger()).isTrue(); - assertThat(i1.getAsInt()).isEqualTo(1); - } - { - final VPackSlice i2 = vpack.get("i2"); - assertThat(i2.isInteger()).isTrue(); - assertThat(i2.getAsInt()).isEqualTo(1); - } - } - - @Test - void fromNegativeInteger() throws JsonProcessingException { - final TestEntityInteger entity = new TestEntityInteger(); - entity.i1 = -50; - entity.i2 = -50; - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice i1 = vpack.get("i1"); - assertThat(i1.isInteger()).isTrue(); - assertThat(i1.getAsInt()).isEqualTo(-50); - } - { - final VPackSlice i2 = vpack.get("i2"); - assertThat(i2.isInteger()).isTrue(); - assertThat(i2.getAsInt()).isEqualTo(-50); - } - } - - @Test - void toInteger() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("i1", 2); - builder.add("i2", 3); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityInteger entity = mapper.readValue(vpack.getBuffer(), TestEntityInteger.class); - assertThat(entity).isNotNull(); - assertThat(entity.i1).isEqualTo(2); - assertThat(entity.i2).isEqualTo(Integer.valueOf(3)); - } - - @Test - void toNegativeInteger() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("i1", -50); - builder.add("i2", -50); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityInteger entity = mapper.readValue(vpack.getBuffer(), TestEntityInteger.class); - assertThat(entity).isNotNull(); - assertThat(entity.i1).isEqualTo(-50); - assertThat(entity.i2).isEqualTo(Integer.valueOf(-50)); - } - - public static class TestEntityLong { - private long l1 = 1; - private Long l2 = 1L; - - public long getL1() { - return l1; - } - - public void setL1(final long l1) { - this.l1 = l1; - } - - public Long getL2() { - return l2; - } - - public void setL2(final Long l2) { - this.l2 = l2; - } - } - - @Test - void fromLong() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityLong())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice l1 = vpack.get("l1"); - assertThat(l1.isInteger()).isTrue(); - assertThat(l1.getAsLong()).isEqualTo(1L); - } - { - final VPackSlice l2 = vpack.get("l2"); - assertThat(l2.isInteger()).isTrue(); - assertThat(l2.getAsLong()).isEqualTo(1L); - } - } - - @Test - void fromNegativeLong() throws JsonProcessingException { - final TestEntityLong entity = new TestEntityLong(); - entity.l1 = -100L; - entity.l2 = -300L; - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice l1 = vpack.get("l1"); - assertThat(l1.isInteger()).isTrue(); - assertThat(l1.getAsLong()).isEqualTo(-100L); - } - { - final VPackSlice l2 = vpack.get("l2"); - assertThat(l2.isInteger()).isTrue(); - assertThat(l2.getAsLong()).isEqualTo(-300); - } - } - - @Test - void toLong() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("l1", 2); - builder.add("l2", 3); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); - assertThat(entity).isNotNull(); - assertThat(entity.l1).isEqualTo(2); - assertThat(entity.l2).isEqualTo(Long.valueOf(3)); - } - - @Test - void toNegativeLong() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("l1", -100L); - builder.add("l2", -300L); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); - assertThat(entity).isNotNull(); - assertThat(entity.l1).isEqualTo(-100L); - assertThat(entity.l2).isEqualTo(Long.valueOf(-300)); - } - - @Test - void negativeLong() { - final TestEntityLong entity = new TestEntityLong(); - entity.l1 = -100L; - entity.l2 = -300L; - final VPack vp = new VPack.Builder().build(); - final TestEntityLong out = vp.deserialize(vp.serialize(entity), TestEntityLong.class); - assertThat(out.l1).isEqualTo(entity.l1); - assertThat(out.l2).isEqualTo(entity.l2); - } - - @Test - void intToLong() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("l1", 100); - builder.add("l2", 300); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); - assertThat(entity).isNotNull(); - assertThat(entity.l1).isEqualTo(100); - assertThat(entity.l2).isEqualTo(Long.valueOf(300)); - } - - @Test - void negativeIntToLong() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("l1", -100); - builder.add("l2", -300); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); - assertThat(entity).isNotNull(); - assertThat(entity.l1).isEqualTo(-100L); - assertThat(entity.l2).isEqualTo(Long.valueOf(-300)); - } - - @Test - void negativeLongToInt() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("i1", -100L); - builder.add("i2", -300L); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityInteger entity = mapper.readValue(vpack.getBuffer(), TestEntityInteger.class); - assertThat(entity).isNotNull(); - assertThat(entity.i1).isEqualTo(-100); - assertThat(entity.i2).isEqualTo(Integer.valueOf(-300)); - } - - @Test - void negativeLongToShort() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("s1", -100L); - builder.add("s2", -300L); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityShort entity = mapper.readValue(vpack.getBuffer(), TestEntityShort.class); - assertThat(entity).isNotNull(); - assertThat(entity.s1).isEqualTo((short) -100); - assertThat(entity.s2).isEqualTo(Short.valueOf((short) -300)); - } - - @Test - void negativeShortToLong() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("l1", (short) -100); - builder.add("l2", (short) -300); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityLong entity = mapper.readValue(vpack.getBuffer(), TestEntityLong.class); - assertThat(entity).isNotNull(); - assertThat(entity.l1).isEqualTo(-100L); - assertThat(entity.l2).isEqualTo(Long.valueOf(-300)); - } - - public static class TestEntityFloat { - private float f1 = 1; - private Float f2 = 1F; - - public float getF1() { - return f1; - } - - public void setF1(final float f1) { - this.f1 = f1; - } - - public Float getF2() { - return f2; - } - - public void setF2(final Float f2) { - this.f2 = f2; - } - } - - @Test - void fromFloat() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityFloat())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice f1 = vpack.get("f1"); - assertThat(f1.isDouble()).isTrue(); - assertThat(f1.getAsFloat()).isEqualTo(1.0F); - } - { - final VPackSlice f2 = vpack.get("f2"); - assertThat(f2.isDouble()).isTrue(); - assertThat(f2.getAsFloat()).isEqualTo(1.0F); - } - } - - @Test - void toFloat() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("f1", 2F); - builder.add("f2", 3F); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityFloat entity = mapper.readValue(vpack.getBuffer(), TestEntityFloat.class); - assertThat(entity).isNotNull(); - assertThat(entity.f1).isEqualTo(2F); - assertThat(entity.f2).isEqualTo(new Float(3)); - } - - public static class TestEntityShort { - private short s1 = 1; - private Short s2 = 1; - - public short getS1() { - return s1; - } - - public void setS1(final short s1) { - this.s1 = s1; - } - - public Short getS2() { - return s2; - } - - public void setS2(final Short s2) { - this.s2 = s2; - } - } - - @Test - void fromShort() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityShort())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice s1 = vpack.get("s1"); - assertThat(s1.isInteger()).isTrue(); - assertThat(s1.getAsShort()).isEqualTo((short) 1); - } - { - final VPackSlice s2 = vpack.get("s2"); - assertThat(s2.isInteger()).isTrue(); - assertThat(s2.getAsShort()).isEqualTo((short) 1); - } - } - - @Test - void toShort() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("s1", 2); - builder.add("s2", 3); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityShort entity = mapper.readValue(vpack.getBuffer(), TestEntityShort.class); - assertThat(entity).isNotNull(); - assertThat(entity.s1).isEqualTo((short) 2); - assertThat(entity.s2).isEqualTo(Short.valueOf((short) 3)); - } - - public static class TestEntityByte { - private byte b1 = 1; // short integer path - private Byte b2 = 100; // integer path - - public byte getB1() { - return b1; - } - - public void setB1(final byte b1) { - this.b1 = b1; - } - - public Byte getB2() { - return b2; - } - - public void setB2(final Byte b2) { - this.b2 = b2; - } - } - - @Test - void fromByte() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityByte())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice b1 = vpack.get("b1"); - assertThat(b1.isInteger()).isTrue(); - assertThat(b1.getAsByte()).isEqualTo((byte) 1); - } - { - final VPackSlice b2 = vpack.get("b2"); - assertThat(b2.isInteger()).isTrue(); - assertThat(b2.getAsByte()).isEqualTo((byte) 100); - } - } - - @Test - void toByte() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("b1", 30); // integer path - builder.add("b2", 4); // short integer path - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityByte entity = mapper.readValue(vpack.getBuffer(), TestEntityByte.class); - assertThat(entity).isNotNull(); - assertThat(entity.b1).isEqualTo((byte) 30); - assertThat(entity.b2).isEqualTo(Byte.valueOf((byte) 4)); - } - - public static class TestEntityDouble { - private Double d1 = 1.5; - private double d2 = 1.5; - - public Double getD1() { - return d1; - } - - public void setD1(final Double d1) { - this.d1 = d1; - } - - public double getD2() { - return d2; - } - - public void setD2(final double d2) { - this.d2 = d2; - } - } - - @Test - void fromDouble() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityDouble())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice d1 = vpack.get("d1"); - assertThat(d1.isDouble()).isTrue(); - assertThat(d1.getAsDouble()).isEqualTo(1.5); - } - { - final VPackSlice d2 = vpack.get("d2"); - assertThat(d2.isDouble()).isTrue(); - assertThat(d2.getAsDouble()).isEqualTo(1.5); - } - } - - @Test - void toDouble() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("d1", 2.25); - builder.add("d2", 3.75); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityDouble entity = mapper.readValue(vpack.getBuffer(), TestEntityDouble.class); - assertThat(entity).isNotNull(); - assertThat(entity.d1).isEqualTo(2.25); - assertThat(entity.d2).isEqualTo(3.75); - } - - public static class TestEntityBigNumber { - private static final BigInteger BI = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); - private static final BigDecimal BD = BigDecimal.valueOf(Double.MAX_VALUE).add(BigDecimal.ONE); - - private BigInteger bi = BI; - private BigDecimal bd = BD; - - public BigInteger getBi() { - return bi; - } - - public void setBi(final BigInteger bi) { - this.bi = bi; - } - - public BigDecimal getBd() { - return bd; - } - - public void setBd(final BigDecimal bd) { - this.bd = bd; - } - } - - @Test - void fromBigNumbers() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityBigNumber())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice bi = vpack.get("bi"); - assertThat(bi.isString()).isTrue(); - assertThat(bi.getAsBigInteger()).isEqualTo(TestEntityBigNumber.BI); - } - { - final VPackSlice bd = vpack.get("bd"); - assertThat(bd.isString()).isTrue(); - assertThat(bd.getAsBigDecimal()).isEqualTo(TestEntityBigNumber.BD); - } - } - - @Test - void toBigNumbers() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("bi", BigInteger.valueOf(2)); - builder.add("bd", BigDecimal.valueOf(3.75)); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityBigNumber entity = mapper.readValue(vpack.getBuffer(), TestEntityBigNumber.class); - assertThat(entity).isNotNull(); - assertThat(entity.bi).isEqualTo(BigInteger.valueOf(2)); - assertThat(entity.bd).isEqualTo(BigDecimal.valueOf(3.75)); - } - - @Test - void bigDecimal() { - final BigDecimal fromDouble = BigDecimal.valueOf(-710.01); - final BigDecimal fromString = new BigDecimal("-710.01"); - assertThat(fromDouble).isEqualTo(fromString); - assertThat(new VPackBuilder().add(fromDouble).slice().getAsBigDecimal()).isEqualTo(fromDouble); - assertThat(new VPackBuilder().add(fromString).slice().getAsBigDecimal()).isEqualTo(fromDouble); - } - - public static class TestEntityArray { - private String[] a1 = {"a", "b", "cd"}; - private int[] a2 = {1, 2, 3, 4, 5}; - private boolean[] a3 = {true, true, false}; - private TestEnum[] a4 = TestEnum.values(); - - public String[] getA1() { - return a1; - } - - public void setA1(final String[] a1) { - this.a1 = a1; - } - - public int[] getA2() { - return a2; - } - - public void setA2(final int[] a2) { - this.a2 = a2; - } - - public boolean[] getA3() { - return a3; - } - - public void setA3(final boolean[] a3) { - this.a3 = a3; - } - - public TestEnum[] getA4() { - return a4; - } - - public void setA4(final TestEnum[] a4) { - this.a4 = a4; - } - - } - - @Test - void fromArray() throws JsonProcessingException { - final TestEntityArray entity = new TestEntityArray(); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice a1 = vpack.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.getLength()).isEqualTo(entity.a1.length); - for (int i = 0; i < a1.getLength(); i++) { - assertThat(a1.get(i).getAsString()).isEqualTo(entity.a1[i]); - } - } - { - final VPackSlice a2 = vpack.get("a2"); - assertThat(a2.isArray()).isTrue(); - assertThat(a2.getLength()).isEqualTo(entity.a2.length); - for (int i = 0; i < a2.getLength(); i++) { - assertThat(a2.get(i).getAsInt()).isEqualTo(entity.a2[i]); - } - } - { - final VPackSlice a3 = vpack.get("a3"); - assertThat(a3.isArray()).isTrue(); - assertThat(a3.getLength()).isEqualTo(entity.a3.length); - for (int i = 0; i < a3.getLength(); i++) { - assertThat(a3.get(i).getAsBoolean()).isEqualTo(entity.a3[i]); - } - } - { - final VPackSlice a4 = vpack.get("a4"); - assertThat(a4.isArray()).isTrue(); - assertThat(a4.getLength()).isEqualTo(entity.a4.length); - for (int i = 0; i < a4.getLength(); i++) { - assertThat(TestEnum.valueOf(a4.get(i).getAsString())).isEqualTo(entity.a4[i]); - } - } - } - - @Test - void toArray() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("a1", ValueType.ARRAY); - builder.add("a"); - builder.add("b"); - builder.add("c"); - builder.close(); - } - { - builder.add("a2", ValueType.ARRAY); - builder.add(1); - builder.add(2); - builder.add(3); - builder.add(4); - builder.close(); - } - { - builder.add("a3", ValueType.ARRAY); - builder.add(false); - builder.add(true); - builder.close(); - } - { - builder.add("a4", ValueType.ARRAY); - builder.add(TestEnum.A.name()); - builder.add(TestEnum.B.name()); - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityArray entity = mapper.readValue(vpack.getBuffer(), TestEntityArray.class); - assertThat(entity).isNotNull(); - { - assertThat(entity.a1).hasSize(3); - assertThat(entity.a1[0]).isEqualTo("a"); - assertThat(entity.a1[1]).isEqualTo("b"); - assertThat(entity.a1[2]).isEqualTo("c"); - } - { - assertThat(entity.a2).hasSize(4); - assertThat(entity.a2[0]).isEqualTo(1); - assertThat(entity.a2[1]).isEqualTo(2); - assertThat(entity.a2[2]).isEqualTo(3); - assertThat(entity.a2[3]).isEqualTo(4); - } - { - assertThat(entity.a3).hasSize(2); - assertThat(entity.a3[0]).isFalse(); - assertThat(entity.a3[1]).isTrue(); - } - { - assertThat(entity.a4).hasSize(2); - assertThat(entity.a4[0]).isEqualTo(TestEnum.A); - assertThat(entity.a4[1]).isEqualTo(TestEnum.B); - } - } - - @Test - void fromArrayWithNull() throws JsonProcessingException { - final TestEntityArray entity = new TestEntityArray(); - entity.a1 = new String[]{"foo", null}; - - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - - final VPackSlice a1 = vpack.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.size()).isEqualTo(2); - assertThat(a1.get(0).isString()).isTrue(); - assertThat(a1.get(0).getAsString()).isEqualTo("foo"); - assertThat(a1.get(1).isNull()).isTrue(); - } - - protected enum TestEnum { - A, B, C - } - - public static class TestEntityEnum { - private TestEnum e1 = TestEnum.A; - - public TestEnum getE1() { - return e1; - } - - public void setE1(final TestEnum e1) { - this.e1 = e1; - } - } - - @Test - void fromEnum() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityEnum())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice e1 = vpack.get("e1"); - assertThat(e1.isString()).isTrue(); - assertThat(TestEnum.valueOf(e1.getAsString())).isEqualTo(TestEnum.A); - } - } - - @Test - void toEnum() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("e1", TestEnum.B.name()); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityEnum entity = mapper.readValue(vpack.getBuffer(), TestEntityEnum.class); - assertThat(entity).isNotNull(); - assertThat(entity.e1).isEqualTo(TestEnum.B); - } - - public static class TestEntityObject { - private TestEntityLong o1 = new TestEntityLong(); - private TestEntityArray o2 = new TestEntityArray(); - - public TestEntityLong getO1() { - return o1; - } - - public void setO1(final TestEntityLong o1) { - this.o1 = o1; - } - - public TestEntityArray getO2() { - return o2; - } - - public void setO2(final TestEntityArray o2) { - this.o2 = o2; - } - } - - @Test - void fromObject() throws JsonProcessingException { - final TestEntityObject entity = new TestEntityObject(); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice o1 = vpack.get("o1"); - assertThat(o1.isObject()).isTrue(); - { - final VPackSlice l1 = o1.get("l1"); - assertThat(l1.isInteger()).isTrue(); - assertThat(l1.getAsLong()).isEqualTo(1L); - } - { - final VPackSlice l2 = o1.get("l2"); - assertThat(l2.isInteger()).isTrue(); - assertThat(l2.getAsLong()).isEqualTo(1L); - } - } - { - final VPackSlice o2 = vpack.get("o2"); - assertThat(o2.isObject()).isTrue(); - { - final VPackSlice a1 = o2.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.getLength()).isEqualTo(entity.o2.a1.length); - for (int i = 0; i < a1.getLength(); i++) { - assertThat(a1.get(i).getAsString()).isEqualTo(entity.o2.a1[i]); - } - } - { - final VPackSlice a2 = o2.get("a2"); - assertThat(a2.isArray()).isTrue(); - assertThat(a2.getLength()).isEqualTo(entity.o2.a2.length); - for (int i = 0; i < a2.getLength(); i++) { - assertThat(a2.get(i).getAsInt()).isEqualTo(entity.o2.a2[i]); - } - } - { - final VPackSlice a3 = o2.get("a3"); - assertThat(a3.isArray()).isTrue(); - assertThat(a3.getLength()).isEqualTo(entity.o2.a3.length); - for (int i = 0; i < a3.getLength(); i++) { - assertThat(a3.get(i).getAsBoolean()).isEqualTo(entity.o2.a3[i]); - } - } - { - final VPackSlice a4 = o2.get("a4"); - assertThat(a4.isArray()).isTrue(); - assertThat(a4.getLength()).isEqualTo(entity.o2.a4.length); - for (int i = 0; i < a4.getLength(); i++) { - assertThat(TestEnum.valueOf(a4.get(i).getAsString())).isEqualTo(entity.o2.a4[i]); - } - } - } - } - - @Test - void toObject() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("o1", ValueType.OBJECT); - builder.add("l1", 5L); - builder.add("l2", 5L); - builder.close(); - } - { - builder.add("o2", ValueType.OBJECT); - { - builder.add("a1", ValueType.ARRAY); - builder.add("a"); - builder.add("b"); - builder.add("c"); - builder.close(); - } - { - builder.add("a2", ValueType.ARRAY); - builder.add(1); - builder.add(2); - builder.add(3); - builder.add(4); - builder.close(); - } - { - builder.add("a3", ValueType.ARRAY); - builder.add(false); - builder.add(true); - builder.close(); - } - { - builder.add("a4", ValueType.ARRAY); - builder.add(TestEnum.A.name()); - builder.add(TestEnum.B.name()); - builder.close(); - } - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityObject entity = mapper.readValue(vpack.getBuffer(), TestEntityObject.class); - assertThat(entity).isNotNull(); - { - assertThat(entity.o1.l1).isEqualTo(5L); - assertThat(entity.o1.l2).isEqualTo(Long.valueOf(5)); - } - { - assertThat(entity.o2.a1).hasSize(3); - assertThat(entity.o2.a1[0]).isEqualTo("a"); - assertThat(entity.o2.a1[1]).isEqualTo("b"); - assertThat(entity.o2.a1[2]).isEqualTo("c"); - } - { - assertThat(entity.o2.a2).hasSize(4); - assertThat(entity.o2.a2[0]).isEqualTo(1); - assertThat(entity.o2.a2[1]).isEqualTo(2); - assertThat(entity.o2.a2[2]).isEqualTo(3); - assertThat(entity.o2.a2[3]).isEqualTo(4); - } - { - assertThat(entity.o2.a3).hasSize(2); - assertThat(entity.o2.a3[0]).isFalse(); - assertThat(entity.o2.a3[1]).isTrue(); - } - { - assertThat(entity.o2.a4).hasSize(2); - assertThat(entity.o2.a4[0]).isEqualTo(TestEnum.A); - assertThat(entity.o2.a4[1]).isEqualTo(TestEnum.B); - } - } - - public static class TestEntityArrayInArray { - private long[][] a1; - - public long[][] getA1() { - return a1; - } - - public void setA1(final long[][] a1) { - this.a1 = a1; - } - } - - @Test - void fromArrayInArray() throws JsonProcessingException { - final TestEntityArrayInArray entity = new TestEntityArrayInArray(); - entity.a1 = new long[][]{{1, 2, 3}, {4, 5, 6}}; - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice a1 = vpack.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.getLength()).isEqualTo(entity.a1.length); - for (int i = 0; i < a1.getLength(); i++) { - final VPackSlice at = a1.get(i); - assertThat(at.isArray()).isTrue(); - assertThat(at.getLength()).isEqualTo(entity.a1[i].length); - for (int j = 0; j < at.getLength(); j++) { - final VPackSlice atat = at.get(j); - assertThat(atat.isInteger()).isTrue(); - assertThat(atat.getAsLong()).isEqualTo(entity.a1[i][j]); - } - } - } - } - - @Test - void toArrayInArray() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("a1", ValueType.ARRAY); - { - builder.add(ValueType.ARRAY); - builder.add(1); - builder.add(2); - builder.add(3); - builder.close(); - } - { - builder.add(ValueType.ARRAY); - builder.add(4); - builder.add(5); - builder.add(6); - builder.close(); - } - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityArrayInArray entity = mapper.readValue(vpack.getBuffer(), TestEntityArrayInArray.class); - assertThat(entity).isNotNull(); - assertThat(entity.a1.length).isEqualTo(2); - { - assertThat(entity.a1[0]).hasSize(3); - assertThat(entity.a1[0][0]).isEqualTo(1L); - assertThat(entity.a1[0][1]).isEqualTo(2L); - assertThat(entity.a1[0][2]).isEqualTo(3L); - } - { - assertThat(entity.a1[1]).hasSize(3); - assertThat(entity.a1[1][0]).isEqualTo(4L); - assertThat(entity.a1[1][1]).isEqualTo(5L); - assertThat(entity.a1[1][2]).isEqualTo(6L); - } - } - - @SuppressWarnings("serial") - public static class TestCollection extends LinkedList { - - } - - public static class TestEntityCollectionExtendedWithNulls { - - protected TestCollection a1; - - public TestCollection getA1() { - return a1; - } - - public void setA1(final TestCollection a1) { - this.a1 = a1; - } - - } - - @Test - void fromCollectionExtendedWithNulls() { - - final TestCollection collection = new TestCollection(); - collection.add("one"); - collection.add(null); - collection.add("two"); - - final TestEntityCollectionExtendedWithNulls entity = new TestEntityCollectionExtendedWithNulls(); - entity.setA1(collection); - - final VPackSlice vpack = new VPack.Builder().serializeNullValues(true).build().serialize(entity); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice a1 = vpack.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.getLength()).isEqualTo(entity.a1.size()); - - VPackSlice at = a1.get(0); - assertThat(at.isString()).isTrue(); - assertThat(at.getAsString()).isEqualTo(entity.a1.get(0)); - at = a1.get(1); - assertThat(at.isNull()).isTrue(); - at = a1.get(2); - assertThat(at.isString()).isTrue(); - assertThat(at.getAsString()).isEqualTo(entity.a1.get(2)); - } - } - - @Test - void toCollectionExtendedWithNulls() throws Exception { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("a1", ValueType.ARRAY); - builder.add("one"); - builder.add(ValueType.NULL); - builder.add("two"); - builder.close(); - } - builder.close(); - } - - final VPackSlice vpack = builder.slice(); - final TestEntityCollectionExtendedWithNulls entity = mapper.readValue(vpack.getBuffer(), - TestEntityCollectionExtendedWithNulls.class); - assertThat(entity).isNotNull(); - assertThat(entity.getA1()).isNotNull(); - assertThat(entity.getA1()).hasSize(3); - assertThat(entity.getA1()).contains("one", null, "two"); - } - - public static class TestEntityArrayInArrayInArray { - - private double[][][] a1; - - public double[][][] getA1() { - return a1; - } - - public void setA1(final double[][][] a1) { - this.a1 = a1; - } - - } - - @Test - void fromArrayInArrayInArray() throws JsonProcessingException { - final TestEntityArrayInArrayInArray entity = new TestEntityArrayInArrayInArray(); - entity.setA1(new double[][][]{{{1.5, 2.25}, {10.5, 20.25}}, {{100.5}, {200.25}}}); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice a1 = vpack.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.getLength()).isEqualTo(entity.a1.length); - for (int i = 0; i < a1.getLength(); i++) { - final VPackSlice at = a1.get(i); - assertThat(at.isArray()).isTrue(); - assertThat(at.getLength()).isEqualTo(entity.a1[i].length); - for (int j = 0; j < at.getLength(); j++) { - final VPackSlice atat = at.get(j); - assertThat(atat.isArray()).isTrue(); - assertThat(atat.getLength()).isEqualTo(entity.a1[i][j].length); - for (int k = 0; k < atat.getLength(); k++) { - final VPackSlice atatat = atat.get(k); - assertThat(atatat.isDouble()).isTrue(); - assertThat(atatat.getAsDouble()).isEqualTo(entity.a1[i][j][k]); - } - } - } - } - } - - @Test - void toArrayInArrayInArray() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("a1", ValueType.ARRAY); - builder.add(ValueType.ARRAY); - { - builder.add(ValueType.ARRAY); - builder.add(1.5); - builder.add(2.5); - builder.add(3.5); - builder.close(); - } - { - builder.add(ValueType.ARRAY); - builder.add(4.5); - builder.add(5.5); - builder.add(6.5); - builder.close(); - } - { - builder.add(ValueType.ARRAY); - builder.add(7.5); - builder.add(8.5); - builder.add(9.5); - builder.close(); - } - builder.close(); - builder.add(ValueType.ARRAY); - { - builder.add(ValueType.ARRAY); - builder.add(1.5); - builder.add(2.5); - builder.add(3.5); - builder.close(); - } - { - builder.add(ValueType.ARRAY); - builder.add(4.5); - builder.add(5.5); - builder.add(6.5); - builder.close(); - } - { - builder.add(ValueType.ARRAY); - builder.add(7.5); - builder.add(8.5); - builder.add(9.5); - builder.close(); - } - builder.close(); - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityArrayInArrayInArray entity = mapper.readValue(vpack.getBuffer(), - TestEntityArrayInArrayInArray.class); - assertThat(entity).isNotNull(); - assertThat(entity.a1.length).isEqualTo(2); - { - assertThat(entity.a1[0].length).isEqualTo(3); - assertThat(entity.a1[0][0]).hasSize(3); - assertThat(entity.a1[0][0][0]).isEqualTo(1.5); - assertThat(entity.a1[0][0][1]).isEqualTo(2.5); - assertThat(entity.a1[0][0][2]).isEqualTo(3.5); - assertThat(entity.a1[0][1]).hasSize(3); - assertThat(entity.a1[0][1][0]).isEqualTo(4.5); - assertThat(entity.a1[0][1][1]).isEqualTo(5.5); - assertThat(entity.a1[0][1][2]).isEqualTo(6.5); - assertThat(entity.a1[0][2]).hasSize(3); - assertThat(entity.a1[0][2][0]).isEqualTo(7.5); - assertThat(entity.a1[0][2][1]).isEqualTo(8.5); - assertThat(entity.a1[0][2][2]).isEqualTo(9.5); - } - { - assertThat(entity.a1[1].length).isEqualTo(3); - assertThat(entity.a1[1][0]).hasSize(3); - assertThat(entity.a1[1][0][0]).isEqualTo(1.5); - assertThat(entity.a1[1][0][1]).isEqualTo(2.5); - assertThat(entity.a1[1][0][2]).isEqualTo(3.5); - assertThat(entity.a1[1][1]).hasSize(3); - assertThat(entity.a1[1][1][0]).isEqualTo(4.5); - assertThat(entity.a1[1][1][1]).isEqualTo(5.5); - assertThat(entity.a1[1][1][2]).isEqualTo(6.5); - assertThat(entity.a1[1][2]).hasSize(3); - assertThat(entity.a1[1][2][0]).isEqualTo(7.5); - assertThat(entity.a1[1][2][1]).isEqualTo(8.5); - assertThat(entity.a1[1][2][2]).isEqualTo(9.5); - } - } - - public static class TestEntityObjectInArray { - private TestEntityString[] a1; - - public TestEntityString[] getA1() { - return a1; - } - - public void setA1(final TestEntityString[] a1) { - this.a1 = a1; - } - } - - @Test - void fromObjectInArray() throws JsonProcessingException { - final TestEntityObjectInArray entity = new TestEntityObjectInArray(); - { - final TestEntityString[] a1 = new TestEntityString[2]; - final TestEntityString s = new TestEntityString(); - s.setS("abc"); - a1[0] = s; - a1[1] = s; - entity.setA1(a1); - } - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice a1 = vpack.get("a1"); - assertThat(a1.isArray()).isTrue(); - assertThat(a1.getLength()).isEqualTo(2); - for (int i = 0; i < a1.getLength(); i++) { - final VPackSlice at = a1.get(i); - assertThat(at.isObject()).isTrue(); - final VPackSlice s = at.get("s"); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo("abc"); - } - } - } - - @Test - void toObjectInArray() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("a1", ValueType.ARRAY); - { - builder.add(ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - } - builder.close(); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityObjectInArray entity = mapper.readValue(vpack.getBuffer(), TestEntityObjectInArray.class); - assertThat(entity).isNotNull(); - assertThat(entity.a1).hasSize(1); - final TestEntityString st = entity.a1[0]; - assertThat(st).isNotNull(); - assertThat(st.s).isEqualTo("abc"); - } - - public static class TestEntityA { - private String a = "a"; - - public String getA() { - return a; - } - - public void setA(final String a) { - this.a = a; - } - } - - public static class TestEntityB extends TestEntityA { - private String b = "b"; - - public String getB() { - return b; - } - - public void setB(final String b) { - this.b = b; - } - } - - @Test - void fromInheritance() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityB())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(2); - { - final VPackSlice a = vpack.get("a"); - assertThat(a.isString()).isTrue(); - assertThat(a.getAsString()).isEqualTo("a"); - } - { - final VPackSlice b = vpack.get("b"); - assertThat(b.isString()).isTrue(); - assertThat(b.getAsString()).isEqualTo("b"); - } - } - - @Test - void toInheritance() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("a", "test"); - builder.add("b", "test"); - builder.close(); - } - final VPackSlice vpack = builder.slice(); - { - final TestEntityA entity = mapper.readValue(vpack.getBuffer(), TestEntityA.class); - assertThat(entity).isNotNull(); - assertThat(entity.getA()).isEqualTo("test"); - } - { - final TestEntityB entity = mapper.readValue(vpack.getBuffer(), TestEntityB.class); - assertThat(entity).isNotNull(); - assertThat(entity.getA()).isEqualTo("test"); - assertThat(entity.getB()).isEqualTo("test"); - } - } - - public static class TestEntityC { - private TestEntityD d; - - public TestEntityD getD() { - return d; - } - - public void setD(final TestEntityD d) { - this.d = d; - } - } - - protected interface TestEntityD { - String getD(); - - void setD(String d); - } - - public static class TestEntityDImpl implements TestEntityD { - private String d = "d"; - - @Override - public String getD() { - return d; - } - - @Override - public void setD(final String d) { - this.d = d; - } - } - - @Test - void fromInterface() throws JsonProcessingException { - final TestEntityC entity = new TestEntityC(); - entity.setD(new TestEntityDImpl()); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice d = vpack.get("d"); - assertThat(d.isObject()).isTrue(); - final VPackSlice dd = d.get("d"); - assertThat(dd.isString()).isTrue(); - assertThat(dd.getAsString()).isEqualTo("d"); - } - } - - @Test - void toInterface() { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("d", ValueType.OBJECT); - builder.add("d", "test"); - builder.close(); - builder.close(); - } - final VPackSlice slice = builder.slice(); - final VPack vPack = new VPack.Builder() - .registerInstanceCreator(TestEntityD.class, (VPackInstanceCreator) TestEntityDImpl::new).build(); - final TestEntityC entity = vPack.deserialize(slice, TestEntityC.class); - assertThat(entity).isNotNull(); - assertThat(entity.d).isNotNull(); - assertThat(entity.d.getD()).isEqualTo("test"); - } - - public static class TestEntityCollection { - private Collection c1 = new LinkedList<>(); - private List c2 = new ArrayList<>(); - private ArrayList c3 = new ArrayList<>(); - private Set c4 = new LinkedHashSet<>(); - private HashSet c5 = new HashSet<>(); - - public TestEntityCollection() { - super(); - } - - public Collection getC1() { - return c1; - } - - public void setC1(final Collection c1) { - this.c1 = c1; - } - - public List getC2() { - return c2; - } - - public void setC2(final List c2) { - this.c2 = c2; - } - - public ArrayList getC3() { - return c3; - } - - public void setC3(final ArrayList c3) { - this.c3 = c3; - } - - public Set getC4() { - return c4; - } - - public void setC4(final Set c4) { - this.c4 = c4; - } - - public HashSet getC5() { - return c5; - } - - public void setC5(final HashSet c5) { - this.c5 = c5; - } - } - - @Test - void fromCollection() throws JsonProcessingException { - final TestEntityCollection entity = new TestEntityCollection(); - { - entity.c1.add("test"); - entity.c2.add("test"); - entity.c3.add("test"); - entity.c4.add("test"); - entity.c5.add("test"); - } - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice c1 = vpack.get("c1"); - assertThat(c1.isArray()).isTrue(); - assertThat(c1.getLength()).isEqualTo(1); - assertThat(c1.get(0).getAsString()).isEqualTo("test"); - } - { - final VPackSlice c2 = vpack.get("c2"); - assertThat(c2.isArray()).isTrue(); - assertThat(c2.getLength()).isEqualTo(1); - assertThat(c2.get(0).getAsString()).isEqualTo("test"); - } - { - final VPackSlice c3 = vpack.get("c3"); - assertThat(c3.isArray()).isTrue(); - assertThat(c3.getLength()).isEqualTo(1); - assertThat(c3.get(0).getAsString()).isEqualTo("test"); - } - { - final VPackSlice c4 = vpack.get("c4"); - assertThat(c4.isArray()).isTrue(); - assertThat(c4.getLength()).isEqualTo(1); - assertThat(c4.get(0).getAsString()).isEqualTo("test"); - } - { - final VPackSlice c5 = vpack.get("c5"); - assertThat(c5.isArray()).isTrue(); - assertThat(c5.getLength()).isEqualTo(1); - assertThat(c5.get(0).getAsString()).isEqualTo("test"); - } - } - - @Test - void toCollection() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("c1", ValueType.ARRAY); - builder.add("test1"); - builder.add("test2"); - builder.close(); - } - { - builder.add("c2", ValueType.ARRAY); - builder.add("test1"); - builder.add("test2"); - builder.close(); - } - { - builder.add("c3", ValueType.ARRAY); - builder.add("test1"); - builder.add("test2"); - builder.close(); - } - { - builder.add("c4", ValueType.ARRAY); - builder.add("test1"); - builder.add("test2"); - builder.close(); - } - { - builder.add("c5", ValueType.ARRAY); - builder.add("test1"); - builder.add("test2"); - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityCollection entity = mapper.readValue(vpack.getBuffer(), TestEntityCollection.class); - assertThat(entity).isNotNull(); - { - checkCollection(entity.c1); - checkCollection(entity.c2); - checkCollection(entity.c3); - checkCollection(entity.c4); - checkCollection(entity.c5); - } - } - - private void checkCollection(final Collection col) { - assertThat(col).isNotNull(); - assertThat(col).hasSize(2); - for (final String next : col) { - assertThat("test1".equals(next) || "test2".equals(next)).isTrue(); - } - } - - public static class TestEntityCollectionWithObjects { - private Collection c1; - private Set c2; - - public Collection getC1() { - return c1; - } - - public void setC1(final Collection c1) { - this.c1 = c1; - } - - public Set getC2() { - return c2; - } - - public void setC2(final Set c2) { - this.c2 = c2; - } - } - - @Test - void fromCollectionWithObjects() throws JsonProcessingException { - final TestEntityCollectionWithObjects entity = new TestEntityCollectionWithObjects(); - { - final Collection c1 = new ArrayList<>(); - c1.add(new TestEntityString()); - c1.add(new TestEntityString()); - entity.setC1(c1); - final Set c2 = new HashSet<>(); - c2.add(new TestEntityArray()); - entity.setC2(c2); - } - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice c1 = vpack.get("c1"); - assertThat(c1.isArray()).isTrue(); - assertThat(c1.getLength()).isEqualTo(2); - assertThat(c1.get(0).isObject()).isTrue(); - assertThat(c1.get(1).isObject()).isTrue(); - { - final VPackSlice s = c1.get(0).get("s"); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo("test"); - } - } - { - final VPackSlice c2 = vpack.get("c2"); - assertThat(c2.isArray()).isTrue(); - assertThat(c2.getLength()).isEqualTo(1); - assertThat(c2.get(0).isObject()).isTrue(); - { - final VPackSlice a2 = c2.get(0).get("a2"); - assertThat(a2.isArray()).isTrue(); - assertThat(a2.getLength()).isEqualTo(5); - for (int i = 0; i < a2.getLength(); i++) { - final VPackSlice at = a2.get(i); - assertThat(at.isInteger()).isTrue(); - assertThat(at.getAsInt()).isEqualTo(i + 1); - } - } - } - } - - @Test - void toCollectionWithObjects() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("c1", ValueType.ARRAY); - builder.add(ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - builder.close(); - } - { - builder.add("c2", ValueType.ARRAY); - builder.add(ValueType.OBJECT); - builder.add("a2", ValueType.ARRAY); - for (int i = 0; i < 10; i++) { - builder.add(i); - } - builder.close(); - builder.close(); - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityCollectionWithObjects entity = mapper.readValue(vpack.getBuffer(), - TestEntityCollectionWithObjects.class); - assertThat(entity).isNotNull(); - { - assertThat(entity.c1).isNotNull(); - assertThat(entity.c1).hasSize(1); - assertThat(entity.c1.iterator().next().s).isEqualTo("abc"); - } - { - assertThat(entity.c2).isNotNull(); - assertThat(entity.c2).hasSize(1); - final int[] array = entity.c2.iterator().next().a2; - for (int i = 0; i < array.length; i++) { - assertThat(array[i]).isEqualTo(i); - } - } - } - - public static class TestEntityMap { - private Map m1; - private HashMap m2; - private Map m3; - - public Map getM1() { - return m1; - } - - public void setM1(final Map m1) { - this.m1 = m1; - } - - public HashMap getM2() { - return m2; - } - - public void setM2(final HashMap m2) { - this.m2 = m2; - } - - public Map getM3() { - return m3; - } - - public void setM3(final Map m3) { - this.m3 = m3; - } - } - - @Test - void fromMap() throws JsonProcessingException { - final TestEntityMap entity = new TestEntityMap(); - { - final Map m1 = new LinkedHashMap<>(); - m1.put("a", "b"); - m1.put("c", "d"); - entity.setM1(m1); - final HashMap m2 = new HashMap<>(); - m2.put(1, "a"); - m2.put(2, "b"); - entity.setM2(m2); - final Map m3 = new HashMap<>(); - final TestEntityString s = new TestEntityString(); - s.setS("abc"); - m3.put("a", s); - entity.setM3(m3); - } - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice m1 = vpack.get("m1"); - assertThat(m1.isObject()).isTrue(); - assertThat(m1.getLength()).isEqualTo(2); - { - final VPackSlice a = m1.get("a"); - assertThat(a.isString()).isTrue(); - assertThat(a.getAsString()).isEqualTo("b"); - } - { - final VPackSlice c = m1.get("c"); - assertThat(c.isString()).isTrue(); - assertThat(c.getAsString()).isEqualTo("d"); - } - } - { - final VPackSlice m2 = vpack.get("m2"); - assertThat(m2.isObject()).isTrue(); - assertThat(m2.getLength()).isEqualTo(2); - { - final VPackSlice one = m2.get("1"); - assertThat(one.isString()).isTrue(); - assertThat(one.getAsString()).isEqualTo("a"); - } - { - final VPackSlice two = m2.get("2"); - assertThat(two.isString()).isTrue(); - assertThat(two.getAsString()).isEqualTo("b"); - } - } - { - final VPackSlice m3 = vpack.get("m3"); - assertThat(m3.isObject()).isTrue(); - assertThat(m3.getLength()).isEqualTo(1); - final VPackSlice a = m3.get("a"); - assertThat(a.isObject()).isTrue(); - final VPackSlice s = a.get("s"); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo("abc"); - } - } - - @Test - void toMap() throws IOException { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - { - builder.add("m1", ValueType.OBJECT); - builder.add("a", "a"); - builder.add("b", "b"); - builder.close(); - } - { - builder.add("m2", ValueType.OBJECT); - builder.add("1", "a"); - builder.add("-1", "a"); - builder.close(); - } - { - builder.add("m3", ValueType.OBJECT); - builder.add("a", ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - builder.close(); - } - builder.close(); - } - final VPackSlice vpack = builder.slice(); - final TestEntityMap entity = mapper.readValue(vpack.getBuffer(), TestEntityMap.class); - assertThat(entity).isNotNull(); - { - assertThat(entity.m1).isNotNull(); - assertThat(entity.m1).hasSize(2); - final String a = entity.m1.get("a"); - assertThat(a).isNotNull(); - assertThat(a).isEqualTo("a"); - final String b = entity.m1.get("b"); - assertThat(b).isNotNull(); - assertThat(b).isEqualTo("b"); - } - { - assertThat(entity.m2).isNotNull(); - assertThat(entity.m2).hasSize(2); - final String one = entity.m2.get(1); - assertThat(one).isNotNull(); - assertThat(one).isEqualTo("a"); - final String oneNegative = entity.m2.get(-1); - assertThat(oneNegative).isNotNull(); - assertThat(oneNegative).isEqualTo("a"); - } - { - assertThat(entity.m3).isNotNull(); - assertThat(entity.m3).hasSize(1); - final TestEntityString a = entity.m3.get("a"); - assertThat(a).isNotNull(); - assertThat(a.s).isEqualTo("abc"); - } - } - - public static class TestEntityMapStringableKey { - private Map m1; - private Map m2; - private Map m3; - private Map m4; - private Map m5; - private Map m6; - private Map m7; - private Map m8; - private Map m9; - private Map m10; - private Map m11; - - public Map getM1() { - return m1; - } - - public void setM1(final Map m1) { - this.m1 = m1; - } - - public Map getM2() { - return m2; - } - - public void setM2(final Map m2) { - this.m2 = m2; - } - - public Map getM3() { - return m3; - } - - public void setM3(final Map m3) { - this.m3 = m3; - } - - public Map getM4() { - return m4; - } - - public void setM4(final Map m4) { - this.m4 = m4; - } - - public Map getM5() { - return m5; - } - - public void setM5(final Map m5) { - this.m5 = m5; - } - - public Map getM6() { - return m6; - } - - public void setM6(final Map m6) { - this.m6 = m6; - } - - public Map getM7() { - return m7; - } - - public void setM7(final Map m7) { - this.m7 = m7; - } - - public Map getM8() { - return m8; - } - - public void setM8(final Map m8) { - this.m8 = m8; - } - - public Map getM9() { - return m9; - } - - public void setM9(final Map m9) { - this.m9 = m9; - } - - public Map getM10() { - return m10; - } - - public void setM10(final Map m10) { - this.m10 = m10; - } - - public Map getM11() { - return m11; - } - - public void setM11(final Map m11) { - this.m11 = m11; - } - - } - - @Test - void fromMapStringableKey() throws JsonProcessingException { - final TestEntityMapStringableKey entity = new TestEntityMapStringableKey(); - final String value = "test"; - { - final Map m1 = new HashMap<>(); - m1.put(true, value); - m1.put(false, value); - entity.setM1(m1); - } - { - final Map m2 = new HashMap<>(); - m2.put(1, value); - m2.put(2, value); - entity.setM2(m2); - } - { - final Map m3 = new HashMap<>(); - m3.put(1L, value); - m3.put(2L, value); - entity.setM3(m3); - } - { - final Map m4 = new HashMap<>(); - m4.put(1.5F, value); - m4.put(2.25F, value); - entity.setM4(m4); - } - { - final Map m5 = new HashMap<>(); - m5.put(Short.valueOf("1"), value); - m5.put(Short.valueOf("2"), value); - entity.setM5(m5); - } - { - final Map m6 = new HashMap<>(); - m6.put(1.5, value); - m6.put(2.25, value); - entity.setM6(m6); - } - { - final Map m7 = new HashMap<>(); - m7.put(1.5, value); - m7.put(1L, value); - entity.setM7(m7); - } - { - final Map m8 = new HashMap<>(); - m8.put(new BigInteger("1"), value); - m8.put(new BigInteger("2"), value); - entity.setM8(m8); - } - { - final Map m9 = new HashMap<>(); - m9.put(new BigDecimal("1.5"), value); - m9.put(new BigDecimal("2.25"), value); - entity.setM9(m9); - } - { - final Map m10 = new HashMap<>(); - m10.put('1', value); - m10.put('a', value); - entity.setM10(m10); - } - { - final Map m11 = new HashMap<>(); - m11.put(TestEnum.A, value); - m11.put(TestEnum.B, value); - entity.setM11(m11); - } - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - final VPackSlice m1 = vpack.get("m1"); - assertThat(m1.isObject()).isTrue(); - assertThat(m1.getLength()).isEqualTo(2); - checkMapAttribute(m1.get("true")); - checkMapAttribute(m1.get("false")); - } - { - final VPackSlice m2 = vpack.get("m2"); - assertThat(m2.isObject()).isTrue(); - assertThat(m2.getLength()).isEqualTo(2); - checkMapAttribute(m2.get("1")); - checkMapAttribute(m2.get("2")); - } - { - final VPackSlice m3 = vpack.get("m3"); - assertThat(m3.isObject()).isTrue(); - assertThat(m3.getLength()).isEqualTo(2); - checkMapAttribute(m3.get("1")); - checkMapAttribute(m3.get("2")); - } - { - final VPackSlice m4 = vpack.get("m4"); - assertThat(m4.isObject()).isTrue(); - assertThat(m4.getLength()).isEqualTo(2); - checkMapAttribute(m4.get("1.5")); - checkMapAttribute(m4.get("2.25")); - } - { - final VPackSlice m5 = vpack.get("m5"); - assertThat(m5.isObject()).isTrue(); - assertThat(m5.getLength()).isEqualTo(2); - checkMapAttribute(m5.get("1")); - checkMapAttribute(m5.get("2")); - } - { - final VPackSlice m6 = vpack.get("m6"); - assertThat(m6.isObject()).isTrue(); - assertThat(m6.getLength()).isEqualTo(2); - checkMapAttribute(m6.get("1.5")); - checkMapAttribute(m6.get("2.25")); - } - { - final VPackSlice m7 = vpack.get("m7"); - assertThat(m7.isObject()).isTrue(); - assertThat(m7.getLength()).isEqualTo(2); - checkMapAttribute(m7.get("1.5")); - checkMapAttribute(m7.get("1")); - } - { - final VPackSlice m8 = vpack.get("m8"); - assertThat(m8.isObject()).isTrue(); - assertThat(m8.getLength()).isEqualTo(2); - checkMapAttribute(m8.get("1")); - checkMapAttribute(m8.get("2")); - } - { - final VPackSlice m9 = vpack.get("m9"); - assertThat(m9.isObject()).isTrue(); - assertThat(m9.getLength()).isEqualTo(2); - checkMapAttribute(m9.get("1.5")); - checkMapAttribute(m9.get("2.25")); - } - { - final VPackSlice m10 = vpack.get("m10"); - assertThat(m10.isObject()).isTrue(); - assertThat(m10.getLength()).isEqualTo(2); - checkMapAttribute(m10.get("1")); - checkMapAttribute(m10.get("a")); - } - { - final VPackSlice m11 = vpack.get("m11"); - assertThat(m11.isObject()).isTrue(); - assertThat(m11.getLength()).isEqualTo(2); - checkMapAttribute(m11.get(TestEnum.A.name())); - checkMapAttribute(m11.get(TestEnum.B.name())); - } - } - - @Test - void toMapSringableKey() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - { - builder.add("m1", ValueType.OBJECT); - builder.add("true", "test"); - builder.add("false", "test"); - builder.close(); - } - { - builder.add("m2", ValueType.OBJECT); - builder.add("1", "test"); - builder.add("2", "test"); - builder.close(); - } - { - builder.add("m3", ValueType.OBJECT); - builder.add("1", "test"); - builder.add("2", "test"); - builder.close(); - } - { - builder.add("m4", ValueType.OBJECT); - builder.add("1.5", "test"); - builder.add("2.25", "test"); - builder.close(); - } - { - builder.add("m5", ValueType.OBJECT); - builder.add("1", "test"); - builder.add("2", "test"); - builder.close(); - } - { - builder.add("m6", ValueType.OBJECT); - builder.add("1.5", "test"); - builder.add("2.25", "test"); - builder.close(); - } - { - builder.add("m7", ValueType.OBJECT); - builder.add("1.5", "test"); - builder.add("1", "test"); - builder.close(); - } - { - builder.add("m8", ValueType.OBJECT); - builder.add("1", "test"); - builder.add("2", "test"); - builder.close(); - } - { - builder.add("m9", ValueType.OBJECT); - builder.add("1.5", "test"); - builder.add("2.25", "test"); - builder.close(); - } - { - builder.add("m10", ValueType.OBJECT); - builder.add("1", "test"); - builder.add("a", "test"); - builder.close(); - } - { - builder.add("m11", ValueType.OBJECT); - builder.add(TestEnum.A.name(), "test"); - builder.add(TestEnum.B.name(), "test"); - builder.close(); - } - builder.close(); - final TestEntityMapStringableKey entity = new VPack.Builder().build().deserialize(builder.slice(), - TestEntityMapStringableKey.class); - { - assertThat(entity.m1).hasSize(2); - checkMapAttribute(entity.m1.get(true)); - checkMapAttribute(entity.m1.get(false)); - } - { - assertThat(entity.m2).hasSize(2); - checkMapAttribute(entity.m2.get(1)); - checkMapAttribute(entity.m2.get(2)); - } - { - assertThat(entity.m3).hasSize(2); - checkMapAttribute(entity.m3.get(1L)); - checkMapAttribute(entity.m3.get(2L)); - } - { - assertThat(entity.m4).hasSize(2); - checkMapAttribute(entity.m4.get(1.5F)); - checkMapAttribute(entity.m4.get(2.25F)); - } - { - assertThat(entity.m5).hasSize(2); - checkMapAttribute(entity.m5.get(Short.valueOf("1"))); - checkMapAttribute(entity.m5.get(Short.valueOf("2"))); - } - { - assertThat(entity.m6).hasSize(2); - checkMapAttribute(entity.m6.get(1.5)); - checkMapAttribute(entity.m6.get(2.25)); - } - { - assertThat(entity.m7).hasSize(2); - checkMapAttribute(entity.m7.get(1.5)); - checkMapAttribute(entity.m7.get((double) 1L)); - } - { - assertThat(entity.m8).hasSize(2); - checkMapAttribute(entity.m8.get(new BigInteger("1"))); - checkMapAttribute(entity.m8.get(new BigInteger("2"))); - } - { - assertThat(entity.m9).hasSize(2); - checkMapAttribute(entity.m9.get(new BigDecimal("1.5"))); - checkMapAttribute(entity.m9.get(new BigDecimal("2.25"))); - } - { - assertThat(entity.m10).hasSize(2); - checkMapAttribute(entity.m10.get('1')); - checkMapAttribute(entity.m10.get('a')); - } - { - assertThat(entity.m11).hasSize(2); - checkMapAttribute(entity.m11.get(TestEnum.A)); - checkMapAttribute(entity.m11.get(TestEnum.B)); - } - } - - private void checkMapAttribute(final VPackSlice attr) { - assertThat(attr.isString()).isTrue(); - assertThat(attr.getAsString()).isEqualTo("test"); - } - - private void checkMapAttribute(final String attr) { - assertThat(attr).isEqualTo("test"); - } - - public static class TestEntityMapWithObjectKey { - private Map m1; - private Map m2; - - public Map getM1() { - return m1; - } - - public void setM1(final Map m1) { - this.m1 = m1; - } - - public Map getM2() { - return m2; - } - - public void setM2(final Map m2) { - this.m2 = m2; - } - } - - @Test - void toMapWithObjectKey() { - final int size = 2; - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - { - builder.add("m1", ValueType.ARRAY); - for (int i = 0; i < size; i++) { - builder.add(ValueType.OBJECT); - { - builder.add("key", ValueType.OBJECT); - builder.add("l1", 5L); - builder.close(); - } - { - builder.add("value", ValueType.OBJECT); - builder.add("c1", ValueType.ARRAY); - builder.add("test"); - builder.close(); - builder.close(); - } - builder.close(); - } - builder.close(); - } - { - builder.add("m2", ValueType.ARRAY); - for (int i = 0; i < size; i++) { - builder.add(ValueType.OBJECT); - { - builder.add("key", ValueType.OBJECT); - builder.add("l1", 5L); - builder.close(); - } - { - builder.add("value", "test"); - } - builder.close(); - } - builder.close(); - } - builder.close(); - final TestEntityMapWithObjectKey entity = new VPack.Builder().build().deserialize(builder.slice(), - TestEntityMapWithObjectKey.class); - assertThat(entity).isNotNull(); - { - assertThat(entity.m1).isNotNull(); - assertThat(entity.m1).hasSize(size); - for (final Entry entry : entity.m1.entrySet()) { - assertThat(entry.getKey().l1).isEqualTo(5L); - assertThat(entry.getValue().c1).hasSize(1); - assertThat(entry.getValue().c1.iterator().next()).isEqualTo("test"); - } - } - { - assertThat(entity.m2).isNotNull(); - assertThat(entity.m2).hasSize(2); - for (final Entry entry : entity.m2.entrySet()) { - assertThat(entry.getKey().l1).isEqualTo(5L); - assertThat(entry.getValue()).isEqualTo("test"); - } - } - } - - public static class TestEntityEmpty { - - } - - @Test - void fromEmptyObject() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityEmpty())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.getLength()).isZero(); - } - - @Test - void toEmptyObject() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.close(); - final TestEntityEmpty entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityEmpty.class); - assertThat(entity).isNotNull(); - } - - public static class TestEntityEmptyMap { - private Map m; - - public Map getM() { - return m; - } - - public void setM(final Map m) { - this.m = m; - } - } - - @Test - void fromEmptyMap() throws JsonProcessingException { - final TestEntityEmptyMap entity = new TestEntityEmptyMap(); - entity.setM(new HashMap<>()); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(1); - final VPackSlice m = vpack.get("m"); - assertThat(m.isObject()).isTrue(); - assertThat(m.getLength()).isZero(); - } - - @Test - void toEmptyMap() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("m", ValueType.OBJECT); - builder.close(); - builder.close(); - final TestEntityEmptyMap entity = new VPack.Builder().build().deserialize(builder.slice(), - TestEntityEmptyMap.class); - assertThat(entity).isNotNull(); - assertThat(entity.m).isNotNull(); - assertThat(entity.m).isEmpty(); - } - - public static class TestEntityBaseAttributes { - private String _key = "test1"; - private String _rev = "test2"; - private String _id = "test3"; - private String _from = "test4"; - private String _to = "test5"; - - public String get_key() { - return _key; - } - - public void set_key(final String _key) { - this._key = _key; - } - - public String get_rev() { - return _rev; - } - - public void set_rev(final String _rev) { - this._rev = _rev; - } - - public String get_id() { - return _id; - } - - public void set_id(final String _id) { - this._id = _id; - } - - public String get_from() { - return _from; - } - - public void set_from(final String _from) { - this._from = _from; - } - - public String get_to() { - return _to; - } - - public void set_to(final String _to) { - this._to = _to; - } - - } - - @Test - void fromObjectWithAttributeAdapter() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityBaseAttributes())); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(5); - { - final VPackSlice key = vpack.get("_key"); - assertThat(key.isString()).isTrue(); - assertThat(key.getAsString()).isEqualTo("test1"); - } - { - final VPackSlice rev = vpack.get("_rev"); - assertThat(rev.isString()).isTrue(); - assertThat(rev.getAsString()).isEqualTo("test2"); - } - { - final VPackSlice id = vpack.get("_id"); - assertThat(id.isString()).isTrue(); - assertThat(id.getAsString()).isEqualTo("test3"); - } - { - final VPackSlice from = vpack.get("_from"); - assertThat(from.isString()).isTrue(); - assertThat(from.getAsString()).isEqualTo("test4"); - } - { - final VPackSlice to = vpack.get("_to"); - assertThat(to.isString()).isTrue(); - assertThat(to.getAsString()).isEqualTo("test5"); - } - } - - @Test - void toObjectWithAttributeAdapter() { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("_key", "a"); - builder.add("_rev", "b"); - builder.add("_id", "c"); - builder.add("_from", "d"); - builder.add("_to", "e"); - builder.close(); - } - final TestEntityBaseAttributes entity = new VPack.Builder().build().deserialize(builder.slice(), - TestEntityBaseAttributes.class); - assertThat(entity).isNotNull(); - assertThat(entity._key).isEqualTo("a"); - assertThat(entity._rev).isEqualTo("b"); - assertThat(entity._id).isEqualTo("c"); - assertThat(entity._from).isEqualTo("d"); - assertThat(entity._to).isEqualTo("e"); - } - - @Test - void fromMapWithAttributeAdapter() throws JsonProcessingException { - final TestEntityMap entity = new TestEntityMap(); - { - final Map m1 = new HashMap<>(); - m1.put("_key", "test1"); - m1.put("_rev", "test2"); - m1.put("_id", "test3"); - m1.put("_from", "test4"); - m1.put("_to", "test5"); - entity.setM1(m1); - } - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice m1 = vpack.get("m1"); - assertThat(m1.isObject()).isTrue(); - assertThat(m1.getLength()).isEqualTo(5); - { - final VPackSlice key = m1.get("_key"); - assertThat(key.isString()).isTrue(); - assertThat(key.getAsString()).isEqualTo("test1"); - } - { - final VPackSlice rev = m1.get("_rev"); - assertThat(rev.isString()).isTrue(); - assertThat(rev.getAsString()).isEqualTo("test2"); - } - { - final VPackSlice id = m1.get("_id"); - assertThat(id.isString()).isTrue(); - assertThat(id.getAsString()).isEqualTo("test3"); - } - { - final VPackSlice from = m1.get("_from"); - assertThat(from.isString()).isTrue(); - assertThat(from.getAsString()).isEqualTo("test4"); - } - { - final VPackSlice to = m1.get("_to"); - assertThat(to.isString()).isTrue(); - assertThat(to.getAsString()).isEqualTo("test5"); - } - } - - @Test - void toMapWithAttributeAdapter() { - final VPackBuilder builder = new VPackBuilder(); - { - builder.add(ValueType.OBJECT); - builder.add("m1", ValueType.OBJECT); - builder.add("_key", "a"); - builder.add("_rev", "b"); - builder.add("_id", "c"); - builder.add("_from", "d"); - builder.add("_to", "e"); - builder.close(); - builder.close(); - } - final TestEntityMap entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityMap.class); - assertThat(entity).isNotNull(); - assertThat(entity.m1).hasSize(5); - } - - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - private @interface CustomFilterAnnotation { - boolean serialize() - - default true; - - boolean deserialize() default true; - } - - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - private @interface CustomNamingAnnotation { - String name(); - } - - private static class CustomAnEntity { - @CustomFilterAnnotation(serialize = false) - private String a = null; - @CustomFilterAnnotation(deserialize = false) - private String b = null; - @CustomNamingAnnotation(name = "d") - @CustomFilterAnnotation(deserialize = false) - private String c = null; - - CustomAnEntity() { - super(); - } - } - - @Test - void fromCutsomAnnotation() { - final CustomAnEntity entity = new CustomAnEntity(); - entity.a = "1"; - entity.b = "2"; - entity.c = "3"; - final VPackSlice vpack = new VPack.Builder().annotationFieldFilter(CustomFilterAnnotation.class, - new VPackAnnotationFieldFilter() { - - @Override - public boolean serialize(final CustomFilterAnnotation annotation) { - return annotation.serialize(); - } - - @Override - public boolean deserialize(final CustomFilterAnnotation annotation) { - return annotation.deserialize(); - } - }).annotationFieldNaming(CustomNamingAnnotation.class, - CustomNamingAnnotation::name).build().serialize(entity); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.get("a").isNone()).isTrue(); - assertThat(vpack.get("b").isString()).isTrue(); - assertThat(vpack.get("b").getAsString()).isEqualTo("2"); - assertThat(vpack.get("c").isNone()).isTrue(); - assertThat(vpack.get("d").isString()).isTrue(); - assertThat(vpack.get("d").getAsString()).isEqualTo("3"); - } - - @Test - void directFromCollection() throws JsonProcessingException { - final Collection list = new ArrayList<>(); - list.add("test"); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(list)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isArray()).isTrue(); - assertThat(vpack.size()).isEqualTo(1); - final VPackSlice test = vpack.get(0); - assertThat(test.isString()).isTrue(); - assertThat(test.getAsString()).isEqualTo("test"); - } - - @Test - void directFromCollectionWithType() throws JsonProcessingException { - final Collection list = new ArrayList<>(); - list.add(new TestEntityString()); - list.add(new TestEntityString()); - - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(list)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isArray()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(list.size()); - for (int i = 0; i < list.size(); i++) { - final VPackSlice entry = vpack.get(i); - assertThat(entry.isObject()).isTrue(); - assertThat(entry.getLength()).isEqualTo(3); - final VPackSlice s = entry.get("s"); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo("test"); - } - } - - @Test - void directToCollection() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.ARRAY); - builder.add(ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - builder.close(); - final List list = new VPack.Builder().build().deserialize(builder.slice(), - new Type>() { - }.getType()); - assertThat(list).hasSize(1); - final TestEntityString entry = list.get(0); - assertThat(entry.s).isEqualTo("abc"); - } - - @Test - void directFromStringMap() throws JsonProcessingException { - final Map map = new HashMap<>(); - map.put("a", new TestEntityString()); - map.put("b", new TestEntityString()); - - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(map)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(2); - final VPackSlice a = vpack.get("a"); - checkStringEntity(a); - } - - @Test - void directToStringMap() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("a", ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - builder.close(); - final Map map = new VPack.Builder().build().deserialize(builder.slice(), - new Type>() { - }.getType()); - assertThat(map).hasSize(1); - final TestEntityString a = map.get("a"); - assertThat(a).isNotNull(); - assertThat(a.s).isEqualTo("abc"); - } - - @Test - void directFromMap() throws JsonProcessingException { - final Map map = new HashMap<>(); - final TestEntityA entity = new TestEntityA(); - entity.a = "test"; - map.put("test", entity); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(map)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice test = vpack.get("test"); - assertThat(test.isObject()).isTrue(); - final VPackSlice a = test.get("a"); - assertThat(a.isString()).isTrue(); - assertThat(a.getAsString()).isEqualTo("test"); - } - - @Test - void directFromMapWithinMap() throws JsonProcessingException { - final Map map = new HashMap<>(); - final Map map2 = new HashMap<>(); - map2.put("b", "test"); - map.put("a", map2); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(map)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.size()).isEqualTo(1); - final VPackSlice a = vpack.get("a"); - assertThat(a.isObject()).isTrue(); - assertThat(a.size()).isEqualTo(1); - final VPackSlice b = a.get("b"); - assertThat(b.isString()).isTrue(); - assertThat(b.getAsString()).isEqualTo("test"); - } - - private void checkStringEntity(final VPackSlice vpack) { - final TestEntityString expected = new TestEntityString(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(3); - final VPackSlice s = vpack.get("s"); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo(expected.s); - final VPackSlice c1 = vpack.get("c1"); - assertThat(c1.isString()).isTrue(); - assertThat(new Character(c1.getAsChar())).isEqualTo(expected.c1); - final VPackSlice c2 = vpack.get("c2"); - assertThat(c2.isString()).isTrue(); - assertThat(c2.getAsChar()).isEqualTo(expected.c2); - } - - @Test - void directToObjectMap() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.ARRAY); - builder.add(ValueType.OBJECT); - builder.add("key", ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - builder.add("value", ValueType.OBJECT); - builder.add("s", "abc"); - builder.close(); - builder.close(); - builder.close(); - final Map map = new VPack.Builder().build().deserialize(builder.slice(), - new Type>() { - }.getType()); - assertThat(map).hasSize(1); - for (final Entry entry : map.entrySet()) { - assertThat(entry.getKey().s).isEqualTo("abc"); - assertThat(entry.getValue().s).isEqualTo("abc"); - } - } - - @SuppressWarnings("unchecked") - @Test - void directToMapWithinMap() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("a", ValueType.OBJECT); - builder.add("b", "test"); - builder.add("c", true); - builder.add("d", 1L); - builder.add("e", 1.5); - final Date date = new Date(); - builder.add("f", date); - builder.add("g", ValueType.ARRAY); - builder.close(); - builder.close(); - builder.close(); - final Map map = new VPack.Builder().build().deserialize(builder.slice(), Map.class); - assertThat(map).hasSize(1); - final Object a = map.get("a"); - assertThat(Map.class.isAssignableFrom(a.getClass())).isTrue(); - final Map mapA = (Map) a; - assertThat(mapA).hasSize(6); - final Object b = mapA.get("b"); - assertThat(String.class.isAssignableFrom(b.getClass())).isTrue(); - assertThat(b).hasToString("test"); - final Object c = mapA.get("c"); - assertThat(Boolean.class.isAssignableFrom(c.getClass())).isTrue(); - assertThat((Boolean) c).isTrue(); - final Object d = mapA.get("d"); - assertThat(Number.class.isAssignableFrom(d.getClass())).isTrue(); - assertThat(((Number) d).longValue()).isEqualTo(1L); - final Object e = mapA.get("e"); - assertThat(Double.class.isAssignableFrom(e.getClass())).isTrue(); - assertThat((Double) e).isEqualTo(1.5); - final Object f = mapA.get("f"); - assertThat(Date.class.isAssignableFrom(f.getClass())).isTrue(); - assertThat((Date) f).isEqualTo(date); - final Object g = mapA.get("g"); - assertThat(Collection.class.isAssignableFrom(g.getClass())).isTrue(); - assertThat(List.class.isAssignableFrom(g.getClass())).isTrue(); - } - - @Test - void dontSerializeNullValues() { - final VPack serializer = new VPack.Builder().serializeNullValues(false).build(); - final TestEntityString entity = new TestEntityString(); - entity.setS(null); - final VPackSlice vpack = serializer.serialize(entity); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice s = vpack.get("s"); - assertThat(s.isNone()).isTrue(); - } - - @Test - void serializeNullValue() { - final VPack serializer = new VPack.Builder().serializeNullValues(true).build(); - final TestEntityString entity = new TestEntityString(); - entity.setS(null); - final VPackSlice vpack = serializer.serialize(entity); - assertThat(vpack).isNotNull(); - final VPackSlice s = vpack.get("s"); - assertThat(s.isNull()).isTrue(); - } - - @Test - void toNullValue() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("s", ValueType.NULL); - builder.close(); - final TestEntityString entity = new VPack.Builder().build().deserialize(builder.slice(), - TestEntityString.class); - assertThat(entity).isNotNull(); - assertThat(entity.s).isNull(); - assertThat(entity.c1).isNotNull(); - assertThat(entity.c2).isNotNull(); - } - - @Test - void toSimpleString() { - final VPackBuilder builder = new VPackBuilder(); - builder.add("test"); - final String s = new VPack.Builder().build().deserialize(builder.slice(), String.class); - assertThat(s).isEqualTo("test"); - } - - @Test - void fromSimpleString() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes("test")); - assertThat(vpack).isNotNull(); - assertThat(vpack.isString()).isTrue(); - assertThat(vpack.getAsString()).isEqualTo("test"); - } - - public static class TestEntityTyped { - private T e; - } - - @Test - void fromStringTypedEntity() throws JsonProcessingException { - final TestEntityTyped entity = new TestEntityTyped<>(); - entity.e = "test"; - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice e = vpack.get("e"); - assertThat(e).isNotNull(); - assertThat(e.isString()).isTrue(); - assertThat(e.getAsString()).isEqualTo("test"); - } - - @Test - void fromObjectTypedEntity() throws JsonProcessingException { - final TestEntityTyped entity = new TestEntityTyped<>(); - entity.e = new TestEntityString(); - entity.e.s = "test2"; - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice e = vpack.get("e"); - assertThat(e).isNotNull(); - assertThat(e.isObject()).isTrue(); - final VPackSlice s = e.get("s"); - assertThat(s).isNotNull(); - assertThat(s.isString()).isTrue(); - assertThat(s.getAsString()).isEqualTo("test2"); - } - - @Test - void fromTypedTypedEntity() throws JsonProcessingException { - final TestEntityTyped> entity = new TestEntityTyped<>(); - entity.e = new TestEntityTyped<>(); - entity.e.e = "test"; - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice e = vpack.get("e"); - assertThat(e).isNotNull(); - assertThat(e.isObject()).isTrue(); - final VPackSlice e2 = e.get("e"); - assertThat(e2).isNotNull(); - assertThat(e2.isString()).isTrue(); - assertThat(e2.getAsString()).isEqualTo("test"); - } - - @Test - void fieldNamingStrategySerialize() { - final VPackSlice vpack = new VPack.Builder().fieldNamingStrategy(field -> "bla").build().serialize(new TestEntityA()); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - final VPackSlice bla = vpack.get("bla"); - assertThat(bla.isString()).isTrue(); - assertThat(bla.getAsString()).isEqualTo("a"); - } - - @Test - void fieldNamingStrategyDeserialize() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("bla", "test"); - builder.close(); - final TestEntityA entity = new VPack.Builder().fieldNamingStrategy(field -> "bla").build().deserialize(builder.slice(), TestEntityA.class); - assertThat(entity).isNotNull(); - assertThat(entity.a).isEqualTo("test"); - } - - @Test - void serializeVPack() throws JsonProcessingException { - final VPackBuilder builder = new VPackBuilder(); - builder.add("test"); - final VPackSlice slice = builder.slice(); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(slice)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isString()).isTrue(); - assertThat(vpack.getAsString()).isEqualTo("test"); - } - - @Test - void deserializeVPack() { - final VPackBuilder builder = new VPackBuilder(); - builder.add("test"); - final VPackSlice slice = builder.slice(); - final VPackSlice vpack = new VPack.Builder().build().deserialize(slice, slice.getClass()); - assertThat(vpack).isNotNull(); - assertThat(vpack.isString()).isTrue(); - assertThat(vpack.getAsString()).isEqualTo("test"); - } - - public static class TestEntityDate { - private java.util.Date utilDate = new Date(1474988621); - private java.sql.Date sqlDate = new java.sql.Date(1474988621); - private java.sql.Timestamp timestamp = new java.sql.Timestamp(1474988621); - - public java.util.Date getUtilDate() { - return utilDate; - } - - public void setUtilDate(final java.util.Date utilDate) { - this.utilDate = utilDate; - } - - public java.sql.Date getSqlDate() { - return sqlDate; - } - - public void setSqlDate(final java.sql.Date sqlDate) { - this.sqlDate = sqlDate; - } - - public java.sql.Timestamp getTimestamp() { - return timestamp; - } - - public void setTimestamp(final java.sql.Timestamp timestamp) { - this.timestamp = timestamp; - } - - } - - @Test - void fromDate() throws JsonProcessingException { - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(new TestEntityDate())); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - { - assertThat(vpack.get("utilDate").isString()).isTrue(); - assertThat(vpack.get("utilDate").getAsString()).isEqualTo(DATE_FORMAT.format(new Date(1474988621))); - } - { - assertThat(vpack.get("sqlDate").isString()).isTrue(); - assertThat(vpack.get("sqlDate").getAsString()).isEqualTo(DATE_FORMAT.format(new java.sql.Date(1474988621))); - } - { - assertThat(vpack.get("timestamp").isString()).isTrue(); - assertThat(vpack.get("timestamp").getAsString()).isEqualTo(DATE_FORMAT.format(new java.sql.Timestamp(1474988621))); - } - } - - @Test - void toDate() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("utilDate", new Date(1475062216)); - builder.add("sqlDate", new java.sql.Date(1475062216)); - builder.add("timestamp", new java.sql.Timestamp(1475062216)); - builder.close(); - - final TestEntityDate entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityDate.class); - assertThat(entity).isNotNull(); - assertThat(entity.utilDate).isEqualTo(new Date(1475062216)); - assertThat(entity.sqlDate).isEqualTo(new java.sql.Date(1475062216)); - assertThat(entity.timestamp).isEqualTo(new java.sql.Timestamp(1475062216)); - } - - @Test - void toDateFromString() { - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("utilDate", DATE_FORMAT.format(new Date(1475062216))); - builder.add("sqlDate", DATE_FORMAT.format(new java.sql.Date(1475062216))); - builder.add("timestamp", DATE_FORMAT.format(new java.sql.Timestamp(1475062216))); - builder.close(); - - final TestEntityDate entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityDate.class); - assertThat(entity).isNotNull(); - assertThat(entity.utilDate).isEqualTo(new Date(1475062216)); - assertThat(entity.sqlDate).isEqualTo(new java.sql.Date(1475062216)); - assertThat(entity.timestamp).isEqualTo(new java.sql.Timestamp(1475062216)); - } - - public static class TestEntityUUID { - private UUID uuid; - - UUID getUuid() { - return uuid; - } - - void setUuid(final UUID uuid) { - this.uuid = uuid; - } - } - - @Test - void fromUUID() throws IOException { - final TestEntityUUID entity = new TestEntityUUID(); - entity.setUuid(UUID.randomUUID()); - byte[] bytes = mapper.writeValueAsBytes(entity); - final VPackSlice vpack = new VPackSlice(bytes); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - - final VPackSlice uuid = vpack.get("uuid"); - assertThat(uuid.isString()).isTrue(); - assertThat(uuid.getAsString()).isEqualTo(entity.getUuid().toString()); - assertThat(mapper.readValue(bytes, TestEntityUUID.class).getUuid()).isEqualTo(entity.getUuid()); - } - - @Test - void toUUID() { - final UUID uuid = UUID.randomUUID(); - final VPackBuilder builder = new VPackBuilder(); - builder.add(ValueType.OBJECT); - builder.add("uuid", uuid.toString()); - builder.close(); - - final TestEntityUUID entity = new VPack.Builder().build().deserialize(builder.slice(), TestEntityUUID.class); - assertThat(entity).isNotNull(); - assertThat(entity.uuid).isEqualTo(uuid); - } - - @Test - void uuid() { - final TestEntityUUID entity = new TestEntityUUID(); - entity.setUuid(UUID.randomUUID()); - final VPack vpacker = new VPack.Builder().build(); - final VPackSlice vpack = vpacker.serialize(entity); - final TestEntityUUID entity2 = vpacker.deserialize(vpack, TestEntityUUID.class); - assertThat(entity2).isNotNull(); - assertThat(entity2.getUuid()).isEqualTo(entity.getUuid()); - } - - private static class BinaryEntity { - private byte[] foo; - - BinaryEntity() { - super(); - } - } - - @Test - void fromBinary() throws JsonProcessingException { - final BinaryEntity entity = new BinaryEntity(); - entity.foo = "bar".getBytes(); - final VPackSlice vpack = new VPackSlice(mapper.writeValueAsBytes(entity)); - assertThat(vpack).isNotNull(); - assertThat(vpack.isObject()).isTrue(); - assertThat(vpack.get("foo").isString()).isTrue(); - assertThat(vpack.get("foo").getAsString()).isEqualTo(Base64.getEncoder().encodeToString(entity.foo)); - } - - @Test - void toBinary() throws IOException { - final String value = Base64.getEncoder().encodeToString("bar".getBytes()); - final VPackSlice vpack = new VPackBuilder().add(ValueType.OBJECT).add("foo", value).close().slice(); - final BinaryEntity entity = mapper.readValue(vpack.getBuffer(), BinaryEntity.class); - assertThat(entity).isNotNull(); - assertThat(entity.foo).isEqualTo("bar".getBytes()); - } - - @Test - void asFloatingNumber() { - final VPackSlice vpack = new VPackBuilder().add(ValueType.OBJECT).add("value", 12000).close().slice(); - assertThat(vpack.get("value").getAsInt()).isEqualTo(12000); - assertThat(vpack.get("value").getAsFloat()).isEqualTo(12000F); - assertThat(vpack.get("value").getAsDouble()).isEqualTo(12000.); - } - - @Test - void toVPackSlice() throws IOException { - final VPackSlice value = new VPackBuilder().add(ValueType.OBJECT).add("key", "value").close().slice(); - final VPackSlice entity = mapper.readValue(value.getBuffer(), VPackSlice.class); - assertThat(entity).isEqualTo(value); - } - - -} diff --git a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java b/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java deleted file mode 100644 index 63c1b87ae..000000000 --- a/src/test/java/com/arangodb/mapping/annotations/ArangoAnnotationsTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.mapping.annotations; - -import com.arangodb.mapping.ArangoJack; -import com.arangodb.velocypack.VPackSlice; -import org.junit.jupiter.api.Test; - -import java.util.HashMap; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Michele Rastelli - */ -class ArangoAnnotationsTest { - - private final ArangoJack mapper = new ArangoJack(); - - @Test - void documentField() { - DocumentFieldEntity e = new DocumentFieldEntity(); - e.setId("Id"); - e.setKey("Key"); - e.setRev("Rev"); - e.setFrom("From"); - e.setTo("To"); - - VPackSlice slice = mapper.serialize(e); - System.out.println(slice); - Map deserialized = mapper.deserialize(slice, Object.class); - assertThat(deserialized) - .containsEntry("_id", e.getId()) - .containsEntry("_key", e.getKey()) - .containsEntry("_rev", e.getRev()) - .containsEntry("_from", e.getFrom()) - .containsEntry("_to", e.getTo()) - .hasSize(5); - - DocumentFieldEntity deserializedEntity = mapper.deserialize(slice, DocumentFieldEntity.class); - assertThat(deserializedEntity).isEqualTo(e); - } - - @Test - void documentFieldAnnotations() { - AnnotatedEntity e = new AnnotatedEntity(); - e.setId("Id"); - e.setKey("Key"); - e.setRev("Rev"); - e.setFrom("From"); - e.setTo("To"); - - VPackSlice slice = mapper.serialize(e); - System.out.println(slice); - Map deserialized = mapper.deserialize(slice, Object.class); - assertThat(deserialized) - .containsEntry("_id", e.getId()) - .containsEntry("_key", e.getKey()) - .containsEntry("_rev", e.getRev()) - .containsEntry("_from", e.getFrom()) - .containsEntry("_to", e.getTo()) - .hasSize(5); - - AnnotatedEntity deserializedEntity = mapper.deserialize(slice, AnnotatedEntity.class); - assertThat(deserializedEntity).isEqualTo(e); - } - - @Test - void serializedName() { - SerializedNameEntity e = new SerializedNameEntity(); - e.setA("A"); - e.setB("B"); - e.setC("C"); - - VPackSlice slice = mapper.serialize(e); - System.out.println(slice); - Map deserialized = mapper.deserialize(slice, Object.class); - assertThat(deserialized) - .containsEntry(SerializedNameEntity.SERIALIZED_NAME_A, e.getA()) - .containsEntry(SerializedNameEntity.SERIALIZED_NAME_B, e.getB()) - .containsEntry(SerializedNameEntity.SERIALIZED_NAME_C, e.getC()) - .hasSize(3); - - SerializedNameEntity deserializedEntity = mapper.deserialize(slice, SerializedNameEntity.class); - assertThat(deserializedEntity).isEqualTo(e); - } - - @Test - void serializedNameParameter() { - Map e = new HashMap<>(); - e.put(SerializedNameParameterEntity.SERIALIZED_NAME_A, "A"); - e.put(SerializedNameParameterEntity.SERIALIZED_NAME_B, "B"); - e.put(SerializedNameParameterEntity.SERIALIZED_NAME_C, "C"); - - VPackSlice slice = mapper.serialize(e); - SerializedNameParameterEntity deserializedEntity = mapper - .deserialize(slice, SerializedNameParameterEntity.class); - assertThat(deserializedEntity).isEqualTo(new SerializedNameParameterEntity("A", "B", "C")); - } - - @Test - void expose() { - ExposeEntity e = new ExposeEntity(); - e.setReadWrite("readWrite"); - e.setReadOnly("readOnly"); - e.setWriteOnly("writeOnly"); - e.setIgnored("ignored"); - - VPackSlice serializedEntity = mapper.serialize(e); - Map deserializedEntity = mapper.deserialize(serializedEntity, Object.class); - assertThat(deserializedEntity) - .containsEntry("readWrite", "readWrite") - .containsEntry("readOnly", "readOnly") - .hasSize(2); - - Map map = new HashMap<>(); - map.put("readWrite", "readWrite"); - map.put("readOnly", "readOnly"); - map.put("writeOnly", "writeOnly"); - map.put("ignored", "ignored"); - - VPackSlice serializedMap = mapper.serialize(map); - ExposeEntity deserializedMap = mapper.deserialize(serializedMap, ExposeEntity.class); - assertThat(deserializedMap.getIgnored()).isNull(); - assertThat(deserializedMap.getReadOnly()).isNull(); - assertThat(deserializedMap.getWriteOnly()).isEqualTo("writeOnly"); - assertThat(deserializedMap.getReadWrite()).isEqualTo("readWrite"); - } - -} diff --git a/src/test/java/com/arangodb/mapping/annotations/DocumentFieldEntity.java b/src/test/java/com/arangodb/mapping/annotations/DocumentFieldEntity.java deleted file mode 100644 index 20241673f..000000000 --- a/src/test/java/com/arangodb/mapping/annotations/DocumentFieldEntity.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.mapping.annotations; - -import com.arangodb.entity.DocumentField; - -import java.util.Objects; - -/** - * @author Michele Rastelli - */ -public class DocumentFieldEntity { - - @DocumentField(DocumentField.Type.ID) - private String id; - - @DocumentField(DocumentField.Type.KEY) - private String key; - - @DocumentField(DocumentField.Type.REV) - private String rev; - - @DocumentField(DocumentField.Type.FROM) - private String from; - - @DocumentField(DocumentField.Type.TO) - private String to; - - public DocumentFieldEntity() { - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getRev() { - return rev; - } - - public void setRev(String rev) { - this.rev = rev; - } - - public String getFrom() { - return from; - } - - public void setFrom(String from) { - this.from = from; - } - - public String getTo() { - return to; - } - - public void setTo(String to) { - this.to = to; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - DocumentFieldEntity that = (DocumentFieldEntity) o; - return Objects.equals(id, that.id) && Objects.equals(key, that.key) && Objects.equals(rev, that.rev) && Objects - .equals(from, that.from) && Objects.equals(to, that.to); - } - - @Override - public int hashCode() { - return Objects.hash(id, key, rev, from, to); - } - - @Override - public String toString() { - return "AnnotatedEntity{" + "idField='" + id + '\'' + ", keyField='" + key + '\'' + ", revField='" + rev + '\'' - + ", fromField='" + from + '\'' + ", toField='" + to + '\'' + '}'; - } - -} diff --git a/src/test/java/com/arangodb/mapping/annotations/ExposeEntity.java b/src/test/java/com/arangodb/mapping/annotations/ExposeEntity.java deleted file mode 100644 index 3100f9b38..000000000 --- a/src/test/java/com/arangodb/mapping/annotations/ExposeEntity.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.mapping.annotations; - -import com.arangodb.velocypack.annotations.Expose; - -import java.util.Objects; - -/** - * @author Michele Rastelli - */ -public class ExposeEntity { - - @Expose() - private String readWrite; - - @Expose(deserialize = false) - private String readOnly; - - @Expose(serialize = false) - private String writeOnly; - - @Expose(serialize = false, - deserialize = false) - private String ignored; - - public ExposeEntity() { - } - - public String getReadWrite() { - return readWrite; - } - - public void setReadWrite(String readWrite) { - this.readWrite = readWrite; - } - - public String getReadOnly() { - return readOnly; - } - - public void setReadOnly(String readOnly) { - this.readOnly = readOnly; - } - - public String getWriteOnly() { - return writeOnly; - } - - public void setWriteOnly(String writeOnly) { - this.writeOnly = writeOnly; - } - - public String getIgnored() { - return ignored; - } - - public void setIgnored(String ignored) { - this.ignored = ignored; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - ExposeEntity that = (ExposeEntity) o; - return Objects.equals(readWrite, that.readWrite) && Objects.equals(readOnly, that.readOnly) && Objects - .equals(writeOnly, that.writeOnly) && Objects.equals(ignored, that.ignored); - } - - @Override - public int hashCode() { - return Objects.hash(readWrite, readOnly, writeOnly, ignored); - } - - @Override - public String toString() { - return "ExposeEntity{" + "readWrite='" + readWrite + '\'' + ", readOnly='" + readOnly + '\'' + ", writeOnly='" - + writeOnly + '\'' + ", ignored='" + ignored + '\'' + '}'; - } -} \ No newline at end of file diff --git a/src/test/java/com/arangodb/mapping/annotations/SerializedNameEntity.java b/src/test/java/com/arangodb/mapping/annotations/SerializedNameEntity.java deleted file mode 100644 index 110d750be..000000000 --- a/src/test/java/com/arangodb/mapping/annotations/SerializedNameEntity.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.mapping.annotations; - -import com.arangodb.velocypack.annotations.SerializedName; - -import java.util.Objects; - -/** - * @author Michele Rastelli - */ -public class SerializedNameEntity { - - final static String SERIALIZED_NAME_A = "aSerializedName"; - final static String SERIALIZED_NAME_B = "bSerializedName"; - final static String SERIALIZED_NAME_C = "cSerializedName"; - - @SerializedName(SERIALIZED_NAME_A) - private String a; - private String b; - private String c; - - public SerializedNameEntity() { - } - - public String getA() { - return a; - } - - public void setA(String a) { - this.a = a; - } - - @SerializedName(SERIALIZED_NAME_B) - public String getB() { - return b; - } - - public void setB(String b) { - this.b = b; - } - - public String getC() { - return c; - } - - @SerializedName(SERIALIZED_NAME_C) - public void setC(String c) { - this.c = c; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - SerializedNameEntity that = (SerializedNameEntity) o; - return Objects.equals(a, that.a) && Objects.equals(b, that.b) && Objects.equals(c, that.c); - } - - @Override - public int hashCode() { - return Objects.hash(a, b, c); - } - - @Override - public String toString() { - return "SerializedNameEntity{" + "a='" + a + '\'' + ", b='" + b + '\'' + ", c='" + c + '\'' + '}'; - } -} diff --git a/src/test/java/com/arangodb/mapping/annotations/SerializedNameParameterEntity.java b/src/test/java/com/arangodb/mapping/annotations/SerializedNameParameterEntity.java deleted file mode 100644 index 034c00f93..000000000 --- a/src/test/java/com/arangodb/mapping/annotations/SerializedNameParameterEntity.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.mapping.annotations; - -import com.arangodb.velocypack.annotations.SerializedName; - -import java.util.Objects; - -/** - * @author Michele Rastelli - */ -public class SerializedNameParameterEntity { - - final static String SERIALIZED_NAME_A = "aSerializedName"; - final static String SERIALIZED_NAME_B = "bSerializedName"; - final static String SERIALIZED_NAME_C = "cSerializedName"; - - private String a; - private String b; - private String c; - - public SerializedNameParameterEntity( - @SerializedName(SERIALIZED_NAME_A) - String a, - @SerializedName(SERIALIZED_NAME_B) - String b, - @SerializedName(SERIALIZED_NAME_C) - String c) { - this.a = a; - this.b = b; - this.c = c; - } - - public String getA() { - return a; - } - - public String getB() { - return b; - } - - public String getC() { - return c; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - SerializedNameParameterEntity that = (SerializedNameParameterEntity) o; - return Objects.equals(a, that.a) && Objects.equals(b, that.b) && Objects.equals(c, that.c); - } - - @Override - public int hashCode() { - return Objects.hash(a, b, c); - } - - @Override - public String toString() { - return "SerializedNameParameterEntity{" + "a='" + a + '\'' + ", b='" + b + '\'' + ", c='" + c + '\'' + '}'; - } -} diff --git a/src/test/java/com/arangodb/util/ArangoSerializationTest.java b/src/test/java/com/arangodb/util/ArangoSerializationTest.java deleted file mode 100644 index d17bd27c4..000000000 --- a/src/test/java/com/arangodb/util/ArangoSerializationTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.util; - -import com.arangodb.ArangoDB; -import com.arangodb.entity.BaseDocument; -import com.arangodb.mapping.ArangoJack; -import com.arangodb.velocypack.*; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * @author Mark Vollmary - */ -class ArangoSerializationTest { - - private static ArangoSerialization util; - - @BeforeAll - static void setup() { - final ArangoDB arangoDB = new ArangoDB.Builder().serializer(new ArangoJack()).build(); - util = arangoDB.util(); - } - - @Test - void deserialize() { - final VPackBuilder builder = new VPackBuilder().add(ValueType.OBJECT).add("foo", "bar").close(); - final BaseDocument doc = util.deserialize(builder.slice(), BaseDocument.class); - assertThat(doc.getAttribute("foo")).isEqualTo("bar"); - } - - @Test - void serialize() { - final BaseDocument entity = new BaseDocument(); - entity.addAttribute("foo", "bar"); - final VPackSlice vpack = util.serialize(entity); - assertThat(vpack.get("foo").isString()).isTrue(); - assertThat(vpack.get("foo").getAsString()).isEqualTo("bar"); - } - - @Test - void serializeNullValues() { - final BaseDocument entity = new BaseDocument(); - entity.addAttribute("foo", null); - final VPackSlice vpack = util.serialize(entity, new ArangoSerializer.Options().serializeNullValues(true)); - assertThat(vpack.get("foo").isNull()).isTrue(); - } - - @Test - void skipSerializeNullValues() { - final BaseDocument entity = new BaseDocument(); - entity.addAttribute("bar", null); - final VPackSlice vpack = util.serialize(entity); - assertThat(vpack.get("bar").isNone()).isTrue(); - } - - @Test - void serializeType() { - final Collection list = new ArrayList<>(); - list.add(new BaseDocument()); - list.add(new BaseDocument()); - - final VPackSlice vpack = util.serialize(list, - new ArangoSerializer.Options().type(new Type>() { - }.getType())); - assertThat(vpack.isArray()).isTrue(); - assertThat(vpack.getLength()).isEqualTo(list.size()); - } - - @Test - void parseJsonIncludeNull() { - final Map entity = new HashMap<>(); - entity.put("value", new String[]{"test", null}); - final String json = util.deserialize(util.serialize(entity, new ArangoSerializer.Options()), String.class); - assertThat(json).isEqualTo("{\"value\":[\"test\",null]}"); - } - - @Test - void parseNullString() { - final String json = util.deserialize(new VPackBuilder().add((String) null).slice(), String.class); - assertThat(json).isNull(); - } - -} diff --git a/src/test/java/helper/NativeImageHelper.java b/src/test/java/helper/NativeImageHelper.java deleted file mode 100644 index 39bb227e5..000000000 --- a/src/test/java/helper/NativeImageHelper.java +++ /dev/null @@ -1,67 +0,0 @@ -package helper; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.reflections.Reflections; -import org.reflections.scanners.MethodParameterScanner; -import org.reflections.util.ClasspathHelper; -import org.reflections.util.ConfigurationBuilder; -import org.reflections.util.FilterBuilder; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.List; - -/** - * Helper scripts to generate GraalVM native image configuration - * - * @author Michele Rastelli - */ -public class NativeImageHelper { - public static void main(String[] args) throws JsonProcessingException { - generateReflectConfig(); - } - - private static void generateReflectConfig() throws JsonProcessingException { - System.out.println("---------------------------"); - System.out.println("--- reflect-config.json ---"); - System.out.println("---------------------------"); - - List packages = Arrays.asList("com.arangodb.entity", "com.arangodb.model"); - - ObjectMapper mapper = new ObjectMapper(); - ArrayNode rootNode = mapper.createArrayNode(); - ObjectNode noArgConstructor = mapper.createObjectNode(); - noArgConstructor.put("name", ""); - noArgConstructor.set("parameterTypes", mapper.createArrayNode()); - ArrayNode methods = mapper.createArrayNode(); - methods.add(noArgConstructor); - - packages.stream() - .flatMap(p -> { - final ConfigurationBuilder config = new ConfigurationBuilder() - .setScanners(new MethodParameterScanner()) - .setUrls(ClasspathHelper.forPackage(p)) - .filterInputsBy(new FilterBuilder().includePackage(p)); - - return new Reflections(config).getConstructorsMatchParams().stream(); - }) - .filter((it -> Modifier.isPublic(it.getDeclaringClass().getModifiers()))) - .filter(it -> Modifier.isPublic(it.getModifiers())) - .map(Constructor::getName) - .map(className -> { - ObjectNode entry = mapper.createObjectNode(); - entry.put("name", className); - entry.put("allDeclaredFields", true); - entry.set("methods", methods); - return entry; - }) - .forEach(rootNode::add); - - String jsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode); - System.out.println(jsonString); - } -} diff --git a/src/test/resources/META-INF/native-image/native-image.properties b/src/test/resources/META-INF/native-image/native-image.properties deleted file mode 100644 index a18c4a2fe..000000000 --- a/src/test/resources/META-INF/native-image/native-image.properties +++ /dev/null @@ -1,3 +0,0 @@ -Args=\ - -H:ResourceConfigurationFiles=test-classes/META-INF/native-image/resource-config.json \ - -H:ReflectionConfigurationResources=${.}/reflect-config.json diff --git a/src/test/resources/META-INF/native-image/reflect-config.json b/src/test/resources/META-INF/native-image/reflect-config.json deleted file mode 100644 index f3181a2c9..000000000 --- a/src/test/resources/META-INF/native-image/reflect-config.json +++ /dev/null @@ -1,591 +0,0 @@ -[ - { - "name": "ch.qos.logback.classic.encoder.PatternLayoutEncoder", - "allPublicMethods": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.classic.pattern.DateConverter", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.classic.pattern.LevelConverter", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.classic.pattern.LineSeparatorConverter", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.classic.pattern.LoggerConverter", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.classic.pattern.MessageConverter", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.classic.pattern.ThreadConverter", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "ch.qos.logback.core.ConsoleAppender", - "allPublicMethods": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.ArangoCollectionTest$TestUpdateEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.ArangoDatabaseTest$TransactionTestEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.ArangoDatabaseTest$TransactionTestEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.document.AqlQueryWithSpecialReturnTypesExampleTest$Gender", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.document.TestEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.graph.AQLActorsAndMoviesExampleTest$Actor", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.graph.AQLActorsAndMoviesExampleTest$Movie", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.graph.Circle", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.graph.CircleEdge", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.async.example.graph.ShortestPathInAQLExampleTest$Pair", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.document.AqlQueryWithSpecialReturnTypesExampleTest$Gender", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.document.TestEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.graph.AQLActorsAndMoviesExampleTest$Actor", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.graph.AQLActorsAndMoviesExampleTest$Movie", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.graph.Circle", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.graph.CircleEdge", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.example.graph.ShortestPathInAQLExampleTest$Pair", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$BinaryEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$CustomAnEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$CustomFilterAnnotation" - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$CustomNamingAnnotation" - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestCollection", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityA", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityArray", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityArrayInArray", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityArrayInArrayInArray", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityB", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityBaseAttributes", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityBigNumber", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityBoolean", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityByte", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityC", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityCollection", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityCollectionExtendedWithNulls", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityCollectionWithObjects", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityD", - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityDImpl", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityDate", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityDouble", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityEmpty", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityEmptyMap", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityEnum", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityFloat", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityInteger", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityLong", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityMap", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityMapStringableKey", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityMapWithObjectKey", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityObject", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityObjectInArray", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityShort", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityString", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityTyped", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEntityUUID", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.VPackSerializeDeserializeTest$TestEnum", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.annotations.DocumentFieldEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.annotations.AnnotatedEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.annotations.ExposeEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.annotations.SerializedNameEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.mapping.annotations.SerializedNameParameterEntity", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.serde.CustomSerdeTest$Person", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.serde.CustomSerdeTest$PersonDeserializer", - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.serde.CustomSerdeTest$PersonSerializer", - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "com.arangodb.serde.CustomTypeHintTest$Animal", - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.serde.CustomTypeHintTest$Gorilla", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "com.arangodb.serde.CustomTypeHintTest$Zoo", - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredConstructors": true, - "allDeclaredClasses": true - }, - { - "name": "java.util.HashSet", - "allDeclaredMethods": true, - "allDeclaredConstructors": true - } -] diff --git a/src/test/resources/arangodb-bad2.properties b/src/test/resources/arangodb-bad2.properties deleted file mode 100644 index 1c19ad869..000000000 --- a/src/test/resources/arangodb-bad2.properties +++ /dev/null @@ -1 +0,0 @@ -arangodb.host=127.0.0.1:8529 diff --git a/src/test/resources/arangodb-ssl.properties b/src/test/resources/arangodb-ssl.properties deleted file mode 100644 index cc3e07b70..000000000 --- a/src/test/resources/arangodb-ssl.properties +++ /dev/null @@ -1,2 +0,0 @@ -arangodb.hosts=localhost:8529 -arangodb.useSsl=true diff --git a/tests/travis/server.pem b/tests/travis/server.pem deleted file mode 100644 index 108998782..000000000 --- a/tests/travis/server.pem +++ /dev/null @@ -1,29 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICKTCCAZICCQDrch/8O8H4PTANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJE -RTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMTIwNzI0MDYxNzUwWhcN -MTMwNzI0MDYxNzUwWjBZMQswCQYDVQQGEwJERTETMBEGA1UECAwKU29tZS1TdGF0 -ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAls -b2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMDwRweF75H+BFBY -m9c4V/AZyWehxQ+pRfy6d+oPiUbOByqLDEQBdiMamQ0acJX9sn+MsFixEDRC1Y8r -ef49k1hb9V/pPtSFPVl5y8Db4FiDabKD9juUvNRqCXAzu99dwJwFZU2Ldq4BiCmf -8V0SO+nHJHs3+HNgbYU+g77Fax7dAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEASYfI -Afq5lRn+XoESn+PQ89XJ83Jr5mJhDkT7ebw+w1CQsnR9uYIeAYNxOyb3bfHOntnz -3irGYJWkrewVYjNkID8jhZSYEOZkfC4jxNLigg7QXyw/XWwwCIEr8/ZW+cnci43G -+IhSspyoJnljELM99ZsW0IaBLT+tgHzep4bIh0Y= ------END CERTIFICATE----- ------BEGIN RSA PRIVATE KEY----- -MIICXgIBAAKBgQDA8EcHhe+R/gRQWJvXOFfwGclnocUPqUX8unfqD4lGzgcqiwxE -AXYjGpkNGnCV/bJ/jLBYsRA0QtWPK3n+PZNYW/Vf6T7UhT1ZecvA2+BYg2myg/Y7 -lLzUaglwM7vfXcCcBWVNi3auAYgpn/FdEjvpxyR7N/hzYG2FPoO+xWse3QIDAQAB -AoGBALsP+34C0M02gI456xbXDQPArLJqePp/P1kSnbL0zz80AGSyHflNhXHxltTK -fsAeElNyX4QOYEybRB2kpInov5KrL3lR926GY++otHpSAue+PfLJHH8OU8qjartw -KGlzdnFFYQVLNc0qYGl/h0MxH6+Ce8JV0y1zI4J3nwMwCZwBAkEA6uqluGj4SXIj -6W+FefuHlHXgFn+TZgsGNNmmCMhLJPUUP7auIagtG1n12mN47kWqhLu3asLEVq4+ -YnCEa0hF3QJBANJBKN/zyfmvkiET33cY03282gSN0YLyibMYoNDOOYMFEW2b+3oF -x0d40FfEkYS0R4rJiR1HI8xWw8uQEWsXLQECQQDRx1DN6Q8vpznij7BGShO8w7ak -4LAkA9w6/dGDLjnMev7mFqBRdfkx35foucOYI6YueeNE90CVl2wmRAw8MYIRAkEA -qUUgPTyuDMCWqt6u99ka243hD+2FESFmTrOzNKfykVLRNydvDEv+pcHUKfTtGqNx -PYEHTHTrkyT/OLFh9I+SAQJAOntw15vhgKiy0DUvjSvXGJziBDPsu/MCZ2CZbaVx -ipkUZQCZLd/HvMphAiirLV+mAJQC732KKlR9/HWRzDDFEQ== ------END RSA PRIVATE KEY----- diff --git a/tests/travis/setup_arangodb.sh b/tests/travis/setup_arangodb.sh deleted file mode 100755 index 5613ad035..000000000 --- a/tests/travis/setup_arangodb.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -cd $DIR - -VERSION=devel -NAME=ArangoDB-$VERSION - -if [ ! -d "$DIR/$NAME" ]; then - # download ArangoDB - echo "wget https://www.arangodb.com/repositories/travisCI/$NAME.tar.gz" - wget https://www.arangodb.com/repositories/travisCI/$NAME.tar.gz - echo "tar zxf $NAME.tar.gz" - tar zvxf $NAME.tar.gz -fi - -ARCH=$(arch) -PID=$(echo $PPID) -TMP_DIR="/tmp/arangodb.$PID" -PID_FILE="/tmp/arangodb.$PID.pid" -ARANGODB_DIR="$DIR/$NAME" -ARANGOD="${ARANGODB_DIR}/bin/arangod_x86_64" - -# create database directory -mkdir ${TMP_DIR} - -echo "Starting ArangoDB '${ARANGOD}'" - -${ARANGOD} \ - --database.directory ${TMP_DIR} \ - --configuration none \ - --server.endpoint tcp://127.0.0.1:8529 \ - --server.endpoint ssl://127.0.0.1:8530 \ - --ssl.keyfile ./server.pem \ - --javascript.app-path ${ARANGODB_DIR}/js/apps \ - --javascript.startup-directory ${ARANGODB_DIR}/js \ - --server.authentication=true & - -sleep 2 - -echo "Check for arangod process" -process=$(ps auxww | grep "bin/arangod" | grep -v grep) - -if [ "x$process" == "x" ]; then - echo "no 'arangod' process found" - echo "ARCH = $ARCH" - exit 1 -fi - -echo "Waiting until ArangoDB is ready on port 8529" -while [[ -z $(curl -uroot: -s 'http://127.0.0.1:8529/_api/version') ]]; do - echo -n "." - sleep 2s -done - -echo "ArangoDB is up" diff --git a/tutorial/.gitignore b/tutorial/.gitignore new file mode 100644 index 000000000..f631b0010 --- /dev/null +++ b/tutorial/.gitignore @@ -0,0 +1,32 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +target +**/.idea +*.iml +**/.directory +/gradle/.gradle/ +/gradle/build/ +/gradle/gradle/ +/gradle/gradlew +/gradle/gradlew.bat diff --git a/tutorial/README.md b/tutorial/README.md new file mode 100644 index 000000000..3983069b0 --- /dev/null +++ b/tutorial/README.md @@ -0,0 +1,3 @@ +# ArangoDB Java driver tutorial + +Code for ArangoDB [Java driver tutorial](https://www.arangodb.com/docs/stable/drivers/java-tutorial.html). diff --git a/tutorial/Tutorial.md b/tutorial/Tutorial.md new file mode 100644 index 000000000..9f2bcc3cc --- /dev/null +++ b/tutorial/Tutorial.md @@ -0,0 +1,307 @@ +# Tutorial: Java in 10 Minutes + +This is a short tutorial with the [Java Driver](https://github.com/arangodb/arangodb-java-driver) and ArangoDB. In less +than 10 minutes you can learn how to use ArangoDB Java driver in Maven and Gradle projects. + + +## Project configuration + +To use the ArangoDB Java driver, you need to import +[arangodb-java-driver](https://github.com/arangodb/arangodb-java-driver) +as a library into your project. + +In a Maven project, you need to add the following dependency to `pom.xml`: + +```xml + + + com.arangodb + arangodb-java-driver + ... + + +``` + +In a Gradle project, you need to add the following to `build.gradle`: + +```groovy +dependencies { + implementation 'com.arangodb:arangodb-java-driver:...' +} +``` + + +## Connection + +Let's configure and open a connection to start ArangoDB. + +```java +ArangoDB arangoDB = new ArangoDB.Builder() + .host("localhost", 8529) + .build(); +``` + +> **Hint:** The default connection is to 127.0.0.1:8529. + + +## Creating a database + +Let’s create a new database: + +```java +ArangoDatabase db = arangoDB.db(DbName.of("mydb")); +System.out.println("Creating database..."); +db.create(); +``` + + +## Creating a collection + +Now let’s create our first collection: + +```java +ArangoCollection collection = db.collection("firstCollection"); +System.out.println("Creating collection..."); +collection.create(); +``` + + +## Creating a document + +Now we create a document in the collection. Any object can be added as a document to the database and be retrieved from +the database as an object. + +For this example we use the class BaseDocument, provided with the driver. The attributes of the document are stored in a +map as key/value pair: + +```java +String key = "myKey"; +BaseDocument doc = new BaseDocument(key); +doc.addAttribute("a", "Foo"); +doc.addAttribute("b", 42); +System.out.println("Inserting document..."); +collection.insertDocument(doc); +``` + +Some details you should know about the code: + +- the document key is passed to the `BaseDocument` constructor +- `addAttribute()` puts a new key/value pair into the document +- each attribute is stored as a single key value pair in the document root + + +## Read a document + +To read the created document: + +```java +System.out.println("Reading document..."); +BaseDocument readDocument = collection.getDocument(key, BaseDocument.class); +System.out.println("Key: " + readDocument.getKey()); +System.out.println("Attribute a: " + readDocument.getAttribute("a")); +System.out.println("Attribute b: " + readDocument.getAttribute("b")); +``` + +After executing this program the console output should be: + +```text +Key: myKey +Attribute a: Foo +Attribute b: 42 +``` + +Some details you should know about the code: + +- `getDocument()` reads the stored document data and deserilizes it into the given class (`BaseDocument`) + + +## Creating a document from Jackson JsonNode + +We can also create a document from a Jackson [JsonNode](https://fasterxml.github.io/jackson-databind/javadoc/2.13/com/fasterxml/jackson/databind/JsonNode.html) object: + +```java +System.out.println("Creating a document from Jackson JsonNode..."); +String keyJackson = "myJacksonKey"; +JsonNode jsonNode = JsonNodeFactory.instance.objectNode() + .put("_key", keyJackson) + .put("a", "Bar") + .put("b", 53); +System.out.println("Inserting document from Jackson JsonNode..."); +collection.insertDocument(jsonNode); +``` + + +## Read a document as Jackson JsonNode + +Documents can also be read as Jackson [JsonNode](https://fasterxml.github.io/jackson-databind/javadoc/2.13/com/fasterxml/jackson/databind/JsonNode.html): + +```java +System.out.println("Reading document as Jackson JsonNode..."); +JsonNode readJsonNode = collection.getDocument(keyJackson, JsonNode.class); +System.out.println("Key: " + readJsonNode.get("_key").textValue()); +System.out.println("Attribute a: " + readJsonNode.get("a").textValue()); +System.out.println("Attribute b: " + readJsonNode.get("b").intValue()); +``` + +After executing this program the console output should be: + +```text +Key: myKey +Attribute a: Bar +Attribute b: 53 +``` + +Some details you should know about the code: + +- `getDocument()` returns the stored document as instance of `com.fasterxml.jackson.databind.JsonNode`. + + +## Creating a document from JSON String + +Documents can also be created from raw JSON strings: + +```java +System.out.println("Creating a document from JSON String..."); +String keyJson = "myJsonKey"; +RawJson json = RawJson.of("{\"_key\":\"" + keyJson + "\",\"a\":\"Baz\",\"b\":64}"); +System.out.println("Inserting document from JSON String..."); +collection.insertDocument(json); +``` + +## Read a document as JSON String + +Documents can also be read as raw JSON strings: + +```java +System.out.println("Reading document as JSON String..."); +RawJson readJson = collection.getDocument(keyJson, RawJson.class); +System.out.println(readJson.getValue()); +``` + +After executing this program the console output should be: + +```text +{"_key":"myJsonKey","_id":"firstCollection/myJsonKey","_rev":"_e0nEe2y---","a":"Baz","b":64} +``` + + +## Update a document + +Let's update the document: + +```java +doc.addAttribute("c", "Bar"); +System.out.println("Updating document ..."); +collection.updateDocument(key, doc); +``` + + +## Read the document again + +Let’s read the document again: + +```java +System.out.println("Reading updated document ..."); +BaseDocument updatedDocument = collection.getDocument(key, BaseDocument.class); +System.out.println("Key: " + updatedDocument.getKey()); +System.out.println("Attribute a: " + updatedDocument.getAttribute("a")); +System.out.println("Attribute b: " + updatedDocument.getAttribute("b")); +System.out.println("Attribute c: " + updatedDocument.getAttribute("c")); +``` + +After executing this program the console output should look like this: + +```text +Key: myKey +Attribute a: Foo +Attribute b: 42 +Attribute c: Bar +``` + + +## Delete a document + +Let’s delete a document: + +```java +System.out.println("Deleting document ..."); +collection.deleteDocument(key); +``` + + +## Execute AQL queries + +First we need to create some documents with the name Homer in collection firstCollection: + +```java +for (int i = 0; i < 10; i++) { + BaseDocument value = new BaseDocument(String.valueOf(i)); + value.addAttribute("name", "Homer"); + collection.insertDocument(value); +} +``` + +Get all documents with the name Homer from collection firstCollection and iterate over the result: + +```java +String query = "FOR t IN firstCollection FILTER t.name == @name RETURN t"; +Map bindVars = Collections.singletonMap("name", "Homer"); +System.out.println("Executing read query ..."); +ArangoCursor cursor = db.query(query, bindVars, null, BaseDocument.class); +cursor.forEach(aDocument -> System.out.println("Key: " + aDocument.getKey())); +``` + +After executing this program the console output should look something like this: + +```text +Key: 1 +Key: 0 +Key: 5 +Key: 3 +Key: 4 +Key: 9 +Key: 2 +Key: 7 +Key: 8 +Key: 6 +``` + +Some details you should know about the code: + +- the AQL query uses the placeholder `@name` which has to be bind to a value +- `query()` executes the defined query and returns a `ArangoCursor` with the given class (here: `BaseDocument`) +- the order is not guaranteed + + +## Delete a document with AQL + +Now we will delete the document created before: + +```java +String query = "FOR t IN firstCollection FILTER t.name == @name " + + "REMOVE t IN firstCollection LET removed = OLD RETURN removed"; +Map bindVars = Collections.singletonMap("name", "Homer"); +System.out.println("Executing delete query ..."); +ArangoCursor cursor = db.query(query, bindVars, null, BaseDocument.class); +cursor.forEach(aDocument -> System.out.println("Removed document " + aDocument.getKey())); +``` + +After executing this program the console output should look something like this: + +```text +Removed document: 1 +Removed document: 0 +Removed document: 5 +Removed document: 3 +Removed document: 4 +Removed document: 9 +Removed document: 2 +Removed document: 7 +Removed document: 8 +Removed document: 6 +``` + +## Learn more + +- Have a look at the [AQL documentation](https://www.arangodb.com/docs/stable/aql/) to learn more about the query language. +- Also check out the documentation about ArangoDB's [Data Model & Concepts](https://www.arangodb.com/docs/stable/data-model-and-concepts.html) diff --git a/tutorial/gradle/build.gradle b/tutorial/gradle/build.gradle new file mode 100644 index 000000000..fad8b8db1 --- /dev/null +++ b/tutorial/gradle/build.gradle @@ -0,0 +1,14 @@ +plugins { + id 'java' +} + +group 'com.arangodb' +version '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + implementation 'com.arangodb:arangodb-java-driver:7.0.0-ALPHA.2' +} diff --git a/tutorial/gradle/settings.gradle b/tutorial/gradle/settings.gradle new file mode 100644 index 000000000..28160edab --- /dev/null +++ b/tutorial/gradle/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'arangodb-java-driver-tutorial-gradle' diff --git a/tutorial/gradle/src b/tutorial/gradle/src new file mode 120000 index 000000000..c927ed2aa --- /dev/null +++ b/tutorial/gradle/src @@ -0,0 +1 @@ +../maven/src \ No newline at end of file diff --git a/tutorial/maven/pom.xml b/tutorial/maven/pom.xml new file mode 100644 index 000000000..5154baa86 --- /dev/null +++ b/tutorial/maven/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + + com.arangodb + arangodb-java-driver-tutorial-maven + 1.0-SNAPSHOT + + + 17 + 17 + 17 + UTF-8 + + + + + com.arangodb + arangodb-java-driver + 7.0.0-ALPHA.2 + + + + diff --git a/tutorial/maven/src/main/java/FirstProject.java b/tutorial/maven/src/main/java/FirstProject.java new file mode 100644 index 000000000..2950387db --- /dev/null +++ b/tutorial/maven/src/main/java/FirstProject.java @@ -0,0 +1,134 @@ +import com.arangodb.*; +import com.arangodb.entity.BaseDocument; +import com.arangodb.util.RawJson; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; + +import java.util.Collections; +import java.util.Map; + +public class FirstProject { + private static final ArangoDB arangoDB = new ArangoDB.Builder() + .host("localhost", 8529) + .password("test") + .build(); + + private static void cleanup() { + ArangoDatabase db = arangoDB.db(DbName.of("mydb")); + if (db.exists()) db.drop(); + } + + public static void main(String[] args) { + cleanup(); + + // Creating a database + ArangoDatabase db = arangoDB.db(DbName.of("mydb")); + System.out.println("Creating database..."); + db.create(); + + // Creating a collection + ArangoCollection collection = db.collection("firstCollection"); + System.out.println("Creating collection..."); + collection.create(); + + // Creating a document + String key = "myKey"; + BaseDocument doc = new BaseDocument(key); + doc.addAttribute("a", "Foo"); + doc.addAttribute("b", 42); + System.out.println("Inserting document..."); + collection.insertDocument(doc); + + // Read a document + { + System.out.println("Reading document..."); + BaseDocument readDocument = collection.getDocument(key, BaseDocument.class); + System.out.println("Key: " + readDocument.getKey()); + System.out.println("Attribute a: " + readDocument.getAttribute("a")); + System.out.println("Attribute b: " + readDocument.getAttribute("b")); + } + + // Creating a document from Jackson JsonNode + String keyJackson = "myJacksonKey"; + JsonNode jsonNode = JsonNodeFactory.instance.objectNode() + .put("_key", keyJackson) + .put("a", "Bar") + .put("b", 53); + System.out.println("Inserting document from Jackson JsonNode..."); + collection.insertDocument(jsonNode); + + // Read a document as Jackson JsonNode + { + System.out.println("Reading document as Jackson JsonNode..."); + JsonNode readJsonNode = collection.getDocument(keyJackson, JsonNode.class); + System.out.println("Key: " + readJsonNode.get("_key").textValue()); + System.out.println("Attribute a: " + readJsonNode.get("a").textValue()); + System.out.println("Attribute b: " + readJsonNode.get("b").intValue()); + } + + // Creating a document from JSON String + String keyJson = "myJsonKey"; + RawJson json = RawJson.of(""" + {"_key":"%s","a":"Baz","b":64} + """.formatted(keyJson)); + System.out.println("Inserting document from JSON String..."); + collection.insertDocument(json); + + // Read a document as JSON String + { + System.out.println("Reading document as JSON String..."); + RawJson readJson = collection.getDocument(keyJson, RawJson.class); + System.out.println(readJson.getValue()); + } + + // Update a document + { + doc.addAttribute("c", "Bar"); + System.out.println("Updating document ..."); + collection.updateDocument(key, doc); + } + + // Read the document again + { + System.out.println("Reading updated document ..."); + BaseDocument updatedDocument = collection.getDocument(key, BaseDocument.class); + System.out.println("Key: " + updatedDocument.getKey()); + System.out.println("Attribute a: " + updatedDocument.getAttribute("a")); + System.out.println("Attribute b: " + updatedDocument.getAttribute("b")); + System.out.println("Attribute c: " + updatedDocument.getAttribute("c")); + } + + // Delete a document + { + System.out.println("Deleting document ..."); + collection.deleteDocument(key); + } + + // Execute AQL queries + { + for (int i = 0; i < 10; i++) { + BaseDocument value = new BaseDocument(String.valueOf(i)); + value.addAttribute("name", "Homer"); + collection.insertDocument(value); + } + + String query = "FOR t IN firstCollection FILTER t.name == @name RETURN t"; + Map bindVars = Collections.singletonMap("name", "Homer"); + System.out.println("Executing read query ..."); + ArangoCursor cursor = db.query(query, bindVars, null, BaseDocument.class); + cursor.forEach(aDocument -> System.out.println("Key: " + aDocument.getKey())); + } + + // Delete a document with AQL + { + String query = "FOR t IN firstCollection FILTER t.name == @name " + + "REMOVE t IN firstCollection LET removed = OLD RETURN removed"; + Map bindVars = Collections.singletonMap("name", "Homer"); + System.out.println("Executing delete query ..."); + ArangoCursor cursor = db.query(query, bindVars, null, BaseDocument.class); + cursor.forEach(aDocument -> System.out.println("Removed document " + aDocument.getKey())); + } + + arangoDB.shutdown(); + } +} diff --git a/vst/pom.xml b/vst/pom.xml new file mode 100644 index 000000000..76943f277 --- /dev/null +++ b/vst/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + com.arangodb + arangodb-java-driver-parent + 7.0.0-ALPHA.2 + + + vst-protocol + vst-protocol + VST Protocol module for ArangoDB Java Driver + + + false + com.arangodb.vst + + + + + com.arangodb + core + provided + + + com.arangodb + velocypack + + + + \ No newline at end of file diff --git a/vst/src/main/java/com/arangodb/vst/VstAsyncProtocolProvider.java b/vst/src/main/java/com/arangodb/vst/VstAsyncProtocolProvider.java new file mode 100644 index 000000000..8bb1a19d9 --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/VstAsyncProtocolProvider.java @@ -0,0 +1,30 @@ +package com.arangodb.vst; + +import com.arangodb.Protocol; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.*; +import com.arangodb.vst.async.VstCommunicationAsync; +import com.arangodb.vst.async.VstConnectionFactoryAsync; +import com.fasterxml.jackson.databind.Module; + +public class VstAsyncProtocolProvider implements AsyncProtocolProvider { + @Override + public boolean supportsProtocol(Protocol protocol) { + return Protocol.VST.equals(protocol); + } + + @Override + public ConnectionFactory createConnectionFactory() { + return new VstConnectionFactoryAsync(); + } + + @Override + public AsyncCommunication createCommunication(final ArangoConfig config, final HostHandler hostHandler) { + return new VstCommunicationAsync(config, hostHandler); + } + + @Override + public Module protocolModule() { + return VstModule.INSTANCE.get(); + } +} diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/vst/src/main/java/com/arangodb/vst/VstCommunication.java similarity index 74% rename from src/main/java/com/arangodb/internal/velocystream/VstCommunication.java rename to vst/src/main/java/com/arangodb/vst/VstCommunication.java index 0cb2faea1..d90510f6d 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java +++ b/vst/src/main/java/com/arangodb/vst/VstCommunication.java @@ -18,28 +18,27 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.velocystream; +package com.arangodb.vst; import com.arangodb.ArangoDBException; -import com.arangodb.internal.ArangoDefaults; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.AccessType; import com.arangodb.internal.net.Host; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; +import com.arangodb.internal.serde.InternalSerde; import com.arangodb.internal.util.RequestUtils; import com.arangodb.internal.util.ResponseUtils; -import com.arangodb.internal.velocystream.internal.Chunk; -import com.arangodb.internal.velocystream.internal.Message; -import com.arangodb.internal.velocystream.internal.VstConnection; -import com.arangodb.util.ArangoSerialization; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.exception.VPackParserException; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.vst.internal.Chunk; +import com.arangodb.vst.internal.Message; +import com.arangodb.vst.internal.VstConnection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.net.ssl.SSLContext; import java.io.Closeable; import java.io.IOException; import java.util.ArrayList; @@ -49,31 +48,27 @@ /** * @author Mark Vollmary */ -public abstract class VstCommunication implements Closeable { +public abstract class VstCommunication> implements Closeable { protected static final String ENCRYPTION_PLAIN = "plain"; protected static final String ENCRYPTION_JWT = "jwt"; - private static final Logger LOGGER = LoggerFactory.getLogger(VstCommunication.class); - protected static final AtomicLong mId = new AtomicLong(0L); - protected final ArangoSerialization util; + private static final Logger LOGGER = LoggerFactory.getLogger(VstCommunication.class); + protected final InternalSerde serde; protected final String user; protected final String password; - protected volatile String jwt; - protected final Integer chunksize; protected final HostHandler hostHandler; + protected volatile String jwt; - protected VstCommunication(final Integer timeout, final String user, final String password, final String jwt, - final Boolean useSsl, final SSLContext sslContext, final ArangoSerialization util, - final Integer chunksize, final HostHandler hostHandler) { - this.user = user; - this.password = password; - this.jwt = jwt; - this.util = util; + protected VstCommunication(final ArangoConfig config, final HostHandler hostHandler) { + user = config.getUser(); + password = config.getPassword(); + jwt = config.getJwt(); + serde = config.getInternalSerde(); + chunksize = config.getChunkSize(); this.hostHandler = hostHandler; - this.chunksize = chunksize != null ? chunksize : ArangoDefaults.CHUNK_DEFAULT_CONTENT_SIZE; } @SuppressWarnings("unchecked") @@ -140,36 +135,36 @@ public void close() throws IOException { hostHandler.close(); } - public R execute(final Request request, final HostHandle hostHandle) throws ArangoDBException { + public R execute(final InternalRequest request, final HostHandle hostHandle) { return execute(request, hostHandle, 0); } - protected R execute(final Request request, final HostHandle hostHandle, final int attemptCount) throws ArangoDBException { + protected R execute(final InternalRequest request, final HostHandle hostHandle, final int attemptCount) { final C connection = connect(hostHandle, RequestUtils.determineAccessType(request)); return execute(request, connection, attemptCount); } - protected abstract R execute(final Request request, C connection) throws ArangoDBException; + protected abstract R execute(final InternalRequest request, C connection); - protected abstract R execute(final Request request, C connection, final int attemptCount) throws ArangoDBException; + protected abstract R execute(final InternalRequest request, C connection, final int attemptCount); - protected void checkError(final Response response) throws ArangoDBException { - ResponseUtils.checkError(util, response); + protected void checkError(final InternalResponse response) { + ResponseUtils.checkError(serde, response); } - protected Response createResponse(final Message message) throws VPackParserException { - final Response response = util.deserialize(message.getHead(), Response.class); + protected InternalResponse createResponse(final Message message) throws VPackParserException { + final InternalResponse response = serde.deserialize(message.getHead().toByteArray(), InternalResponse.class); if (message.getBody() != null) { - response.setBody(message.getBody()); + response.setBody(message.getBody().toByteArray()); } return response; } - protected final Message createMessage(final Request request) throws VPackParserException { + protected final Message createMessage(final InternalRequest request) throws VPackParserException { request.putHeaderParam("accept", "application/x-velocypack"); request.putHeaderParam("content-type", "application/x-velocypack"); final long id = mId.incrementAndGet(); - return new Message(id, util.serialize(request), request.getBody()); + return new Message(id, serde.serialize(request), request.getBody()); } protected Collection buildChunks(final Message message) { @@ -198,5 +193,4 @@ public void setJwt(String jwt) { this.jwt = jwt; } - } diff --git a/vst/src/main/java/com/arangodb/vst/VstCommunicationSync.java b/vst/src/main/java/com/arangodb/vst/VstCommunicationSync.java new file mode 100644 index 000000000..97b7671c7 --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/VstCommunicationSync.java @@ -0,0 +1,101 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.vst; + +import com.arangodb.ArangoDBException; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.ArangoDBRedirectException; +import com.arangodb.internal.net.HostHandle; +import com.arangodb.internal.net.HostHandler; +import com.arangodb.internal.util.HostUtils; +import com.arangodb.velocypack.exception.VPackParserException; +import com.arangodb.vst.internal.AuthenticationRequest; +import com.arangodb.vst.internal.JwtAuthenticationRequest; +import com.arangodb.vst.internal.Message; +import com.arangodb.vst.internal.VstConnectionSync; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Mark Vollmary + */ +public class VstCommunicationSync extends VstCommunication { + + private static final Logger LOGGER = LoggerFactory.getLogger(VstCommunicationSync.class); + + public VstCommunicationSync(final ArangoConfig config, final HostHandler hostHandler) { + super(config, hostHandler); + } + + @Override + protected InternalResponse execute(final InternalRequest request, final VstConnectionSync connection) { + return execute(request, connection, 0); + } + + @Override + protected InternalResponse execute(final InternalRequest request, final VstConnectionSync connection, final int attemptCount) { + try { + final Message requestMessage = createMessage(request); + if (LOGGER.isDebugEnabled()) { + String body = request.getBody() == null ? "" : serde.toJsonString(request.getBody()); + LOGGER.debug("Send Request [id={}]: {} {}", requestMessage.getId(), request, body); + } + final Message responseMessage = send(requestMessage, connection); + final InternalResponse response = createResponse(responseMessage); + if (LOGGER.isDebugEnabled()) { + String body = response.getBody() == null ? "" : serde.toJsonString(response.getBody()); + LOGGER.debug("Received Response [id={}]: {} {}", responseMessage.getId(), response, body); + } + checkError(response); + return response; + } catch (final VPackParserException e) { + throw new ArangoDBException(e); + } catch (final ArangoDBRedirectException e) { + if (attemptCount >= 3) { + throw e; + } + final String location = e.getLocation(); + final HostDescription redirectHost = HostUtils.createFromLocation(location); + hostHandler.failIfNotMatch(redirectHost, e); + return execute(request, new HostHandle().setHost(redirectHost), attemptCount + 1); + } + } + + private Message send(final Message message, final VstConnectionSync connection) { + return connection.write(message, buildChunks(message)); + } + + @Override + protected void authenticate(final VstConnectionSync connection) { + InternalRequest authRequest; + if (jwt != null) { + authRequest = new JwtAuthenticationRequest(jwt, ENCRYPTION_JWT); + } else { + authRequest = new AuthenticationRequest(user, password != null ? password : "", ENCRYPTION_PLAIN); + } + final InternalResponse response = execute(authRequest, connection); + checkError(response); + } + +} diff --git a/vst/src/main/java/com/arangodb/vst/VstConnectionFactorySync.java b/vst/src/main/java/com/arangodb/vst/VstConnectionFactorySync.java new file mode 100644 index 000000000..0ab5860aa --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/VstConnectionFactorySync.java @@ -0,0 +1,38 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.vst; + +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.Connection; +import com.arangodb.internal.net.ConnectionFactory; +import com.arangodb.vst.internal.VstConnectionSync; + +/** + * @author Mark Vollmary + */ +public class VstConnectionFactorySync implements ConnectionFactory { + + @Override + public Connection create(final ArangoConfig config, final HostDescription host) { + return new VstConnectionSync(config, host); + } +} diff --git a/vst/src/main/java/com/arangodb/vst/VstModule.java b/vst/src/main/java/com/arangodb/vst/VstModule.java new file mode 100644 index 000000000..255a041fd --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/VstModule.java @@ -0,0 +1,26 @@ +package com.arangodb.vst; + +import com.arangodb.vst.internal.AuthenticationRequest; +import com.arangodb.vst.internal.JwtAuthenticationRequest; +import com.fasterxml.jackson.databind.Module; +import com.fasterxml.jackson.databind.module.SimpleModule; + +import java.util.function.Supplier; + +enum VstModule implements Supplier { + INSTANCE; + + private final SimpleModule module; + + VstModule() { + module = new SimpleModule(); + module.addSerializer(AuthenticationRequest.class, VstSerializers.AUTHENTICATION_REQUEST); + module.addSerializer(JwtAuthenticationRequest.class, VstSerializers.JWT_AUTHENTICATION_REQUEST); + } + + @Override + public Module get() { + return module; + } + +} diff --git a/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java b/vst/src/main/java/com/arangodb/vst/VstProtocol.java similarity index 70% rename from src/main/java/com/arangodb/internal/velocystream/VstProtocol.java rename to vst/src/main/java/com/arangodb/vst/VstProtocol.java index 25de5edba..3642f1826 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstProtocol.java +++ b/vst/src/main/java/com/arangodb/vst/VstProtocol.java @@ -18,14 +18,13 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.velocystream; +package com.arangodb.vst; -import com.arangodb.ArangoDBException; import com.arangodb.internal.net.CommunicationProtocol; import com.arangodb.internal.net.HostHandle; -import com.arangodb.internal.velocystream.internal.VstConnectionSync; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; +import com.arangodb.vst.internal.VstConnectionSync; import java.io.IOException; @@ -34,15 +33,15 @@ */ public class VstProtocol implements CommunicationProtocol { - private final VstCommunication communication; + private final VstCommunication communication; - public VstProtocol(final VstCommunication communication) { + public VstProtocol(final VstCommunication communication) { super(); this.communication = communication; } @Override - public Response execute(final Request request, final HostHandle hostHandle) throws ArangoDBException { + public InternalResponse execute(final InternalRequest request, final HostHandle hostHandle) { return communication.execute(request, hostHandle); } diff --git a/vst/src/main/java/com/arangodb/vst/VstProtocolProvider.java b/vst/src/main/java/com/arangodb/vst/VstProtocolProvider.java new file mode 100644 index 000000000..8a6341fc7 --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/VstProtocolProvider.java @@ -0,0 +1,32 @@ +package com.arangodb.vst; + +import com.arangodb.Protocol; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.CommunicationProtocol; +import com.arangodb.internal.net.ConnectionFactory; +import com.arangodb.internal.net.HostHandler; +import com.arangodb.internal.net.ProtocolProvider; +import com.fasterxml.jackson.databind.Module; + +public class VstProtocolProvider implements ProtocolProvider { + @Override + public boolean supportsProtocol(Protocol protocol) { + return Protocol.VST.equals(protocol); + } + + @Override + public ConnectionFactory createConnectionFactory() { + return new VstConnectionFactorySync(); + } + + @Override + public CommunicationProtocol createProtocol(ArangoConfig config, HostHandler hostHandler) { + return new VstProtocol(new VstCommunicationSync(config, hostHandler)); + } + + @Override + public Module protocolModule() { + return VstModule.INSTANCE.get(); + } + +} diff --git a/vst/src/main/java/com/arangodb/vst/VstSerializers.java b/vst/src/main/java/com/arangodb/vst/VstSerializers.java new file mode 100644 index 000000000..72289ec42 --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/VstSerializers.java @@ -0,0 +1,40 @@ +package com.arangodb.vst; + +import com.arangodb.vst.internal.AuthenticationRequest; +import com.arangodb.vst.internal.JwtAuthenticationRequest; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +public final class VstSerializers { + + static final JsonSerializer AUTHENTICATION_REQUEST = + new JsonSerializer() { + @Override + public void serialize(AuthenticationRequest value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeStartArray(); + gen.writeNumber(value.getVersion()); + gen.writeNumber(value.getType()); + gen.writeString(value.getEncryption()); + gen.writeString(value.getUser()); + gen.writeString(value.getPassword()); + gen.writeEndArray(); + } + }; + static final JsonSerializer JWT_AUTHENTICATION_REQUEST = + new JsonSerializer() { + @Override + public void serialize(JwtAuthenticationRequest value, JsonGenerator gen, + SerializerProvider serializers) throws IOException { + gen.writeStartArray(); + gen.writeNumber(value.getVersion()); + gen.writeNumber(value.getType()); + gen.writeString(value.getEncryption()); + gen.writeString(value.getToken()); + gen.writeEndArray(); + } + }; + +} diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/vst/src/main/java/com/arangodb/vst/async/VstCommunicationAsync.java similarity index 54% rename from src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java rename to vst/src/main/java/com/arangodb/vst/async/VstCommunicationAsync.java index 38acb45be..c787c0cbf 100644 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java +++ b/vst/src/main/java/com/arangodb/vst/async/VstCommunicationAsync.java @@ -18,56 +18,61 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.async.internal.velocystream; +package com.arangodb.vst.async; import com.arangodb.ArangoDBException; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.InternalRequest; +import com.arangodb.internal.InternalResponse; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.ArangoDBRedirectException; -import com.arangodb.internal.net.HostDescription; +import com.arangodb.internal.net.AsyncCommunication; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; import com.arangodb.internal.util.HostUtils; -import com.arangodb.internal.velocystream.VstCommunication; -import com.arangodb.internal.velocystream.internal.AuthenticationRequest; -import com.arangodb.internal.velocystream.internal.JwtAuthenticationRequest; -import com.arangodb.internal.velocystream.internal.Message; -import com.arangodb.util.ArangoSerialization; import com.arangodb.velocypack.exception.VPackException; import com.arangodb.velocypack.exception.VPackParserException; -import com.arangodb.velocystream.Request; -import com.arangodb.velocystream.Response; +import com.arangodb.vst.VstCommunication; +import com.arangodb.vst.internal.AuthenticationRequest; +import com.arangodb.vst.internal.JwtAuthenticationRequest; +import com.arangodb.vst.internal.Message; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.net.ssl.SSLContext; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; /** * @author Mark Vollmary */ -public class VstCommunicationAsync extends VstCommunication, VstConnectionAsync> { +public class VstCommunicationAsync + extends VstCommunication, VstConnectionAsync> + implements AsyncCommunication { private static final Logger LOGGER = LoggerFactory.getLogger(VstCommunicationAsync.class); - private VstCommunicationAsync(final HostHandler hostHandler, final Integer timeout, final String user, - final String password, final String jwt, final Boolean useSsl, final SSLContext sslContext, final ArangoSerialization util, - final Integer chunksize, final Integer maxConnections, final Long connectionTtl) { - super(timeout, user, password, jwt, useSsl, sslContext, util, chunksize, hostHandler); + public VstCommunicationAsync(ArangoConfig config, HostHandler hostHandler) { + super(config, hostHandler); } @Override - protected CompletableFuture execute(final Request request, final VstConnectionAsync connection) { + protected CompletableFuture execute(final InternalRequest request, final VstConnectionAsync connection) { return execute(request, connection, 0); } @Override - protected CompletableFuture execute(final Request request, final VstConnectionAsync connection, final int attemptCount) { - final CompletableFuture rfuture = new CompletableFuture<>(); + protected CompletableFuture execute(final InternalRequest request, final VstConnectionAsync connection, + final int attemptCount) { + final CompletableFuture rfuture = new CompletableFuture<>(); try { final Message message = createMessage(request); + if (LOGGER.isDebugEnabled()) { + String body = request.getBody() == null ? "" : serde.toJsonString(request.getBody()); + LOGGER.debug("Send Request [id={}]: {} {}", message.getId(), request, body); + } send(message, connection).whenComplete((m, ex) -> { if (m != null) { - final Response response; + final InternalResponse response; try { response = createResponse(m); } catch (final VPackParserException e) { @@ -100,6 +105,10 @@ protected CompletableFuture execute(final Request request, final VstCo } catch (ArangoDBException e) { rfuture.completeExceptionally(e); } + if (LOGGER.isDebugEnabled()) { + String body = response.getBody() == null ? "" : serde.toJsonString(response.getBody()); + LOGGER.debug("Received Response [id={}]: {} {}", m.getId(), response, body); + } rfuture.complete(response); } else if (ex != null) { LOGGER.error(ex.getMessage(), ex); @@ -116,26 +125,25 @@ protected CompletableFuture execute(final Request request, final VstCo } private CompletableFuture send(final Message message, final VstConnectionAsync connection) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Send Message (id=%s, head=%s, body=%s)", message.getId(), message.getHead(), - message.getBody() != null ? message.getBody() : "{}")); - } return connection.write(message, buildChunks(message)); } @Override protected void authenticate(final VstConnectionAsync connection) { - Request authRequest; + InternalRequest authRequest; if (jwt != null) { authRequest = new JwtAuthenticationRequest(jwt, ENCRYPTION_JWT); } else { authRequest = new AuthenticationRequest(user, password != null ? password : "", ENCRYPTION_PLAIN); } - Response response; + InternalResponse response; try { response = execute(authRequest, connection).get(); - } catch (final InterruptedException | ExecutionException e) { + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ArangoDBException(e); + } catch (final ExecutionException e) { Throwable cause = e.getCause(); if (cause instanceof ArangoDBException) { throw (ArangoDBException) cause; @@ -146,73 +154,4 @@ protected void authenticate(final VstConnectionAsync connection) { checkError(response); } - public static class Builder { - - private final HostHandler hostHandler; - private Integer timeout; - private Long connectionTtl; - private String user; - private String password; - private String jwt; - private Boolean useSsl; - private SSLContext sslContext; - private Integer chunksize; - private Integer maxConnections; - - public Builder(final HostHandler hostHandler) { - super(); - this.hostHandler = hostHandler; - } - - public Builder timeout(final Integer timeout) { - this.timeout = timeout; - return this; - } - - public Builder user(final String user) { - this.user = user; - return this; - } - - public Builder password(final String password) { - this.password = password; - return this; - } - - public Builder jwt(final String jwt) { - this.jwt = jwt; - return this; - } - - public Builder useSsl(final Boolean useSsl) { - this.useSsl = useSsl; - return this; - } - - public Builder sslContext(final SSLContext sslContext) { - this.sslContext = sslContext; - return this; - } - - public Builder chunksize(final Integer chunksize) { - this.chunksize = chunksize; - return this; - } - - public Builder maxConnections(final Integer maxConnections) { - this.maxConnections = maxConnections; - return this; - } - - public Builder connectionTtl(final Long connectionTtl) { - this.connectionTtl = connectionTtl; - return this; - } - - public VstCommunicationAsync build(final ArangoSerialization util) { - return new VstCommunicationAsync(hostHandler, timeout, user, password, jwt, useSsl, sslContext, util, chunksize, - maxConnections, connectionTtl); - } - } - } diff --git a/vst/src/main/java/com/arangodb/vst/async/VstConnectionAsync.java b/vst/src/main/java/com/arangodb/vst/async/VstConnectionAsync.java new file mode 100644 index 000000000..41e6265d3 --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/async/VstConnectionAsync.java @@ -0,0 +1,69 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.vst.async; + +import com.arangodb.async.internal.utils.CompletableFutureUtils; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.vst.internal.Chunk; +import com.arangodb.vst.internal.Message; +import com.arangodb.vst.internal.VstConnection; + +import java.util.Collection; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + +/** + * @author Mark Vollmary + */ +public class VstConnectionAsync extends VstConnection> { + + VstConnectionAsync(final ArangoConfig config, final HostDescription host) { + super(config, host); + } + + @Override + public synchronized CompletableFuture write(final Message message, final Collection chunks) { + final CompletableFuture future = new CompletableFuture<>(); + final FutureTask task = new FutureTask<>(() -> { + try { + future.complete(messageStore.get(message.getId())); + } catch (final Exception e) { + future.completeExceptionally(e); + } + return null; + }); + messageStore.storeMessage(message.getId(), task); + super.writeIntern(message, chunks); + if (timeout == null || timeout == 0L) { + return future; + } else { + return CompletableFutureUtils.orTimeout(future, timeout, TimeUnit.MILLISECONDS); + } + } + + @Override + protected void doKeepAlive() { + sendKeepAlive().join(); + } + +} diff --git a/vst/src/main/java/com/arangodb/vst/async/VstConnectionFactoryAsync.java b/vst/src/main/java/com/arangodb/vst/async/VstConnectionFactoryAsync.java new file mode 100644 index 000000000..3c02a24fd --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/async/VstConnectionFactoryAsync.java @@ -0,0 +1,37 @@ +/* + * DISCLAIMER + * + * Copyright 2018 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.vst.async; + +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; +import com.arangodb.internal.net.Connection; +import com.arangodb.internal.net.ConnectionFactory; + +/** + * @author Mark Vollmary + */ +public class VstConnectionFactoryAsync implements ConnectionFactory { + + @Override + public Connection create(final ArangoConfig config, final HostDescription host) { + return new VstConnectionAsync(config, host); + } +} diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java b/vst/src/main/java/com/arangodb/vst/internal/AuthenticationRequest.java similarity index 86% rename from src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java rename to vst/src/main/java/com/arangodb/vst/internal/AuthenticationRequest.java index 9d47bc548..e57217011 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/AuthenticationRequest.java +++ b/vst/src/main/java/com/arangodb/vst/internal/AuthenticationRequest.java @@ -1,55 +1,55 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream.internal; - -import com.arangodb.DbName; -import com.arangodb.velocystream.Request; - -/** - * @author Mark Vollmary - */ -public class AuthenticationRequest extends Request { - - private final String user; - private final String password; - private final String encryption;// "plain" - - public AuthenticationRequest(final String user, final String password, final String encryption) { - super(DbName.of(null), null, null); - this.user = user; - this.password = password; - this.encryption = encryption; - setType(1000); - } - - public String getUser() { - return user; - } - - public String getPassword() { - return password; - } - - public String getEncryption() { - return encryption; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.vst.internal; + +import com.arangodb.DbName; +import com.arangodb.internal.InternalRequest; + +/** + * @author Mark Vollmary + */ +public class AuthenticationRequest extends InternalRequest { + + private final String user; + private final String password; + private final String encryption;// "plain" + + public AuthenticationRequest(final String user, final String password, final String encryption) { + super(DbName.of(null), null, null); + this.user = user; + this.password = password; + this.encryption = encryption; + setType(1000); + } + + public String getUser() { + return user; + } + + public String getPassword() { + return password; + } + + public String getEncryption() { + return encryption; + } + +} diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/Chunk.java b/vst/src/main/java/com/arangodb/vst/internal/Chunk.java similarity index 94% rename from src/main/java/com/arangodb/internal/velocystream/internal/Chunk.java rename to vst/src/main/java/com/arangodb/vst/internal/Chunk.java index 4b0689e93..93e2d7848 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/Chunk.java +++ b/vst/src/main/java/com/arangodb/vst/internal/Chunk.java @@ -1,88 +1,88 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream.internal; - -/** - * @author Mark Vollmary - */ -public class Chunk { - - private final long messageId; - private final long messageLength; - private final int chunkX; - private final int contentOffset; - private final int contentLength; - - public Chunk(final long messageId, final int chunkX, final long messageLength, final int contentOffset, - final int contentLength) { - this.messageId = messageId; - this.chunkX = chunkX; - this.messageLength = messageLength; - this.contentOffset = contentOffset; - this.contentLength = contentLength; - } - - public Chunk(final long messageId, final int chunkIndex, final int numberOfChunks, final long messageLength, - final int contentOffset, final int contentLength) { - this(messageId, chunkX(chunkIndex, numberOfChunks), messageLength, contentOffset, contentLength); - } - - private static int chunkX(final int chunkIndex, final int numberOfChunks) { - int chunkX; - if (numberOfChunks == 1) { - chunkX = 3;// last byte: 0000 0011 - } else if (chunkIndex == 0) { - chunkX = (numberOfChunks << 1) + 1; - } else { - chunkX = chunkIndex << 1; - } - return chunkX; - } - - public long getMessageId() { - return messageId; - } - - public long getMessageLength() { - return messageLength; - } - - public boolean isFirstChunk() { - return 1 == (chunkX & 0x1); - } - - public int getChunk() { - return chunkX >> 1; - } - - public int getChunkX() { - return chunkX; - } - - public int getContentOffset() { - return contentOffset; - } - - public int getContentLength() { - return contentLength; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.vst.internal; + +/** + * @author Mark Vollmary + */ +public class Chunk { + + private final long messageId; + private final long messageLength; + private final int chunkX; + private final int contentOffset; + private final int contentLength; + + public Chunk(final long messageId, final int chunkX, final long messageLength, final int contentOffset, + final int contentLength) { + this.messageId = messageId; + this.chunkX = chunkX; + this.messageLength = messageLength; + this.contentOffset = contentOffset; + this.contentLength = contentLength; + } + + public Chunk(final long messageId, final int chunkIndex, final int numberOfChunks, final long messageLength, + final int contentOffset, final int contentLength) { + this(messageId, chunkX(chunkIndex, numberOfChunks), messageLength, contentOffset, contentLength); + } + + private static int chunkX(final int chunkIndex, final int numberOfChunks) { + int chunkX; + if (numberOfChunks == 1) { + chunkX = 3;// last byte: 0000 0011 + } else if (chunkIndex == 0) { + chunkX = (numberOfChunks << 1) + 1; + } else { + chunkX = chunkIndex << 1; + } + return chunkX; + } + + public long getMessageId() { + return messageId; + } + + public long getMessageLength() { + return messageLength; + } + + public boolean isFirstChunk() { + return 1 == (chunkX & 0x1); + } + + public int getChunk() { + return chunkX >> 1; + } + + public int getChunkX() { + return chunkX; + } + + public int getContentOffset() { + return contentOffset; + } + + public int getContentLength() { + return contentLength; + } + +} diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/ChunkStore.java b/vst/src/main/java/com/arangodb/vst/internal/ChunkStore.java similarity index 94% rename from src/main/java/com/arangodb/internal/velocystream/internal/ChunkStore.java rename to vst/src/main/java/com/arangodb/vst/internal/ChunkStore.java index e636b9e68..a945ec79d 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/ChunkStore.java +++ b/vst/src/main/java/com/arangodb/vst/internal/ChunkStore.java @@ -1,70 +1,70 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream.internal; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.HashMap; -import java.util.Map; - -/** - * @author Mark Vollmary - */ -public class ChunkStore { - - private final MessageStore messageStore; - private final Map data; - - public ChunkStore(final MessageStore messageStore) { - super(); - this.messageStore = messageStore; - data = new HashMap<>(); - } - - public ByteBuffer storeChunk(final Chunk chunk) throws BufferUnderflowException, IndexOutOfBoundsException { - final long messageId = chunk.getMessageId(); - ByteBuffer chunkBuffer = data.get(messageId); - if (chunkBuffer == null) { - if (!chunk.isFirstChunk()) { - messageStore.cancel(messageId); - return null; - } - final int length = (int) (chunk.getMessageLength() > 0 ? chunk.getMessageLength() - : chunk.getContentLength()); - chunkBuffer = ByteBuffer.allocate(length); - data.put(messageId, chunkBuffer); - } - return chunkBuffer; - } - - public void checkCompleteness(final long messageId) { - checkCompleteness(messageId, data.get(messageId)); - } - - private void checkCompleteness(final long messageId, final ByteBuffer chunkBuffer) - throws BufferUnderflowException, IndexOutOfBoundsException { - if (chunkBuffer.position() == chunkBuffer.limit()) { - messageStore.consume(new Message(messageId, chunkBuffer.array())); - data.remove(messageId); - } - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.vst.internal; + +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Mark Vollmary + */ +public class ChunkStore { + + private final MessageStore messageStore; + private final Map data; + + public ChunkStore(final MessageStore messageStore) { + super(); + this.messageStore = messageStore; + data = new HashMap<>(); + } + + public ByteBuffer storeChunk(final Chunk chunk) throws BufferUnderflowException, IndexOutOfBoundsException { + final long messageId = chunk.getMessageId(); + ByteBuffer chunkBuffer = data.get(messageId); + if (chunkBuffer == null) { + if (!chunk.isFirstChunk()) { + messageStore.cancel(messageId); + return null; + } + final int length = (int) (chunk.getMessageLength() > 0 ? chunk.getMessageLength() + : chunk.getContentLength()); + chunkBuffer = ByteBuffer.allocate(length); + data.put(messageId, chunkBuffer); + } + return chunkBuffer; + } + + public void checkCompleteness(final long messageId) { + checkCompleteness(messageId, data.get(messageId)); + } + + private void checkCompleteness(final long messageId, final ByteBuffer chunkBuffer) + throws BufferUnderflowException, IndexOutOfBoundsException { + if (chunkBuffer.position() == chunkBuffer.limit()) { + messageStore.consume(new Message(messageId, chunkBuffer.array())); + data.remove(messageId); + } + } + +} diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java b/vst/src/main/java/com/arangodb/vst/internal/JwtAuthenticationRequest.java similarity index 75% rename from src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java rename to vst/src/main/java/com/arangodb/vst/internal/JwtAuthenticationRequest.java index c2ccf53b3..982ee32df 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/JwtAuthenticationRequest.java +++ b/vst/src/main/java/com/arangodb/vst/internal/JwtAuthenticationRequest.java @@ -1,9 +1,9 @@ -package com.arangodb.internal.velocystream.internal; +package com.arangodb.vst.internal; import com.arangodb.DbName; -import com.arangodb.velocystream.Request; +import com.arangodb.internal.InternalRequest; -public class JwtAuthenticationRequest extends Request { +public class JwtAuthenticationRequest extends InternalRequest { private final String token; private final String encryption; // "jwt" diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/Message.java b/vst/src/main/java/com/arangodb/vst/internal/Message.java similarity index 86% rename from src/main/java/com/arangodb/internal/velocystream/internal/Message.java rename to vst/src/main/java/com/arangodb/vst/internal/Message.java index 6ad13259c..7b673fb68 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/Message.java +++ b/vst/src/main/java/com/arangodb/vst/internal/Message.java @@ -1,67 +1,67 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream.internal; - -import com.arangodb.velocypack.VPackSlice; - -import java.nio.BufferUnderflowException; - -/** - * @author Mark Vollmary - */ -public class Message { - - private final long id; - private final VPackSlice head; - private final VPackSlice body; - - public Message(final long id, final byte[] chunkBuffer) throws BufferUnderflowException, IndexOutOfBoundsException { - super(); - this.id = id; - head = new VPackSlice(chunkBuffer); - final int headSize = head.getByteSize(); - if (chunkBuffer.length > headSize) { - body = new VPackSlice(chunkBuffer, headSize); - } else { - body = null; - } - } - - public Message(final long id, final VPackSlice head, final VPackSlice body) { - super(); - this.id = id; - this.head = head; - this.body = body; - } - - public long getId() { - return id; - } - - public VPackSlice getHead() { - return head; - } - - public VPackSlice getBody() { - return body; - } - -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.vst.internal; + +import com.arangodb.velocypack.VPackSlice; + +import java.nio.BufferUnderflowException; + +/** + * @author Mark Vollmary + */ +public class Message { + + private final long id; + private final VPackSlice head; + private final VPackSlice body; + + public Message(final long id, final byte[] chunkBuffer) throws BufferUnderflowException, IndexOutOfBoundsException { + super(); + this.id = id; + head = new VPackSlice(chunkBuffer); + final int headSize = head.getByteSize(); + if (chunkBuffer.length > headSize) { + body = new VPackSlice(chunkBuffer, headSize); + } else { + body = null; + } + } + + public Message(final long id, final byte[] head, final byte[] body) { + super(); + this.id = id; + this.head = new VPackSlice(head); + this.body = body != null ? new VPackSlice(body) : null; + } + + public long getId() { + return id; + } + + public VPackSlice getHead() { + return head; + } + + public VPackSlice getBody() { + return body; + } + +} diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java b/vst/src/main/java/com/arangodb/vst/internal/MessageStore.java similarity index 84% rename from src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java rename to vst/src/main/java/com/arangodb/vst/internal/MessageStore.java index 657b17bfa..7e8417205 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java +++ b/vst/src/main/java/com/arangodb/vst/internal/MessageStore.java @@ -1,112 +1,108 @@ -/* - * DISCLAIMER - * - * Copyright 2016 ArangoDB GmbH, Cologne, Germany - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright holder is ArangoDB GmbH, Cologne, Germany - */ - -package com.arangodb.internal.velocystream.internal; - -import com.arangodb.ArangoDBException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.FutureTask; - -/** - * @author Mark Vollmary - */ -public class MessageStore { - - private static final Logger LOGGER = LoggerFactory.getLogger(MessageStore.class); - - private final Map> task; - private final Map response; - private final Map error; - - public MessageStore() { - super(); - task = new ConcurrentHashMap<>(); - response = new ConcurrentHashMap<>(); - error = new ConcurrentHashMap<>(); - } - - public void storeMessage(final long messageId, final FutureTask future) { - task.put(messageId, future); - } - - public void consume(final Message message) { - final FutureTask future = task.remove(message.getId()); - if (future != null) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Received Message (id=%s, head=%s, body=%s)", message.getId(), - message.getHead(), message.getBody() != null ? message.getBody() : "{}")); - } - response.put(message.getId(), message); - future.run(); - } - } - - public Message get(final long messageId) throws ArangoDBException { - final Message result = response.remove(messageId); - if (result == null) { - final Exception e = error.remove(messageId); - if (e != null) { - throw new ArangoDBException(e); - } - } - return result; - } - - public void cancel(final long messageId) { - final FutureTask future = task.remove(messageId); - if (future != null) { - LOGGER.error(String.format("Cancel Message unexpected (id=%s).", messageId)); - future.cancel(true); - } - } - - public synchronized void clear(final Exception e) { - if (!task.isEmpty()) { - LOGGER.error(e.getMessage(), e); - } - for (final Entry> entry : task.entrySet()) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Exceptionally complete Message (id=%s).", entry.getKey())); - } - error.put(entry.getKey(), e); - entry.getValue().run(); - } - task.clear(); - } - - public synchronized void clear() { - for (final Entry> entry : task.entrySet()) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Cancel Message (id=%s).", entry.getKey())); - } - entry.getValue().cancel(true); - } - task.clear(); - } - - public boolean isEmpty() { - return task.isEmpty(); - } -} +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.vst.internal; + +import com.arangodb.ArangoDBException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.FutureTask; + +/** + * @author Mark Vollmary + */ +public class MessageStore { + + private static final Logger LOGGER = LoggerFactory.getLogger(MessageStore.class); + + private final Map> task; + private final Map response; + private final Map error; + + public MessageStore() { + super(); + task = new ConcurrentHashMap<>(); + response = new ConcurrentHashMap<>(); + error = new ConcurrentHashMap<>(); + } + + public void storeMessage(final long messageId, final FutureTask future) { + task.put(messageId, future); + } + + public void consume(final Message message) { + final FutureTask future = task.remove(message.getId()); + if (future != null) { + response.put(message.getId(), message); + future.run(); + } + } + + public Message get(final long messageId) { + final Message result = response.remove(messageId); + if (result == null) { + final Exception e = error.remove(messageId); + if (e != null) { + throw new ArangoDBException(e); + } + } + return result; + } + + public void cancel(final long messageId) { + final FutureTask future = task.remove(messageId); + if (future != null) { + LOGGER.error("Cancel Message unexpected (id={}).", messageId); + future.cancel(true); + } + } + + public synchronized void clear(final Exception e) { + if (!task.isEmpty()) { + LOGGER.error(e.getMessage(), e); + } + for (final Entry> entry : task.entrySet()) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(String.format("Exceptionally complete Message (id=%s).", entry.getKey())); + } + error.put(entry.getKey(), e); + entry.getValue().run(); + } + task.clear(); + } + + public synchronized void clear() { + for (final Entry> entry : task.entrySet()) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(String.format("Cancel Message (id=%s).", entry.getKey())); + } + entry.getValue().cancel(true); + } + task.clear(); + } + + public boolean isEmpty() { + return task.isEmpty(); + } +} diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java b/vst/src/main/java/com/arangodb/vst/internal/VstConnection.java similarity index 88% rename from src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java rename to vst/src/main/java/com/arangodb/vst/internal/VstConnection.java index 266820773..59ce03e0c 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java +++ b/vst/src/main/java/com/arangodb/vst/internal/VstConnection.java @@ -18,12 +18,13 @@ * Copyright holder is ArangoDB GmbH, Cologne, Germany */ -package com.arangodb.internal.velocystream.internal; +package com.arangodb.vst.internal; import com.arangodb.ArangoDBException; +import com.arangodb.config.HostDescription; import com.arangodb.internal.ArangoDefaults; +import com.arangodb.internal.config.ArangoConfig; import com.arangodb.internal.net.Connection; -import com.arangodb.internal.net.HostDescription; import com.arangodb.velocypack.VPackBuilder; import com.arangodb.velocypack.VPackSlice; import com.arangodb.velocypack.ValueType; @@ -46,12 +47,7 @@ import java.util.Collections; import java.util.Date; import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicLong; /** @@ -60,34 +56,17 @@ public abstract class VstConnection implements Connection { private static final Logger LOGGER = LoggerFactory.getLogger(VstConnection.class); private static final byte[] PROTOCOL_HEADER = "VST/1.0\r\n\r\n".getBytes(); - - private ExecutorService executor; - - private ScheduledExecutorService keepAliveScheduler; - private final AtomicLong keepAliveId = new AtomicLong(); - - protected final MessageStore messageStore; - + protected final MessageStore messageStore = new MessageStore(); protected final Integer timeout; + private final AtomicLong keepAliveId = new AtomicLong(); private final Long ttl; - private final Integer keepAliveInterval; - private int keepAliveFailCounter = 0; - private final Boolean useSsl; private final SSLContext sslContext; - - private Socket socket; - private OutputStream outputStream; - private InputStream inputStream; - private final HostDescription host; - private final Map sendTimestamps = new ConcurrentHashMap<>(); - private final String connectionName; - - private final VPackSlice keepAliveRequest = new VPackBuilder() + private final byte[] keepAliveRequest = new VPackBuilder() .add(ValueType.ARRAY) .add(1) .add(1) @@ -99,23 +78,23 @@ public abstract class VstConnection implements Connection { .add(ValueType.OBJECT) .close() .close() - .slice(); + .slice() + .toByteArray(); + private ExecutorService executor; + private ScheduledExecutorService keepAliveScheduler; + private int keepAliveFailCounter = 0; + private Socket socket; + private OutputStream outputStream; + private InputStream inputStream; - protected VstConnection(final HostDescription host, - final Integer timeout, - final Long ttl, - final Integer keepAliveInterval, - final Boolean useSsl, - final SSLContext sslContext, - final MessageStore messageStore) { + protected VstConnection(final ArangoConfig config, final HostDescription host) { super(); + timeout = config.getTimeout(); + ttl = config.getConnectionTtl(); + keepAliveInterval = config.getKeepAliveInterval(); + useSsl = config.getUseSsl(); + sslContext = config.getSslContext(); this.host = host; - this.timeout = timeout; - this.ttl = ttl; - this.keepAliveInterval = keepAliveInterval; - this.useSsl = useSsl; - this.sslContext = sslContext; - this.messageStore = messageStore; connectionName = "connection_" + System.currentTimeMillis() + "_" + Math.random(); LOGGER.debug("[" + connectionName + "]: Connection created"); @@ -125,12 +104,13 @@ protected T sendKeepAlive() { long id = keepAliveId.decrementAndGet(); Message message = new Message(id, keepAliveRequest, null); if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("[%s]: Send keepalive probe (id=%s, head=%s, body=%s)", connectionName, message.getId(), message.getHead(), + LOGGER.debug(String.format("[%s]: Send keepalive probe (id=%s, head=%s, body=%s)", connectionName, + message.getId(), message.getHead(), message.getBody() != null ? message.getBody() : "{}")); } return write(message, Collections.singleton(new Chunk( id, 0, 1, -1, - 0, keepAliveRequest.getByteSize() + 0, keepAliveRequest.length ))); } @@ -164,7 +144,7 @@ public synchronized void open() throws IOException { if (LOGGER.isDebugEnabled()) { LOGGER.debug(String.format("[%s]: Open connection to %s", connectionName, host)); } - if (Boolean.TRUE == useSsl) { + if (Boolean.TRUE.equals(useSsl)) { if (sslContext != null) { socket = sslContext.getSocketFactory().createSocket(); } else { @@ -173,7 +153,7 @@ public synchronized void open() throws IOException { } else { socket = SocketFactory.getDefault().createSocket(); } - socket.connect(new InetSocketAddress(host.getHost(), host.getPort()), timeout != null ? timeout : ArangoDefaults.DEFAULT_TIMEOUT); + socket.connect(new InetSocketAddress(host.getHost(), host.getPort()), timeout); socket.setKeepAlive(true); socket.setTcpNoDelay(true); if (LOGGER.isDebugEnabled()) { @@ -183,7 +163,7 @@ public synchronized void open() throws IOException { outputStream = new BufferedOutputStream(socket.getOutputStream()); inputStream = socket.getInputStream(); - if (Boolean.TRUE == useSsl) { + if (Boolean.TRUE.equals(useSsl)) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(String.format("[%s]: Start Handshake on %s", connectionName, socket)); } @@ -265,12 +245,12 @@ private synchronized void sendProtocolHeader() throws IOException { outputStream.flush(); } - protected synchronized void writeIntern(final Message message, final Collection chunks) - throws ArangoDBException { + protected synchronized void writeIntern(final Message message, final Collection chunks) { for (final Chunk chunk : chunks) { try { if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("[%s]: Send chunk %s:%s from message %s", connectionName, chunk.getChunk(), + LOGGER.debug(String.format("[%s]: Send chunk %s:%s from message %s", connectionName, + chunk.getChunk(), chunk.isFirstChunk() ? 1 : 0, chunk.getMessageId())); sendTimestamps.put(chunk.getMessageId(), System.currentTimeMillis()); } @@ -328,7 +308,8 @@ protected Chunk readChunk() throws IOException { final Chunk chunk = new Chunk(messageId, chunkX, messageLength, 0, contentLength); if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("[%s]: Received chunk %s:%s from message %s", connectionName, chunk.getChunk(), chunk.isFirstChunk() ? 1 : 0, chunk.getMessageId())); + LOGGER.debug(String.format("[%s]: Received chunk %s:%s from message %s", connectionName, chunk.getChunk() + , chunk.isFirstChunk() ? 1 : 0, chunk.getMessageId())); LOGGER.debug("[" + connectionName + "]: Responsetime for Message " + chunk.getMessageId() + " is " + (System.currentTimeMillis() - sendTimestamps.get(chunk.getMessageId()))); } diff --git a/vst/src/main/java/com/arangodb/vst/internal/VstConnectionSync.java b/vst/src/main/java/com/arangodb/vst/internal/VstConnectionSync.java new file mode 100644 index 000000000..28a8bcd89 --- /dev/null +++ b/vst/src/main/java/com/arangodb/vst/internal/VstConnectionSync.java @@ -0,0 +1,63 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.vst.internal; + +import com.arangodb.ArangoDBException; +import com.arangodb.config.HostDescription; +import com.arangodb.internal.config.ArangoConfig; + +import java.util.Collection; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + +/** + * @author Mark Vollmary + */ +public class VstConnectionSync extends VstConnection { + + public VstConnectionSync(final ArangoConfig config, final HostDescription host) { + super(config, host); + } + + @Override + public Message write(final Message message, final Collection chunks) { + final FutureTask task = new FutureTask<>(() -> messageStore.get(message.getId())); + messageStore.storeMessage(message.getId(), task); + super.writeIntern(message, chunks); + try { + return timeout == null || timeout == 0L ? task.get() : task.get(timeout, TimeUnit.MILLISECONDS); + } catch (final ExecutionException e) { + throw ArangoDBException.wrap(e.getCause()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ArangoDBException(e); + } catch (final Exception e) { + throw ArangoDBException.wrap(e); + } + } + + @Override + protected void doKeepAlive() { + sendKeepAlive(); + } + +} diff --git a/vst/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider b/vst/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider new file mode 100644 index 000000000..dc7f09560 --- /dev/null +++ b/vst/src/main/resources/META-INF/services/com.arangodb.internal.net.AsyncProtocolProvider @@ -0,0 +1 @@ +com.arangodb.vst.VstAsyncProtocolProvider diff --git a/vst/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider b/vst/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider new file mode 100644 index 000000000..6d11ca0c7 --- /dev/null +++ b/vst/src/main/resources/META-INF/services/com.arangodb.internal.net.ProtocolProvider @@ -0,0 +1 @@ +com.arangodb.vst.VstProtocolProvider