[
  {
    "path": ".git-blame-ignore-revs",
    "content": "8f35f73471d06957498b5fc09dd83ceb49fd342b\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "/.github/ @michael-simons @meistermeier\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: true\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n- package-ecosystem: maven\n  directory: \"/\"\n  schedule:\n    interval: weekly\n    time: \"04:00\"\n  open-pull-requests-limit: 10\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: build\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build:\n    name: Neo4j Cypher-DSL\n    runs-on: ubuntu-latest\n    outputs:\n      revision: ${{ steps.revision_step.outputs.revision }}\n    steps:\n      - uses: actions/checkout@v4\n      - name: Set up JDK\n        uses: actions/setup-java@v4\n        with:\n          distribution: zulu\n          java-version: 25\n      - name: Enable Sonar for local PRs not from Dependabot\n        if:  ${{ github.event.sender.login != 'dependabot[bot]' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }}\n        run: echo \"USE_SONAR=sonar\" >> $GITHUB_ENV\n      - name: Disable Sonar for foreign PRs or from Dependabot\n        if:  ${{ github.event.sender.login == 'dependabot[bot]' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }}\n        run: echo \"USE_SONAR=-sonar\" >> $GITHUB_ENV\n      - name: Determine revision\n        id: revision_step\n        run: |\n          REVISION=$(./bin/extract-version.sh)\n          echo \"REVISION=$REVISION\" >> $GITHUB_ENV\n          echo \"OLD_VERSION=$(./bin/extract-version.sh latest)\" >> $GITHUB_ENV\n          echo \"::set-output name=revision::$REVISION\"\n      - name: Cache SonarCloud packages\n        uses: actions/cache@v3\n        with:\n          path: ~/.sonar/cache\n          key: ${{ runner.os }}-sonar\n          restore-keys: ${{ runner.os }}-sonar\n      - name: Cache Maven packages\n        uses: actions/cache@v3\n        with:\n          path: ~/.m2\n          key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}\n          restore-keys: ${{ runner.os }}-m2\n      - name: Run Maven build\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}\n        run: >\n          ./mvnw --no-transfer-progress clean deploy -DSCHEMA_NAMES_TEST_ALL_VERSIONS=false -P$USE_SONAR -Drevision=$REVISION -Dsha1=-$GITHUB_SHA -Dchangelist= -Dcypher-dsl.version.old=$OLD_VERSION\n          -DaltDeploymentRepository=releases::default::file://$GITHUB_WORKSPACE/target/repository\n          -pl !org.neo4j:neo4j-cypher-dsl-native-tests\n          -pl !org.neo4j:neo4j-cypher-dsl-examples-core\n          -pl !org.neo4j:neo4j-cypher-dsl-examples-parser\n          -pl !org.neo4j:neo4j-cypher-dsl-examples-ogm-quarkus\n          -pl !org.neo4j:neo4j-cypher-dsl-examples-sdn6\n      - name: Archive artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: artifacts\n          path: target/repository\n\n  test_native:\n    name: Verify compilation on GraalVM native\n    runs-on: ubuntu-latest\n    needs: build\n    steps:\n      - uses: graalvm/setup-graalvm@v1\n        with:\n          distribution: 'graalvm-community'\n          java-version: 25\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n      - name: Determine revision\n        run: echo \"REVISION=${{ needs.build.outputs.revision }}\" >> $GITHUB_ENV\n      - uses: actions/checkout@v4\n      - name: Download artifacts\n        uses: actions/download-artifact@v4\n        with:\n          name: artifacts\n          path: repository\n      - name: Install dependencies\n        run: \"mkdir -p ~/.m2 && mv $GITHUB_WORKSPACE/repository ~/.m2\"\n      - name: Run Maven build\n        run: >\n          ./mvnw --no-transfer-progress clean verify -Djqassistant.skip=true -Drevision=$REVISION -Dsha1=-$GITHUB_SHA -Dchangelist=\n          -pl org.neo4j:neo4j-cypher-dsl-native-tests\n\n  build_examples:\n    name: Verify examples with ${{ matrix.java }}\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        java: [ '17', '21', '25' ]\n    needs: build\n    steps:\n      - name: Determine revision\n        run: echo \"REVISION=${{ needs.build.outputs.revision }}\" >> $GITHUB_ENV\n      - uses: actions/checkout@v4\n      - name: Download artifacts\n        uses: actions/download-artifact@v4\n        with:\n          name: artifacts\n          path: repository\n      - name: Install dependencies\n        run: \"mkdir -p $HOME/.m2 && mv $GITHUB_WORKSPACE/repository $HOME/.m2/\"\n      - uses: actions/setup-java@v4\n        with:\n          distribution: zulu\n          java-version: ${{ matrix.java }}\n      - name: Run Maven build\n        run: >\n          ./mvnw --no-transfer-progress clean verify -Djqassistant.skip=true -Drevision=$REVISION -Dsha1=-$GITHUB_SHA -Dchangelist=\n          -pl org.neo4j:neo4j-cypher-dsl-examples\n          -pl org.neo4j:neo4j-cypher-dsl-examples-core\n          -pl org.neo4j:neo4j-cypher-dsl-examples-parser\n          -pl org.neo4j:neo4j-cypher-dsl-examples-ogm-quarkus\n          -pl org.neo4j:neo4j-cypher-dsl-examples-sdn6\n"
  },
  {
    "path": ".github/workflows/publish_docs.yml",
    "content": "name: publish_docs\n\non:\n  push:\n    branches:\n      - main\n  create:\n    tags:\n      - '*'\n\njobs:\n  publish_docs:\n    if: github.event_name == 'push' || (github.event_name == 'create' && github.event.ref_type == 'tag')\n    runs-on: ubuntu-latest\n    steps:\n      - name: Prepare branch name\n        run: >\n          echo \"refName=${GITHUB_REF##*/}\" >> $GITHUB_ENV\n      - name: Checkout relevant branch\n        uses: actions/checkout@v4\n        with:\n          ref: ${{ env.refName }}\n      - name: Checkout gh-pages\n        uses: actions/checkout@v4\n        with:\n          ref: gh-pages\n          path: target/gh-pages\n      - name: Set up JDK\n        uses: actions/setup-java@v4\n        with:\n          distribution: zulu\n          java-version: 25\n      - name: Run docs generation\n        run: >\n          ./mvnw --no-transfer-progress install -pl neo4j-cypher-dsl-bom &&\n          ./mvnw --no-transfer-progress asciidoctor:process-asciidoc@generate-docs -pl org.neo4j:neo4j-cypher-dsl-parent -Dproject.build.docs=target/gh-pages/${refName} -Duse-latest-version-for-docs=`[ $refName = \"main\" ] && echo \"0\" || echo \"1\"` &&\n          ./mvnw --no-transfer-progress site -pl org.neo4j:neo4j-cypher-dsl-build-proc -pl org.neo4j:neo4j-cypher-dsl -am &&\n          rm -rf target/gh-pages/${refName}/project-info &&\n          mv neo4j-cypher-dsl/target/site target/gh-pages/${refName}/project-info\n      - name: Update index\n        if: (github.event_name == 'create' && github.event.ref_type == 'tag')\n        run: sed -e \"s/\\${current}/${refName}/g\" ./etc/index.tpl > ./target/gh-pages/index.html\n      - name: Commit to gh-pages\n        working-directory: ./target/gh-pages\n        run: |\n          git config --local user.email \"action@github.com\"\n          git config --local user.name \"GitHub Action\"\n          git add .\n          git commit -m \"Update GH-Pages.\"\n      - name: Push changes\n        uses: ad-m/github-push-action@v0.6.0\n        with:\n          directory: target/gh-pages\n          branch: gh-pages\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: release\n\non:\n  workflow_dispatch:\n  create:\n    tags:\n      - '*'\n\njobs:\n  release:\n    if: (github.event_name == 'create' && github.event.ref_type == 'tag') || github.event_name == 'workflow_dispatch'\n    runs-on: ubuntu-latest\n    steps:\n      - name: 'Set up JDK'\n        uses: actions/setup-java@v4\n        with:\n          distribution: zulu\n          java-version: 25\n\n      - name: 'Prepare git'\n        run: git config --global core.autocrlf false\n\n      - name: 'Prepare branch name'\n        if: (github.event_name == 'create' && github.event.ref_type == 'tag')\n        run: >\n          echo \"refName=${GITHUB_REF##*/}\" >> $GITHUB_ENV\n\n      - name: 'Checkout relevant branch'\n        uses: actions/checkout@v4\n        with:\n          ref: ${{ env.refName }}\n          fetch-depth: 0\n\n      - name: Determine revision\n        id: revision_step\n        run: |\n          REVISION=$(./bin/extract-version.sh latest)\n          echo \"REVISION=$REVISION\" >> $GITHUB_ENV\n\n      - name: 'Create release'\n        env:\n          JRELEASER_GITHUB_TOKEN: ${{ secrets.JRELEASER_TOKEN }}\n          JRELEASER_SLACK_WEBHOOK: ${{ secrets.JRELEASER_SLACK_WEBHOOK }}\n        run: ./mvnw --no-transfer-progress -Djreleaser -Drevision=$REVISION -Dsha1= -Dchangelist= jreleaser:announce -pl org.neo4j:neo4j-cypher-dsl-parent\n"
  },
  {
    "path": ".gitignore",
    "content": "target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n.gradle\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### Visual Studio Code ###\n.vscode\n\n### Misc ###\n.DS_Store\n.flattened-pom.xml\ndependency-reduced-pom.xml\n"
  },
  {
    "path": ".mvn/extensions.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<extensions>\n  <extension>\n    <groupId>org.torquebox.mojo</groupId>\n    <artifactId>mavengem-wagon</artifactId>\n    <version>1.0.3</version>\n  </extension>\n</extensions>"
  },
  {
    "path": ".mvn/jvm.config",
    "content": "-XX:+IgnoreUnrecognizedVMOptions\n-Dguice_custom_class_loading=CHILD\n--enable-native-access=ALL-UNNAMED\n"
  },
  {
    "path": ".mvn/wrapper/maven-wrapper.properties",
    "content": "wrapperVersion=3.3.4\ndistributionType=bin\ndistributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip\nwrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\nadmins@neo4j.com.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior,  harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": "CONTRIBUTING.adoc",
    "content": "= Contributing to the Neo4j Ecosystem\n:sectanchors:\n\nAt http://neo4j.com/[Neo4j], we develop our software in the open at\nGitHub. This provides transparency for you, our users, and allows you to\nfork the software to make your own additions and enhancements. We also\nprovide areas specifically for community contributions, in particular\nthe https://github.com/neo4j-contrib[neo4j-contrib] space.\n\nThere's an active https://community.neo4j.com/[Neo4j Online Community]\nwhere we work directly with the community. If you're not already a\nmember, sign up!\n\nWe love our community and wouldn't be where we are without you. Please remember:\nMany things are contributions, among them issues, code, documentation and examples.\n\n== Building and compiling the Neo4j-Cypher-DSL\n\n// tag::building-manual[]\n=== Requirements\n\nFor the full project, including examples and native tests:\n\n* https://www.graalvm.org/release-notes/JDK_24/[GraalVM for JDK 24]\n\nFor the project, including examples but skipping native tests:\n\n* JDK 17+ (Can be https://openjdk.java.net[OpenJDK] or https://www.oracle.com/technetwork/java/index.html[Oracle JDK])\n\nMaven 3.8.4 is our build tool of choice. We provide the Maven wrapper, see `mvnw` respectively `mvnw.cmd` in the project root;\nthe wrapper downloads the appropriate Maven version automatically.\n\nThe build requires a local copy of the project:\n\n[source,console,subs=\"verbatim,attributes\"]\n[[clone-cypher-dsl]]\n.Clone the Neo4j Cypher-DSL\n----\n$ git clone git@github.com:neo4j-contrib/cypher-dsl.git\n----\n\n=== Fast build\n\nNOTE: This is useful if you want to just have an installation of a snapshot version. No tests are run, no verification is done.\n\n[source,console,subs=\"verbatim,attributes\"]\n[[build-fast-bash]]\n.Fast build (only compiling and producing packages)\n----\n$ ./mvnw -Dfast package\n----\n\nFor a local install - maybe to try out a future release - you can also specify the version number:\n\n[source,console,subs=\"verbatim,attributes\"]\n[[build-fast-and-install-bash]]\n.Fast build (locally installed, with an artificial version number)\n----\n$ ./mvnw -Dfast -Drevision=1337 -Dchangelist= install\n----\n\n\n=== Full build (including examples and native tests)\n\nBefore you proceed, verify your locally installed JDK version.\nThe output should be similar:\n\n[source,console,subs=\"verbatim,attributes\"]\n[[verify-jdk]]\n.Verify your JDK\n----\n$ java -version\nopenjdk version \"24\" 2025-03-18\nOpenJDK Runtime Environment GraalVM CE 24+36.1 (build 24+36-jvmci-b01)\nOpenJDK 64-Bit Server VM GraalVM CE 24+36.1 (build 24+36-jvmci-b01, mixed mode, sharing)\n----\n\nCheck whether GraalVM `native-image` is present with:\n\n[source,console,subs=\"verbatim,attributes\"]\n[[verify-native-image]]\n.Check for the present of `native-image`\n----\n$ which native-image\n/Users/msimons/.sdkman/candidates/java/24-graalce/bin/native-image\n----\n\nYou should see `native-image` in the list. If not, you are most likely on a GraalVM version we don't support with this project.\n\nAfter that, use `./mvnw` on a Unix-like operating system to build the Cypher-DSL:\n\n[source,console,subs=\"verbatim,attributes\"]\n[[build-default-bash]]\n.Build with default settings on Linux / macOS\n----\n$ ./mvnw clean verify\n----\n\nOn a Windows machine, use\n\n[source,console,subs=\"verbatim,attributes\"]\n[[build-default-windows]]\n.Build with default settings on Windows\n----\n$ mvnw.cmd clean verify\n----\n\n=== Skipping native tests\n\nOn a plain JDK 17 or higher, run the following to skip the native tests:\n\n[source,console,subs=\"verbatim,attributes\"]\n[[build-skip-native-bash]]\n.Skipping native tests\n----\n$ ./mvnw clean verify -pl \\!org.neo4j:neo4j-cypher-dsl-native-tests\n----\n\n=== Build only the core module\n\nThe core module can be built on plain JDK 17 with:\n\n[source,console,subs=\"verbatim,attributes\"]\n[[build-only-core-bash]]\n.Build only the core module\n----\n$ ./mvnw clean verify -am -pl org.neo4j:neo4j-cypher-dsl\n----\n\n=== CI-friendly version numbers\n\nWe use CI-friendly version numbers, the current build will always identify itself as 9999-SNAPSHOT.\nIf you need to create a specific version you can specify the revision, the changelist and an optional hash like this:\n\n[source,console,subs=\"verbatim,attributes\"]\n.Specifying revision and changelist\n----\n$ ./mvnw clean package -pl org.neo4j:neo4j-cypher-dsl -Drevision=2022.1.0 -Dchangelist=-SNAPSHOT\n----\n\n=== Releasing (Only relevant for the current maintainers)\n\nPrepare a release with:\n\n[source,console,subs=\"verbatim,attributes\"]\n----\n./mvnw exec:exec@prepare-release -pl :neo4j-cypher-dsl-parent -Drevision=2020.0.1 -Dchangelist= -Dcypher-dsl.version.next=2020.0.2-SNAPSHOT\n----\n\nand then let do Teamcity the rest, but chose the same version number there, too.\n// end::building-manual[]\n\n== Tasks\n\n=== Keep the build descriptor (`pom.xml`) sorted\n\n[source,bash]\n----\n./mvnw sortpom:sort\n----\n\n=== Formatting sources / adding headers\n\nWhen you add new files, you can run\n\n[source,bash]\n----\n./mvnw license:format\n----\n\nto add required headers automatically.\n\nWe use https://github.com/spring-io/spring-javaformat[spring-javaformat] to format the source files.\n\n[source,bash]\n----\n./mvnw spring-javaformat:apply\n----\n\nTIP: The Spring Developers write: \"The source formatter does not fundamentally change your code. For example, it will not change the order of import statements. It is effectively limited to adding or removing whitespace and line feeds.\"\nThis means the following checkstyle check might still fail.\nSome common errors include the wrong import order.\n\nThere are plugins for https://github.com/spring-io/spring-javaformat#eclipse[Eclipse] and https://github.com/spring-io/spring-javaformat#intellij-idea[IntelliJ IDEA] and the Checkstyle settings https://github.com/spring-io/spring-javaformat#checkstyle-idea-plugin[can be imported as well].\nWe took those \"as is\" and just disabled the lambda check (requiring even single parameters to have parenthesis).\n\nPublic classes do require an author tag.\nPlease add yourself as an `@author` to the `.java` files you added or that modified substantially (more than cosmetic changes).\n\n== General considerations\n\n=== Need to raise an issue?\n\nWhere you raise an issue depends largely on the nature of the problem.\n\nFirstly, if you are an Enterprise customer, you might want to head over\nto our http://support.neo4j.com/[Customer Support Portal].\n\nThere are plenty of public channels available too, though. If you simply\nwant to get started or have a question on how to use a particular\nfeature, ask a question in https://community.neo4j.com/[Neo4j Online\nCommunity]. If you think you might have hit a bug in our software (it\nhappens occasionally!) or you have specific feature request then use the\nissue feature on the relevant GitHub repository. Check first though as\nsomeone else may have already raised something similar.\n\nhttp://stackoverflow.com/questions/tagged/neo4j[StackOverflow] also\nhosts a ton of questions and might already have a discussion around your\nproblem. Make sure you have a look there too.\n\nInclude as much information as you can in any request you make:\n\n* Which versions of our products are you using?\n* Which language (and which version of that language) are you developing\nwith?\n* What operating system are you on?\n* Are you working with a cluster or on a single machine?\n* What code are you running?\n* What errors are you seeing?\n* What solutions have you tried already?\n\n=== Want to contribute?\n\nIt's easier for all of us if you try to follow these steps before creating a pull request:\n\n* Do all your work in a personal fork of the original repository\n* https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request[Rebase],\ndon't merge (we prefer to keep our history clean)\n* Create a branch (with a useful name) for your contribution\n* Make sure you're familiar with the appropriate coding style (this\nvaries by language so ask if you're in doubt)\n* Include unit tests if appropriate (obviously not necessary for\ndocumentation changes)\n\nNOTE: Small things that doesn't change the public API or documented behaviour and of course bug fixes usually\n      go in quickly. If you want to add new features with public API changes or additions or want to customize or\n      change a feature, please do reach out to us on one of the available channels, preferable by creating a\n      https://github.com/neo4j-contrib/cypher-dsl/issues/new[new issue] first in which we can discuss the proposed changes.\n\nWe can't guarantee that we'll accept pull requests and may ask you to\nmake some changes before they go in. Occasionally, we might also have\nlogistical, commercial, or legal reasons why we can't accept your work,\nbut we'll try to find an alternative way for you to contribute in that\ncase. Remember that many community members have become regular\ncontributors and some are now even Neo employees!\n\n=== Further reading\n\nIf you want to find out more about how you can contribute, head over to\nour website for http://neo4j.com/developer/contributing-code/[more\ninformation].\n\n== Got an idea for a new project?\n\nIf you have an idea for a new tool or library, start by talking to other\npeople in the community. Chances are that someone has a similar idea or\nmay have already started working on it. The best software comes from\ngetting like minds together to solve a problem. And we'll do our best to\nhelp you promote and co-ordinate your Neo ecosystem projects.\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.adoc",
    "content": "= The Neo4j Cypher-DSL\n:sectanchors:\n\n// tag::properties[]\n:groupId: org.neo4j\n:artifactId: neo4j-cypher-dsl\n\n// This will be next version and also the one that will be put into the manual for the main branch\n:neo4j-cypher-dsl-version: 2025.2.8-SNAPSHOT\n// This is the latest released version, used only in the readme\n:neo4j-cypher-dsl-version-latest: 2025.2.7\n\n// end::properties[]\n\nimage:https://github.com/neo4j-contrib/cypher-dsl/workflows/build/badge.svg[link=https://github.com/neo4j-contrib/cypher-dsl/actions]\nimage:https://sonarcloud.io/api/project_badges/measure?project=org.neo4j%3Aneo4j-cypher-dsl-parent&metric=coverage[link=https://sonarcloud.io/summary/new_code?id=org.neo4j%3Aneo4j-cypher-dsl-parent]\nimage:https://sonarcloud.io/api/project_badges/measure?project=org.neo4j%3Aneo4j-cypher-dsl-parent&metric=alert_status[link=https://sonarcloud.io/dashboard?id=org.neo4j%3Aneo4j-cypher-dsl-parent]\nimage:https://maven-badges.herokuapp.com/maven-central/org.neo4j/neo4j-cypher-dsl/badge.svg[Maven Central,link=http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.neo4j%22%20AND%20a%3A%22neo4j-cypher-dsl%22]\n\n[abstract]\n--\nThe Neo4j Cypher-DSL in its current form is a spin-off from Spring Data Neo4j 6+ (né Spring Data Neo4j⚡️RX), where it is used to generate all Cypher queries.\nWe thank all contributors to all branches prior to 2020.0 for their effort in creating the previous versions.\n--\n\nThe primary goal of this project is to have a type safe way of creating Cypher queries targeted at https://neo4j.com[Neo4j 4.0+].\nMost of the constructs used here are modelled after https://www.opencypher.org[openCypher], but we include several constructs specific to Neo4j.\n\nThe core module of the Neo4j Cypher-DSL has no required runtime dependencies.\n\n== Versioning\n\nThis rebooted version of the Neo4j Cypher-DSL uses https://calver.org[CalVer] in the same way Spring does\nsince early 2020 (see https://spring.io/blog/2020/04/30/updates-to-spring-versions[Updates to Spring Versions]),\nstarting at _2020.0.0_.\n\nThe year digit is treated in a semver fashion for the core module.\nThat means that you won't experience any breaking changes when staying in a release line.\nHowever, the first or the latest release in a given year does not necessarily reflect the current calendar year.\nIt's kind of a trade-off, but one that we think is valuable, otherwise we would need to postpone the first release in a year until we need todo some breaking changes.\n\n== Manual\n\nFor a gentle introduction and some getting started guides, please use our\nhttps://neo4j.github.io/cypher-dsl[Manual].\n\n== Getting Started\n\n=== Adding the necessary dependencies\n\nFirst, include the dependency to the Neo4j Cypher-DSL under the following coordinates: `{groupId}:{artifactId}`:\n\n==== Maven configuration\n\n[source,xml,subs=\"verbatim,attributes\"]\n.Inclusion of the Neo4j Cypher-DSL in a Maven project\n----\n<dependency>\n\t<groupId>{groupId}</groupId>\n\t<artifactId>{artifactId}</artifactId>\n\t<version>{neo4j-cypher-dsl-version-latest}</version>\n</dependency>\n----\n\n==== Gradle configuration\n\n[source,groovy,subs=\"verbatim,attributes\"]\n.Inclusion of the Neo4j Cypher-DSL in a Gradle project\n----\ndependencies {\n    compile '{groupId}:{artifactId}:{neo4j-cypher-dsl-version-latest}'\n}\n----\n\n=== A simple example\n\nWith the Cypher-DSL, you can build your queries starting with the static methods provided through `org.neo4j.cypherdsl.core.Cypher`.\nStatic imports for those packages should be allowed:\n\n[source,java,tabsize=4]\n----\nimport static org.neo4j.cypherdsl.core.Cypher.*;\n\nimport org.neo4j.cypherdsl.core.Cypher;\n\nclass SimpleExample {\n\n\tpublic static void main(String... a) {\n\n\t\tvar m = node(\"Movie\").named(\"m\");\n\t\tvar statement = Cypher.match(m)\n\t\t\t.returning(m)\n\t\t\t.build();\n\n\t\tSystem.out.println(statement.getCypher());\n\t\t// Prints MATCH (m:`Movie`) RETURN m\n\t}\n}\n----\n\n=== Required Java Version\n\nFrom version 2023.0.0 onwards, the minimal required Java version to use and build the Cypher-DSL is *Java 17*. If you need a version that is compatible with Java 8, please use 2022.9.x.\n\n== Licensing\n\nThe Cypher-DSL itself is licenced under the https://www.apache.org/licenses/LICENSE-2.0[Apache License 2.0].\n"
  },
  {
    "path": "bin/extract-version.sh",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\nDIR=\"$(dirname \"$(realpath \"$0\")\")\"\n\nif test -n \"${1-}\"; then\n  sed -n 's/\\(:neo4j-cypher-dsl-version-'\"${1}\"':\\) \\(.*\\)/\\2/p' $DIR/../README.adoc\nelse\n  sed -n 's/\\(:neo4j-cypher-dsl-version:\\) \\(.*\\)/\\2/p' $DIR/../README.adoc\nfi\n"
  },
  {
    "path": "bin/prepare-release.sh",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\nDIR=\"$(dirname \"$(realpath \"$0\")\")\"\n\nsed -i .bak 's/\\(:neo4j-cypher-dsl-version-latest:\\) \\(.*\\)/\\1 '\"${1}\"'/g' $DIR/../README.adoc\n\nif test -n \"${2-}\"; then\n  sed -i .bak 's/\\(:neo4j-cypher-dsl-version:\\) \\(.*\\)/\\1 '\"${2}\"'/g' $DIR/../README.adoc\nfi\n\nrm $DIR/../README.adoc.bak\n\ngit add README.adoc\ngit commit -sm \"Prepare release.\"\n"
  },
  {
    "path": "bin/remove-shaded-modules.sh",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\nDIR=\"$(dirname \"$(realpath \"$0\")\")\"\n\nmkdir -p $DIR/../neo4j-cypher-dsl/target/modules\nsed 's/requires org.neo4j.cypherdsl.support.schema_name;$//g'  $DIR/../neo4j-cypher-dsl/src/main/java/module-info.java >  $DIR/../neo4j-cypher-dsl/target/modules/module-info.java\n"
  },
  {
    "path": "bin/runtests.java",
    "content": "///usr/bin/env jbang \"$0\" \"$@\" ; exit $?\n//DEPS org.junit.platform:junit-platform-console-standalone:1.8.1\n//DEPS org.assertj:assertj-core:3.22.0\n//DEPS org.mockito:mockito-junit-jupiter:3.6.0\nimport org.junit.platform.console.ConsoleLauncher;\n\n/**\n * This script is mainly used to execute our tests standalone in CI with JDK 8.\n */\npublic class runtests {\n\n\tpublic static void main(String... a) {\n\t\tConsoleLauncher.main(a);\n\t}\n\n}\n"
  },
  {
    "path": "docs/appendix/2020.0.adoc",
    "content": "== 2020.0\n\n=== 2020.0.1\n\nThis is the first patch release for the rebooted Cypher-DSL project.\n\n==== 🚀 Features\n\n* GH-64 - Add function invocation for builtin point function.\n* GH-65 - Add support for defining calls to stored procedures. \n* `Cypher.literalOf` accepts now `boolean` values as well\n\n==== 🧹 Housekeeping\n\n* Improvements to the manual and Java Docs.\n\nThanks to @Andy2003 for contributing to this release.\n\n=== 2020.0.0\n\nThis is the first version of the rebooted Neo4j Cypher-DSL project. This version has been extracted from https://github.com/neo4j/sdn-rx[SDN-RX].\n\nIt's a completely revamped API and we use it in all places in SDN/RX for generating Cypher-Queries.\n\nWe use https://calver.org[CalVer] in the same way Spring does\nsince early 2020 (see https://spring.io/blog/2020/04/30/updates-to-spring-versions[Updates to Spring Versions]) from this release onwards.\n\nYou'll find the manual of the latest release version under http://neo4j-contrib.github.io/cypher-dsl/current/ and the current development version - or _main_ - under http://neo4j-contrib.github.io/cypher-dsl/main/.\n\n"
  },
  {
    "path": "docs/appendix/2020.1.adoc",
    "content": "== 2020.1\n\n=== 2020.1.6\n\nNo new features. \nRe-released 2020.1.5 due downtime and staging issues of oss.sonatype.org.\n\n=== 2020.1.5\n\n==== 🚀 Features\n\n* GH-116 - Add support for creating calls to Neo4j reduce().\n* GH-119 - Add support for passing symbolic names to nodes and relationships functions.\n* GH-117 - Introduce mutating operator.\n\n=== 2020.1.4\n\n==== 🚀 Features\n\n* GH-114 - Support chained properties.\n* GH-115 - Support named items in YIELD and symbolic names as NamedPath reference.\n\n=== 2020.1.3\n\n==== 🚀 Features\n\n* GH-111 - Provide a programmatic way of creating an optional match.\n\n==== 🐛 Bug Fixes\n\n* GH-110 - Fix collapsing of empty conditions.\n\n=== 2020.1.2\n\n==== 🚀 Features\n\n* GH-88 - Add support for Neo4j 4.0 subqueries.\n* GH-104 - Add support for merge actions.\n* GH-101 - Introduce asFunction on an ongoing call definition.\n\n==== 🐛 Bug Fixes\n\n* GH-106 - Escape symbolic names, property lookups, aliases and map keys.\n\n==== 🧹 Housekeeping\n\n* GH-105 - Remove ::set-env from GH-Actions ci.\n\n==== Further improvements:\n\n* Add support for EXPLAIN and PROFILE keywords.\n* Qualify a yield call (only relevant for JDK15+)\n* Fix wrong offsets in the documentation.\n* Improve JavaDoc and document internal API.\n* Allow `WITH` clause after `YIELD`.\n* Improve reusability of fragments.\n* Make ORDER clause buildable.\n* Remove parts of an experimental API.\n\nWe do publish the Project info now: http://neo4j-contrib.github.io/cypher-dsl/current/project-info/project-info.html[Project info], \nincluding the http://neo4j-contrib.github.io/cypher-dsl/current/project-info/apidocs/index.html[Java API].\n\n=== 2020.1.1\n\n==== 🚀 Features\n\n* List comprehensions can now be build based on named paths.\n\n=== 2020.1.0\n\n==== 🚀 Features\n\n* GH-74 - Automatically generate symbolic name if required: `Node` and `Relationship` objects generate a symbolic name if required and not set\n* Added several new functions\n** GH-77 `properties()`\n** GH-81 `relationships()`\n** GH-83 `startNode()`, `endNode()`,\n** GH-89 All temporal functions\n* GH-76 - Added the list operator (`[]` for accessing sub lists and indexes).\n\n==== 🐛 Bug Fixes\n\n* GH-82 - Expose all necessary interfaces for `call`\n* GH-84 - Fix rendering of nested sub trees.\n* GH-95 - NPE during the creation of map projections\n* GH-96 - Make sure aliased expressions are not rendered multiple times.\n\n==== 🧹 Housekeeping\n\n* GH-67 - Improvements in regards of Java generics.\n* GH-68 - Clean up the Functions api.\n* GH-69 - Avoid star and static imports.\n* GH-72 - Some release cleanup\n* GH-75 - Move Assert to internal utils package.\n* GH-89 - `RelationshipDetails` is now internal API.\n* GH-93 - Ensure compatibility with GraalVM native.\n* GH-94 - Bring back SymbolicName#concat.\n"
  },
  {
    "path": "docs/appendix/2021.0.adoc",
    "content": "== 2021.0\n\n=== 2021.0.2\n\nWARNING: This will already be the last release of the 2021.0 line.\n      2021.1 will be API compatible but not ABI compatible, as some classes have\n      been changed into interfaces.\n      That means it is not a drop in replacement, but your application needs to be recompiled.\n\n==== 🚀 Features\n\n* GH-157 - Provide a method to turn a Java map into an expression.\n* GH-158 - Improve pretty printing of subqueries.\n* Allow the use of raw cypher as expressions.\n* Allow symbolic names to be used as aliases.\n* Cache some symbolic names.\n* Add support for the keys() function.\n\n==== 📖 Documentation\n\n* GH-152 - Document usage of PatterElement in tests.\n\n==== 🐛 Bug Fixes\n\n* GH-149 - Avoid possible stackoverflow exception during visitor traversal.\n* GH-159 - Fix missing labels for nodes after `WITH`.\n\n==== 🧹 Housekeeping\n\n* GH-148 - Add jQAssistant rules and improve building documentation.\n* Add Maven PMD plugin.\n\nThanks https://github.com/Andy2003[Andy] for the improvements of the pretty printer.\n\n=== 2021.0.1\n\n==== 🚀 Features\n\n* GH-147 - Configuration infrastructure for renderer.\n           First use case being a simple, pretty printing renderer.\n\nThe feature looks like this:\n\n[source,java]\n----\nvar c = node(\"Configuration\").named(\"c\");\nvar d = node(\"Cypher-DSL\").named(\"d\");\n\nvar mergeStatement = merge(c.relationshipTo(d, \"CONFIGURES\"))\n    .onCreate()\n        .set(\n            d.property(\"version\").to(literalOf(\"2021.0.1\")),\n            c.property(\"prettyPrint\").to(literalTrue())\n        )\n    .onMatch().set(c.property(\"indentStyle\").to(literalOf(\"TAB\")))\n    .returning(d).build();\n\nvar renderer = Renderer.getRenderer(Configuration.prettyPrinting());\nSystem.out.println(renderer.render(mergeStatement));\n----\n\nand gives you:\n\n[source,cypher]\n----\nMERGE (c:Configuration)-[:CONFIGURES]->(d:`Cypher-DSL`)\n  ON CREATE SET d.version = '2021.0.1', c.prettyPrint = true\n  ON MATCH SET c.indentStyle = 'TAB'\nRETURN d\n----\n\n=== 2021.0.0\n\n2021.0.0 comes with a lot of new features.\nThanks to https://github.com/Andy2003[Andy] for his contributions!\n\nAndy is one of our first users outside https://github.com/spring-projects/spring-data-neo4j[Spring Data Neo4j 6].\nHe started to use the Cypher-DSL in https://github.com/neo4j-graphql/neo4j-graphql-java[Neo4j GraphQL Java].\nNeo4j GraphQL Java is a library to translate GraphQL based schemas and queries to Cypher and execute those statements with the Neo4j database.\nIt can be used from a wide variety of frameworks.\n\nWe are happy and proud to be part of this and even more so about the input and contribution we got back from Andy.\n\nOf course thanks for your input in form of tickets and discussions go out to @utnaf, @aaramg, @K-Lovelace and @maximelovino as well!\n\n==== Noteworthy\n\nTwo things should be mentioned:\n\nThe https://github.com/neo4j-contrib/cypher-dsl/commit/2d0c98af853c72d4cd61099c9d8f3209b7e4c7c6[bugfix for GH-121] might\nchange behavior for some users:\nThe changes prevents the forced rendering of an alias for objects when the original object - the one that has been aliased\n- is passed down to the DSL after an alias has been created.\n\nThe original intention for that behaviour was related to Map projection, in which the alias is actually rendered before the object.\n\nSo now the use of an aliased expression the first time triggers `a AS b` respectively `b: a` in a map projection.\nAll further calls will just render `b`. If the *original* object is used again, `a` will be rendered. If that is not desired\nin your query and you rely on the alias, make sure you use the aliased expression returned from `.as(\"someAlias\")`.\n\nThe other thing are the combined features GH-135 and GH-146.\nThe `Statement` class has become a fully fledged accessor to the Cypher String and the parameters used and if provided,\nthe values for those. The following shows a small example:\n\n[source,java]\n----\nvar person = Cypher.node(\"Person\").named(\"p\");\nvar statement = Cypher\n    .match(person)\n    .where(person.property(\"nickname\").isEqualTo(Cypher.parameter(\"nickname\")))\n    .set(\n        person.property(\"firstName\").to(Cypher.parameter(\"firstName\").withValue(\"Thomas\")),\n        person.property(\"name\").to(Cypher.parameter(\"name\", \"Anderson\"))\n    )\n    .returning(person)\n    .build();\n\nassertThat(statement.getCypher())\n    .isEqualTo(\"MATCH (p:`Person`) WHERE p.nickname = $nickname SET p.firstName = $firstName, p.name = $name RETURN p\");\n\nCollection<String> parameterNames = statement.getParameterNames();\nassertThat(parameterNames).containsExactlyInAnyOrder(\"nickname\", \"firstName\", \"name\");\n\nMap<String, Object> parameters = statement.getParameters();\nassertThat(parameters).hasSize(2);\nassertThat(parameters).containsEntry(\"firstName\", \"Thomas\");\nassertThat(parameters).containsEntry(\"name\", \"Anderson\");\n----\n\n==== 🚀 Features\n\n* GH-122 - Add support for index hints.\n* GH-123 - Expose nested building of nested properties as public API.\n* GH-124 - Add support for Neo4j's mathematical functions.\n* GH-127 - Allow dynamic property lookup.\n* GH-128 - Provide asConditions for RelationshipPatterns.\n* GH-129 - Allow Expressions as Parameter for Skip and Limit.\n* GH-131 - Add support for projections on symbolic names.\n* GH-133 - Allow symbolic names to be used as condition.\n* GH-135 - Collect parameters defined on a statement.\n* GH-141 - Provide a property function on all expressions.\n* GH-142 - Provide a point function accepting generic expressions as parameter.\n* GH-146 - Allow a statement to render itself.\n\n==== 📖 Documentation\n\n* GH-126 - Document how to call arbitrary functions and procedures.\n\n==== 🐛 Bug Fixes\n\n* Prevent double rendering of Node content when using generated names.\n* GH-121 - Don't force rendering of aliases when the original object is used.\n* GH-137 - Fix grouping of nested conditions.\n\n==== 🧹 Housekeeping\n\n* Switch to GraalVM 20.3.0.\n* GH-125 - Use GraalVM image from ghcr.io.\n* GH-139 - Ensure indention via tabs.\n* GH-140 - Provide editorconfig.\n* GH-143 - Remove union types.\n"
  },
  {
    "path": "docs/appendix/2021.1.adoc",
    "content": "== 2021.1\n\n=== 2021.1.2\n\nThis release comes with two notable things: It uses a couple of annotations on the API to guide developers using it correctly.\nIDEs like IDEA will now issue warnings if you don't use a returned builder, or a new instance of an object while wrongly assuming\nyou mutated state.\n\nIn the light of that we discovered that the `RelationshipChain` pattern was mutable and returning a mutated instance while\nit should have returned a fresh one.\n\n_Warning_ This might be a breaking change for users having code like this:\n\n```\nvar pattern = Cypher.node(\"Start\").named(\"s\")\n  .relationshipTo(Cypher.anyNode())\n  .relationshipTo(Cypher.node(\"End\").named(\"e\"));\npattern.named(\"x\");\n```\n\nPrior to 2021.1.2 this would give the pattern the name `x` and modify it in place.\nFrom 2021.1.2 onwards you *must* use the returned value:\n\n```\npattern = pattern.named(\"x\");\n```\n\nWe think that this change is crucial and necessary as all other patterns are immutable as intended and in sum, they build\nup truly immutable statements. One pattern that is mutable like the above invalides the whole guarantee about the statement.\n\n==== 🚀 Features\n\n* Add `named(SymbolicName s)` to RelationshipChain.\n* Generate $TYPE field containing the relationship type. [SDN 6 Annotation Processor]\n* Introduce some optional annotations for guidance along the api.\n\n==== 📖 Documentation\n\n* GH-173 - Improve documentation. [A collection of small improvements]\n\n==== 🐛 Bug Fixes\n\n* GH-174 - Extract types via the visitor API and avoid casting element types. [SDN 6 Annotation Processor]\n* Ensure immutability of `RelationshipChain`.\n\n==== 🧹 Housekeeping\n\n* Remove unnecessary close (will be taken care of via `@Container`). [Only test related]\n* Run tests on JDK 16\n\n=== 2021.1.1\n\nThis is a drop-in replacement for <<v2021.1.0>>. Introducing the interface for `Property` broke the `mutate` operation,\nfor which no test was in place. This and the bug has been fixed.\n\n==== 🐛 Bug Fixes\n\n* GH-168 - Fix mutating containers by properties.\n\n[[v2021.1.0]]\n=== 2021.1.0\n\n2021.1.0 comes with a ton of new features and a handful of breaking changes.\nFear not, the breaking changes are resolvable by recompiling your application.\nWe turned `Node`, `Relationship` and `Property` into interfaces and provide now `NodeBase` and `RelationshipBase` so that you can\nuse them to build a static meta-model of your application. A `PropertyBase` might follow.\n\nFind out everything about the new possibility to define a static meta model in <<static-meta-model,the manual>>.\nThe manual also includes a major part about the two new modules we offer:\n`{groupId}:neo4j-cypher-dsl-codegen-core` and `{groupId}:neo4j-cypher-dsl-codegen-sdn6`.\n`neo4j-cypher-dsl-codegen-core` provides the infrastructure necessary to build code generators for creating a domain model\nfollowing our recommendation and `neo4j-cypher-dsl-codegen-sdn6` is a first implementation of that:\nA Java annotation processor that can be added to any Spring Data Neo4j 6 project in version 6.0.6 or higher.\nIt will find your annotated domain classes and turn them into a model you can use to build queries.\n\nLast but not least: We added support for some expressions of the more generic http://www.querydsl.com[QueryDSL].\nThis will require `com.querydsl:querydsl-core` on the class path but only if you decide to call `Cypher#adapt(foreignExpression)`.\nThis is a feature that is driven by Spring Data Neo4j 6.1 in which we build upon this to provide a `QuerydslPredicateExecutor`.\nFind more in <<query-dsl-support, this section of the manual>>.\n\n==== 🚀 Features\n\n* GH-154 - Make Node and Relationship extendable.\n* GH-155 - Provide infrastructure for generating a static meta model.\n* GH-156 - Create an annotation processor for Spring Data Neo4j 6.\n* GH-167 - Add support for some Query-DSL expressions.\n* Introduce a statement context for allowing anonymous parameters\n  (use `Cypher#anonParameter()` to define a parameter with a value but without a name. The name will be accessible on the statement\n  after rendering).\n* Make rendering of constants as parameters configurable.\n* Allow specification of the direction while creating a sort item.\n* Introduce an interface for Property.\n\n==== 📖 Documentation\n\n* GH-152 - Document usage of PatterElement in tests.\n* GH-164 - Improve public extendable API and add documentation.\n\n==== 🐛 Bug Fixes\n\n* Fix SymbolicName#toString.\n* Clear visited name cache after single queries.\n\n==== 🧹 Housekeeping\n\n* GH-165 - Simplify poms.\n* GH-166 - Improve Cypher.literalOf.\n* Exclude all example projects from release.\n"
  },
  {
    "path": "docs/appendix/2021.2.adoc",
    "content": "== 2021.2\n\n=== 2021.2.4\n\n2021.2.4 is a pure bug fix release.\n\n==== 🐛 Bug Fixes\n\n* GH-203 - Introduce a scope for the `PatternComprehension`.\n\n=== 2021.2.3\n\n2021.2.3 is a rather big release as it contains many small improvements and API functionality required by our next major\nrelease. Those are brought in now so that they can be benefial to others without bumping a major version.\n\n==== 🚀 Features\n\n* GH-195 - Add collection parameter support for `ExposesReturning`.\n* Introduce a `ExposesPatternLengthAccessors` for uniform access to relationships and chains thereof. [improvement]\n* Allow creating instances of `FunctionInvocation` directly. [improvement]\n* Provide factory methods of `MapProjection` and `KeyValueMapEntry` as public API.\n* Provide `set` and `remove` labels operation as public API.\n* Provide `set` and `mutate` of expressions as public API.\n* Provide factory methods of `Hints` as public API.\n* GH-200 - Provide an API to define named paths based on a `Node` pattern.\n* Provide an option to escape names only when necessary. [improvement]\n\n==== 📖 Documentation\n\n* Add documentation for escaping names.\n* GH-198 - Fix spelling errors in JavaDoc and documentation.\n\n==== 🐛 Bug Fixes\n\n* Make `Case` an interface and let it extend `Expression`. [bug]\n* GH-197 - Fix eagerly resolved symbolic names in negated pattern conditions.\n* GH-197 - Clear name cache after leaving a statement.\n* GH-199 - Bring back `with(Named… vars)`.\n\n==== 🧹 Housekeeping\n\n* Don't use fixed driver versions in doc.\n* Pass builder as constructor argument.\n* Improve `Return` and `With` internals.\n* Update Driver, SDN integration and Spring Boot example dependencies.\n* GH-202 - Make API Guardian an optional / provided dependency.\n\nThanks to https://github.com/meistermeier[@meistermeier] and https://github.com/aldrinm[@aldrinm] for their contributions.\n\n=== 2021.2.2\n\n==== 🚀 Features\n\n* Allow all expresions to be used as conditions. [improvement]\n* Add support for unary minus and plus operations. [new-feature]\n* Add support for generatic dynamic distinct aggregating function calls. [new-feature]\n* GH-190 - Introduce a union type for named things and aliased expressions.\n* Provide means to pass additional types to the relationship base class. [new-feature]\n* GH-193 - Allow MATCH after YIELD.\n* GH-189 - Provide an alternate api for methods consuming collections via vargs.\n\n==== 📖 Documentation\n\n* Improve inheritance example. [static-model, codegen]\n\n==== 🐛 Bug Fixes\n\n* Fix parameter collector when running as GraalVM native image\n* GH-192 - Don't introduce new symbolic names in conditional pattern expressions.\n\n==== 🧹 Housekeeping\n\n* GH-178 - Upgrade SDN 6 examples to Spring Boot 2.5 final.\n\nThanks to https://github.com/meistermeier[@meistermeier] for the contribution of the API improvements in regard to collections.\n\n=== 2021.2.1\n\n==== 🚀 Features\n\n* Distinguish between statements and result statements: The Cypher-DSL knows whether a statement would actually return\n  data or not\n* Provide optional integration with the Neo4j-Java-Driver to execute statements.\n* Allow to register Spring converters with the annotation processor. [codegen]\n* GH-182 - Add support for scalar converter functions.\n* GH-183 - Add trim function.\n* GH-184 - Add split function.\n* GH-180 - Add support for LOAD CSV and friends.\n* GH-187 - Add `returningRaw` for returning arbitrary (aliased) Cypher fragments (bot as part of a statement or as a\n  general `RETURN xxx` clause without preceding query)\n* Resolve named parameters in raw literals: You can mix now the expression placeholder `$E` and named parameters in raw\n  Cypher literals giving you much more flexibility in regards what to pass to the raw litera.\n\n==== 🐛 Bug Fixes\n\n* GH-177 - Create a valid loadable and instantiable name when working on nested, inner classes. [codegen]\n* GH-186 - Pretty print subqueries and fix double rendering of Labels after subquery.\n\n==== 🧹 Housekeeping\n\n* Remove unnecessary subpackage 'valid'. [codegen] (test code only)\n* Upgrade to GraalVM 21.1.0.\n* Update Spring dependencies for codegen.\n\nThanks to https://github.com/Andy2003[@Andy2003] for contributing to this release.\n\n=== 2021.2.0\n\n2021.2 doesn't bring any new features apart from being now a Java library supporting the Java module system not only with\nautomatic module names but also with a correct `module-info.java` when running on JDK 11+ on the module path.\n\nThe Cypher-DSL uses the technique of https://openjdk.java.net/jeps/238[JEP 238: Multi-Release JAR Files] to provide a\n`module-info.java` for projects being on JDK 11+.\n\nThe MR-Jar allows us to compile for JDK 8 but also support JDK 11 (we choose 11 as it is the current LTS release as time of writing).\n\nTo use the Cypher-DSL in a modular application you would need to require the following modules:\n\n[source,java]\n----\nmodule org.neo4j.cypherdsl.examples.core {\n\n\trequires org.neo4j.cypherdsl.core;\n}\n----\n\nThis release comes with a small catch: We do support using some https://github.com/querydsl/querydsl[QueryDSL] constructs.\nQuery-DSL will have correct automatic module names in their 5.x release and we asked them to backport those to the\n4.x line on which the Cypher-DSL *optionally* depends (See https://github.com/querydsl/querydsl/pull/2805[2805]).\n\nUntil then we statically require (that is \"optional\" in module speak) Query-DSL via the artifact name.\nThis can cause errors when the artifact (`querydsl-core.jar`)  is renamed via the build process or similar.\nWe are gonna improve that as soon as we can depend on fixed automatic module names.\n\nApart from this big change there is no change in any public API.\nThis release should be a drop-in replacement for the prior release.\n\nA big thank you to https://github.com/sormuras[@sormuras] for his invaluable lessons about the Java module system.\n"
  },
  {
    "path": "docs/appendix/2021.3.adoc",
    "content": "== 2021.3\n\n=== 2021.3.4\n\n2021.3.4 is a pure bug fix release.\n\n==== 🐛 Bug Fixes\n\n* GH-252 - Use a namespace for the message bundle.\n\n=== 2021.3.3\n\n2021.3.3 is a pure housekeeping release, however a release we are proud of. We do analyze this project now with https://www.sonarqube.org[SonarQube]\nvie https://sonarcloud.io[Sonarcloud] and are happy to announce that we have a quadruple A rating:\n\nimage::20211027_sonarcoud.jpg[]\n\nIn addition, we finally invited https://dependabot.com[Dependabot] taking care of at least creating the PRs.\n\n==== 🧹 Housekeeping\n\n* Fix reliability and security issues\n* Fix a minor amounts of remaining code smells\n* Bump several dependencies (only test and build related)\n\n=== 2021.3.2\n\n==== 🚀 Features\n\n* Add support for QueryDSL's `equalsIgnoreCase` operator\n* GH-204 - Provide access to identifiable expressions (See <<retrieving-identifiable-expressions>>)\n\n==== 🧹 Housekeeping\n\n* Fix several (compile) warnings\n* Fix several spelling errors in api docs\n* Upgrade Spring Data Neo4j to 6.1.5 (In module `org.neo4j.cypherdsl.codegen.sdn6`)\n* Upgrade Neo4j Cypher Parser to 4.3.4 (In module `neo4j-cypher-dsl-parser`).\n* Verify examples on JDK 17\n\n=== 2021.3.1\n\n2021.3.1 is a pure bug fix release. API Guardian cannot be an optional dependency, otherwise compiling programs with `-Werror`\nwill fail, as the `@API`-annotation has runtime and not class retention.\n\n==== 🐛 Bug Fixes\n\n* GH-203 - Introduce a scope for the `PatternComprehension`.\n* Revert \"GH-202 - Make API Guardian an optional / provided dependency.\"\n* Support empty BooleanBuilder in QueryDSL adapter.\n\n=== 2021.3.0\n\n==== 🚀 New module: The Cypher-DSL-Parser\n\n2021.3 builds straight upon <<2021.2.3>>, with few additions to the existing API, that didn't quite fit with a patch release,\nbut belong conceptually into this release, which brings a completely new module: The `neo4j-cypher-dsl-parser`.\n\nWhat's behind that name? A Cypher-Parser build on the official Neo4j 4.3 parser frontend and creating a Cypher-DSL-AST or\nsingle expressions usable in the context of the Cypher-DSL.\n\nThe module lives under the following coordinates `org.neo4j:neo4j-cypher-dsl-parser` and requires JDK 11+ (the same version like Neo4j does).\nWe created a couple of <<cypher-parser-examples,examples>>, but we are sure you will have tons of more ideas and therefore\na looking for your feedback.\n\nHere's a sneak preview. It shows you can add a user supplied Cypher fragment to something you are building using the DSL.\n\n[source,java]\n----\nvar userProvidedCypher\n    = \"MATCH (this)-[:LINK]-(o:Other) RETURN o as result\";\nvar userStatement = CypherParser.parse(userProvidedCypher);\n\nvar node = Cypher.node(\"Node\").named(\"node\");\nvar result = Cypher.name(\"result\");\nvar cypher = Cypher\n    .match(node)\n    .call(\n        userStatement,\n        node.as(\"this\")\n    )\n    .returning(result.project(\"foo\", \"bar\"))\n    .build()\n    .getCypher();\n----\n\nFor this release a big thank you goes out to the Cypher-operations team at Neo4j, listening to our requests and ideas!\n"
  },
  {
    "path": "docs/appendix/2021.4.adoc",
    "content": "== 2021.4\n\n=== 2021.4.2\n\n==== 🐛 Bug Fixes\n\n* GH-252 - Use a namespace for the message bundle.\n\nThanks to @Andy2003 for spotting this.\n\n==== 🧹 Housekeeping\n\n* Tons of dependency upgrades in test scope\n* The parser module now uses the Neo4j 4.3.7 parser\n* Bump apiguardian-api from 1.1.1 to 1.1.2 (#250)\n\n=== 2021.4.1\n\n==== 🚀 Features\n\nGH-230 - Add a way for a programmatic sort definition on expressions.\n\n==== 🧹 Housekeeping\n\n* Tons of dependency upgrades in test scope\n* Upgrade to Neo4j-Java-Driver 4.4.1. (a provided dependency)\n* The parser module now uses the Neo4j 4.3.6 parser\n\n=== 2021.4.0\n\n2021.4.0 updates the optional dependency to https://github.com/querydsl/querydsl[Querydsl] to 5.0.0. While this is API\nnot a breaking change, it can be when the Cypher-DSL is run together with Querydsl on the Java Module path. Querydsl\nmaintainer finally introduced automatic module names for all their module on which we can no reliable depend. As that\nmodule name is however different from the generated one, it will be a breaking change on the module path. Therefore\nwe bump our version, too.\n\n==== 🧹 Housekeeping\n\n* Upgrade Querydsl to 5.0.0\n"
  },
  {
    "path": "docs/appendix/2022.0.adoc",
    "content": "== 2022.0\n\n=== 2022.0.0\n\nStarting with the 2022 release line, all current experimental warnings have been removed, and we consider our API stable.\n\n==== Noteworthy\n\nAs we have marked the API as stable we do enforce semantic versioning in our builds now.\nThe parser module `neo4j-cypher-dsl-parser` has been updated to the Neo4j 4.4 parser and therefore doesn't bring in Scala dependencies anymore.\nAnd last but not least, we added the _Contributor Covenant Code of Conduct_.\n\n==== 🚀 Features\n\n* Indent `CREATE` in subqueries. (#254)\n\n==== 🐛 Bug Fixes\n\n* Fix broken asciidoc includes.\n* Give messages constant a better name (The bundle name we used might clash with other bundle names).\n\n==== 🧹 Housekeeping\n\n* Tons of dependency upgrades:\n** Bump reactor-bom from 2020.0.13 to 2020.0.14 (#265)\n** Bump checker-qual from 3.20.0 to 3.21.0 (#264)\n** Bump mockito.version from 4.1.0 to 4.2.0 (#263)\n** Bump neo4j-cypher-javacc-parser from 4.4.0 to 4.4.2 (#262)\n** Bump checker-qual from 3.19.0 to 3.20.0 (#261)\n** Bump neo4j-java-driver from 4.4.1 to 4.4.2 (#260)\n** Bump spring-boot-starter-parent from 2.5.6 to 2.6.1 (#259)\n** Bump checkstyle from 9.1 to 9.2 (#256)\n** Bump junit-bom from 5.8.1 to 5.8.2 (#257)\n** Bump mockito.version from 4.0.0 to 4.1.0 (#255)\n\nThanks again to https://github.com/Andy2003[Andy] for his contributions and feedback.\n"
  },
  {
    "path": "docs/appendix/2022.1.adoc",
    "content": "== 2022.1\n\n=== 2022.1.0\n\n*No breaking changes*. The minor version has been incremented to notify about new default methods in our interfaces. Those\nshouldn't concern you as a user though, as they are not meant to be implemented by you.\n\n==== Noteworthy\n\nOur integration tests on GitHub now uses the official GraalVM action: https://github.com/marketplace/actions/github-action-for-graalvm.\nThanks, https://github.com/meistermeier[Gerrit], for integrating it.\n\n==== 🚀 Features\n\n* Add `size` and `hasSize` on expressions. (#267)\n\n==== 🧹 Housekeeping\n\n* Some polishing (mainly working on getting a \"warning free\" build in all the tools)\n* Tons of dependency upgrades:\n** Bump testcontainers.version from 1.16.2 to 1.16.3 (#289)\n** Bump spring-boot-starter-parent from 2.6.2 to 2.6.3 (#290)\n** Bump mockito.version from 4.2.0 to 4.3.1 (#291)\n** Bump slf4j.version from 1.7.33 to 1.7.35 (#292)\n** Bump japicmp-maven-plugin from 0.15.4 to 0.15.6 (#293)\n** Bump neo4j-java-driver from 4.4.2 to 4.4.3 (#294)\n** Bump checkstyle from 9.2.1 to 9.3 (#295)\n** Bump asciidoctor-maven-plugin from 2.2.1 to 2.2.2 (#296)\n** Bump asciidoctorj from 2.5.2 to 2.5.3 (#285)\n** Bump maven-jar-plugin from 3.2.1 to 3.2.2 (#284)\n** Bump spring-data-neo4j from 6.2.0 to 6.2.1 (#283)\n** Bump reactor-bom from 2020.0.14 to 2020.0.15 (#282)\n** Bump slf4j.version from 1.7.32 to 1.7.33 (#281)\n** Bump neo4j-cypher-javacc-parser from 4.4.2 to 4.4.3 (#280)\n** Bump maven-jar-plugin from 3.2.0 to 3.2.1 (#277)\n** Bump checker-qual from 3.21.0 to 3.21.1 (#276)\n** Bump assertj-core from 3.21.0 to 3.22.0 (#272)\n** Bump maven-site-plugin from 3.9.1 to 3.10.0 (#270)\n** Bump maven-deploy-plugin from 3.0.0-M1 to 3.0.0-M2 (#271)\n** Bump checkstyle from 9.2 to 9.2.1 (#269)\n** Bump spring-boot-starter-parent from 2.6.1 to 2.6.2 (#268)\n** Bump Maven to 3.8.4.\n"
  },
  {
    "path": "docs/appendix/2022.10.adoc",
    "content": "== 2022.10\n\n=== 2022.10.0\n\nWelcome @ali-ince to the list of contributors to Cypher-DSL.\nWe are glad that you and your team are users of this module.\n\n==== 🚀 Features\n\n* Allow retrieving parameter names (#1071)\n* Allow chainable foreach. (#988)\n* Add builder methods for `FOREACH`. (#740)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Update Neo4j from 4.4.29 to 4.4.37\n** Update Neo4j Java Driver from 4.4.15 to 4.4.18\n"
  },
  {
    "path": "docs/appendix/2022.11.adoc",
    "content": "== 2022.11\n\n=== 2022.11.0\n\n==== 🚀 Features\n\n* Allow to call raw cypher from top level entry point (#1073) (#1074)\n"
  },
  {
    "path": "docs/appendix/2022.2.adoc",
    "content": "== 2022.2\n\n=== 2022.2.1\n\n*No breaking changes*.\n\n==== 🚀 Features\n\n* Add randomUUID to predefined functions.\n* Support additional mutate expression types. (#312)\n\n==== 🐛 Bug Fixes\n\n* Don't create empty `WITH` clause without renames. (#320)\n* Fix rendering of nested FOREACH statements. (#318)\n* Check for field type too when computing internalId usage.\n\n==== 📝 Documentation\n\n* Add example how to merge-find things via Springs `CypherdslStatementExecutor`.\n\n==== 🧹 Housekeeping\n\n* Remove Awaitility test-dependency.\n* Dependency upgrades:\n** Bump spring-data-neo4j from 6.2.2 to 6.2.3 (#332)\n** Bump neo4j-cypher-javacc-parser from 4.4.4 to 4.4.5 (#330)\n** Bump checkstyle from 10.0 to 10.1 (#329)\n** Bump jna from 5.10.0 to 5.11.0 (#331)\n** Bump spring-boot-starter-parent from 2.6.4 to 2.6.5 (#333)\n** Bump native-maven-plugin from 0.9.10 to 0.9.11 (#334)\n** Bump neo4j-java-driver from 4.4.3 to 4.4.5 (#328)\n** Bump reactor-bom from 2020.0.16 to 2020.0.17 (#327)\n** Bump mockito.version from 4.3.1 to 4.4.0 (#325)\n** Bump checkstyle from 9.3 to 10.0 (#323)\n** Bump guava from 31.0.1-jre to 31.1-jre (#324)\n** Bump checker-qual from 3.21.2 to 3.21.3 (#322)\n** Bump awaitility from 4.1.1 to 4.2.0 (#321)\n** Bump japicmp-maven-plugin from 0.15.6 to 0.15.7 (#313)\n** Bump spring-boot-starter-parent from 2.6.3 to 2.6.4 (#314)\n\n=== 2022.2.0\n\n*No breaking changes*. The minor version has been incremented to notify about a couple of new methods in the parser module, allowing for more and different types of parsing events to be emitted.\n\nThanks to @ikwattro for his input and feedback in this release.\n\n==== 🚀 Features\n\n* Emit pattern created event on merge clauses.\n* Add callbacks for a \"pattern element created event\". (#303)\n\n==== 📝 Documentation\n\n* Add an example how to track changed properties to nodes.\n* Add rewrite example.\n* Add examples how to extract modified labels for the Cypher parser.\n\n==== 🛠 Build\n\n* Fix surefire settings.\n* Add a 'fast' profile.\n* Reorder module-info.java creation before shading so that javadoc wont fail on vanilla JDK.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump maven-site-plugin from 3.10.0 to 3.11.0 (#311)\n** Bump native-maven-plugin from 0.9.9 to 0.9.10 (#310)\n** Bump maven-pmd-plugin from 3.15.0 to 3.16.0 (#309)\n** Bump spring-data-neo4j from 6.2.1 to 6.2.2 (#308)\n** Bump reactor-bom from 2020.0.15 to 2020.0.16 (#307)\n** Bump slf4j.version from 1.7.35 to 1.7.36 (#306)\n** Bump maven-javadoc-plugin from 3.3.1 to 3.3.2 (#305)\n** Bump neo4j-cypher-javacc-parser from 4.4.3 to 4.4.4 (#304)\n** Bump checker-qual from 3.21.1 to 3.21.2 (#298)\n"
  },
  {
    "path": "docs/appendix/2022.3.adoc",
    "content": "== 2022.3\n\n=== 2022.3.0\n\n*No breaking changes*. The minor version has been incremented due to the following changes:\n\n* Changes in the `ExposesSubqueryCall` (new methods to expose `callInTransactions`, but that interface is not meant for\n  external implementations anyway)\n* Added a new type `Dialect` and a new default method `enterWithResult` on the `Visitor` interface (have a look at the JavaDoc\n  for the rationale behind it).\n\n==== 🚀 Features\n\n* Add support for dialects.\n* Add support for toString(Expression). (#344)\n* Support `CALL {} IN TRANSACTIONS`.\n* Add parameter callbacks to the parser. (#336)\n\n==== 🐛 Bug Fixes\n\n* Prevent `ClassCastException` when using `String` arguments to import variables into a subquery.\n* Make generated static model usable with self referential associations. (#337, Thanks to @ChristophB for his input on #335).\n* Fix tag of CypherParser entry point. (docs)\n\n==== 📝 Documentation\n\n* Add information about GraalVM 21.3.0 and `org.graalvm.buildtools:native-maven-plugin` to CONTRIBUTING.adoc.\n\n==== 🛠 Build\n\n* Fix publish_docs workflow.\n* Add support for registering `allDeclaredConstructors`. (#342)\n* Add `RegisterForReflection` and processor replacing static reflection-config.json. (#341)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump jackson-bom from 2.13.2 to 2.13.2.20220328 (#346)\n** Bump asm from 9.2 to 9.3 (#347)\n** Bump jacoco-maven-plugin from 0.8.7 to 0.8.8 (#345)\n** Update managed version of error_prone_annotations to 2.12.1, avoiding compilation issues in IDEA.\n** Bump spring-boot-starter-parent from 2.6.5 to 2.6.6 (#340)\n** Bump checker-qual from 3.21.3 to 3.21.4 (#339)\n** Bump maven-shade-plugin from 3.2.4 to 3.3.0 (#338)\n"
  },
  {
    "path": "docs/appendix/2022.4.adoc",
    "content": "== 2022.4\n\n=== 2022.4.0\n\n* Added `withoutResults` to both in-statement and standalone call-builders so that one can use procedures without results\n  inside a pipeline. This won't break anything, as the corresponding interface is not meant to implemented by downstream\n  libraries\n* Compound conditions are now correctly immutable (as stated by the contract and its JavaDoc).\n  This might break things if you have them changed inflight.\n\nThanks to @Andy2003 for his input on this release.\n\n==== 🚀 Features\n\n* Allow procedure calls without results after a match clause. (#361)\n\n==== 🐛 Bug Fixes\n\n* Make `CompoundCondition` immutable obliging the interfaces contract. (#365)\n* Don't skip symbolic names if present and already in scope. (#363)\n\n==== 🛠 Build\n\n* Update github-push-action to 0.6.0.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump testcontainers.version from 1.16.3 to 1.17.1 (#352)\n** Bump reactor-bom from 2020.0.17 to 2020.0.18 (#353)\n** Bump mockito.version from 4.4.0 to 4.5.1 (#354)\n** Bump checkstyle from 10.1 to 10.2 (#355)\n** Bump spring-boot-starter-parent from 2.6.6 to 2.6.7 (#356)\n** Bump maven-javadoc-plugin from 3.3.2 to 3.4.0 (#357)\n** Bump maven-site-plugin from 3.11.0 to 3.12.0 (#358)\n** Bump spring-data-neo4j from 6.2.3 to 6.2.4 (#359)\n** Bump neo4j-cypher-javacc-parser from 4.4.5 to 4.4.6 (#360)\n** Bump checker-qual from 3.21.4 to 3.22.0 (#364)\n"
  },
  {
    "path": "docs/appendix/2022.5.adoc",
    "content": "== 2022.5\n\n=== 2022.5.0\n\n*No breaking changes*, the minor version has been bumped due to new default methods of internal interfaces.\nThis release is - again - a safe drop-in replacement for the prior (2022.4.0) one.\n\nThanks to @hindog, @bhspencer, @Hardu2203 and @irene221b for their input on this release.\n\n==== 🚀 Features\n\n* Add explicit `set` operation to `PropertyContainer`. (#394)\n* Support \"WITH *, <expr>\" by handling the 'returnAll' flag received from parser (#367)\n\n==== 🔄️ Refactorings\n\n* refactor: Remove superfluous whitespaces before `MapExpression` in pretty printer. (#401)\n\n==== 📝 Documentation\n\n* Add an example how to use Cypher parameters with`CypherdslStatementExecutor`. (#395)\n* Improve JavaDoc of `TemporalLiteral`.\n* Add correction method description.\n\n==== 🛠 Build\n\n* Use latest Neo4j 4.4 for integration tests.\n* Add a CODEOWNERS declaration.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump jna from 5.11.0 to 5.12.0 (#399)\n** Bump spring-boot-starter-parent from 2.7.0 to 2.7.1 (#398)\n** Bump spring-data-neo4j from 6.3.0 to 6.3.1 (#397)\n** Bump native-maven-plugin from 0.9.11 to 0.9.12 (#396)\n** Bump reactor-bom from 2020.0.19 to 2020.0.20 (#392)\n** Bump checker-qual from 3.22.1 to 3.22.2 (#390)\n** Bump neo4j-cypher-javacc-parser from 4.4.7 to 4.4.8 (#391)\n** Bump maven-enforcer-plugin from 3.0.0 to 3.1.0 (#386)\n** Bump joda-time from 2.10.10 to 2.10.14 (#387)\n** Bump asciidoctorj from 2.5.3 to 2.5.4 (#380)\n** Bump assertj-core from 3.22.0 to 3.23.1 (#383)\n** Bump checker-qual from 3.22.0 to 3.22.1 (#382)\n** Bump mockito.version from 4.6.0 to 4.6.1 (#381)\n** Bump neo4j-java-driver from 4.4.5 to 4.4.6 (#379)\n** Bump maven-pmd-plugin from 3.16.0 to 3.17.0 (#378)\n** Bump asciidoctorj-diagram from 2.2.1 to 2.2.3 (#377)\n** Bump mockito.version from 4.5.1 to 4.6.0 (#376)\n** Bump checkstyle from 10.2 to 10.3 (#375)\n** Bump neo4j-cypher-javacc-parser from 4.4.6 to 4.4.7 (#373)\n** Bump testcontainers.version from 1.17.1 to 1.17.2 (#371)\n** Bump spring-data-neo4j from 6.2.4 to 6.3.0 (#368)\n** Bump jackson-bom from 2.13.2.20220328 to 2.13.3 (#370)\n** Bump reactor-bom from 2020.0.18 to 2020.0.19 (#369)\n"
  },
  {
    "path": "docs/appendix/2022.6.adoc",
    "content": "== 2022.6\n\n=== 2022.6.1\n\n==== 🐛 Bug Fixes\n\n* Include aliased expression in local scopes. (#420)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump neo4j-cypher-javacc-parser from 4.4.8 to 4.4.9 (#418)\n** Bump maven-install-plugin from 3.0.0-M1 to 3.0.1 (#417)\n** Bump spring-boot-starter-parent from 2.7.1 to 2.7.2 (#416)\n** Bump maven-deploy-plugin from 3.0.0-M2 to 3.0.0 (#415)\n** Bump exec-maven-plugin from 3.0.0 to 3.1.0 (#414)\n** Bump native-maven-plugin from 0.9.12 to 0.9.13 (#413)\n** Bump spring-data-neo4j from 6.3.1 to 6.3.2 (#412)\n** Bump reactor-bom from 2020.0.20 to 2020.0.21 (#411)\n** Bump checker-qual from 3.22.2 to 3.23.0 (#410)\n\n=== 2022.6.0\n\n`Functions.internalId()` has been deprecated to accomodate for Neo4j 5 later this year.\nWe are unsure if we will do this to `id()`, too (The method with the same name will be deprecated in Neo4j 5 and eventually\nbe replaced by `elementId()`).\n\n==== 🚀 Features\n\n* Add fallback from `elementId` to `id` on older Neo4j versions. (#407)\n* Add calls for `elementId()`. (#406)\n\n==== 🔄️ Refactorings\n\n* Deprecate `internalId` in favor of `elementId` on nodes. (#408)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump testcontainers.version from 1.17.2 to 1.17.3 (#403)\n** Bump checkstyle from 10.3 to 10.3.1 (#404)\n** Bump jna from 5.12.0 to 5.12.1 (#405)\n"
  },
  {
    "path": "docs/appendix/2022.7.adoc",
    "content": "== 2022.7\n\n=== 2022.7.3\n\n==== 🚀 Features\n\n* Add `point.withinBBox` and convenience methods for cartesian points and coordinates. (#475)\n\n==== 🔄️ Refactorings\n\n* Remove superfluous field.\n\n==== 🛠 Build\n\n* Replace jQAssistant with easier to maintain Archunit test. (#466)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump jackson-bom from 2.13.4 to 2.13.4.20221013 (#479)\n** Bump neo4j-cypher-javacc-parser from 4.4.11 to 4.4.12 (#478)\n** Bump reactor-bom from 2020.0.23 to 2020.0.24 (#477)\n** Bump joda-time from 2.11.2 to 2.12.0 (#476)\n** Bump archunit from 0.23.1 to 1.0.0 (#471)\n** Bump neo4j-java-driver from 4.4.6 to 4.4.9 (#474)\n** Bump testcontainers.version from 1.17.3 to 1.17.5 (#470)\n** Bump checker-qual from 3.25.0 to 3.26.0 (#472)\n** Bump asm from 9.3 to 9.4 (#468)\n** Bump joda-time from 2.11.1 to 2.11.2 (#465)\n** Bump spring-boot-starter-parent from 2.7.3 to 2.7.4 (#464)\n** Bump junit-bom from 5.9.0 to 5.9.1 (#463)\n** Bump asciidoctorj from 2.5.5 to 2.5.6 (#462)\n** Bump checkstyle from 10.3.3 to 10.3.4 (#461)\n** Bump native-maven-plugin from 0.9.13 to 0.9.14 (#460)\n** Bump spring-data-neo4j from 6.3.2 to 6.3.3 (#459)\n** Bump jqassistant.plugin.git from 1.8.0 to 1.9.0 (#458)\n** Bump maven-jar-plugin from 3.2.2 to 3.3.0 (#457)\n** Bump reactor-bom from 2020.0.22 to 2020.0.23 (#456)\n** Bump maven-shade-plugin from 3.3.0 to 3.4.0 (#455)\n** Bump maven-pmd-plugin from 3.18.0 to 3.19.0 (#454)\n** Bump neo4j-cypher-javacc-parser from 4.4.10 to 4.4.11 (#452)\n** Bump mockito.version from 4.7.0 to 4.8.0 (#451)\n\n=== 2022.7.2\n\n*No breaking changes*. This adds a new module - `neo4j-cypher-dsl-schema-name-support` - that contains only one class, dedicated to sanitise and quote names that are meant to be used as labels and types. We are using it internally for all our quoting needs and if you have the need in your application to create dynamic queries that deal with the modification of labels and types, you might want to have a look at that module. It is dependency free and safe to shade. The background to do label and type manipulation is this: Cypher does not support them as parameters, you need to concatenate your query for this. In all other cases, please use proper parameter, but especially for string values.\n\nThanks to @AzuObs @AlexNeo4J and @robsdedude for their feedback on this work and also to @harshitp-fens for their inspiration of the `ON_DELETE_ITEM` parser callback.\n\n==== 🚀 Features\n\n* Provide `ON_DELETE_ITEM` event type. (#449)\n* Introduce standalone schema-name support module. (#445)\n\n==== 🛠 Build\n\n* Fix the build on a restricted TeamCity instance. (#450)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump checker-qual from 3.24.0 to 3.25.0 (#448)\n** Bump japicmp-maven-plugin from 0.15.7 to 0.16.0 (#447)\n** Bump jackson-bom from 2.13.3 to 2.13.4 (#446)\n** Bump checkstyle from 10.3.2 to 10.3.3 (#444)\n** Bump maven-checkstyle-plugin from 3.1.2 to 3.2.0 (#443)\n** Bump maven-pmd-plugin from 3.17.0 to 3.18.0 (#442)\n** Bump joda-time from 2.11.0 to 2.11.1 (#441)\n\n=== 2022.7.1\n\n*No breaking changes*. This is an important bug-fix release and a safe drop-in replacement for 2022.7.0 and all 2022.6 releases. If you can life with some deprecation warnings, it can be used as a drop-in for the 2022.5 and 2022.4 series, too.\n\n==== 🐛 Bug Fixes\n\n* Escape escaped Unicode 0060 (backtick) proper. (#436)\n\n==== 🔄️ Refactorings\n\n* Don't double escape already escaped backticks.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump mockito.version from 4.6.1 to 4.7.0 (#434):\n** Bump reactor-bom from 2020.0.21 to 2020.0.22 (#433):\n** Bump joda-time from 2.10.14 to 2.11.0 (#432):\n** Bump neo4j-cypher-javacc-parser from 4.4.9 to 4.4.10 (#431):\n** Bump maven-javadoc-plugin from 3.4.0 to 3.4.1 (#430):\n** Bump spring-boot-starter-parent from 2.7.2 to 2.7.3 (#439)\n** Bump flatten-maven-plugin from 1.2.7 to 1.3.0 (#437):\n\n=== 2022.7.0\n\n*No breaking changes*, the minor version has been bumped due to new default methods of internal interfaces.\nThis release is - again - a safe drop-in replacement for the prior (2022.6.1) one.\n\nThanks to https://github.com/AakashSorathiya[@AakashSorathiya] and https://github.com/nmervaillie[Nicolas Mervaillie] for their input on this release.\n\n==== 🚀 Features\n\n* Add support for `includesAll` and `includesAny` operations on expressions for list properties\n* Support `org.neo4j.cypher.internal.ast.factory.ASTExpressionFactory#ands`\n\n==== 🔄️ Refactorings\n\n* Add cause to unsupported to `UnsupportedCypherException`.\n\n==== 🛠 Build\n\n* Use current JBang action to verify on JDK 8. (#421)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump maven-site-plugin from 3.12.0 to 3.12.1 (#428)\n** Bump checker-qual from 3.23.0 to 3.24.0 (#429)\n** Bump checkstyle from 10.3.1 to 10.3.2 (#425)\n** Bump junit-bom from 5.8.2 to 5.9.0 (#424)\n** Bump maven-resources-plugin from 3.2.0 to 3.3.0 (#423)\n** Bump asciidoctorj from 2.5.4 to 2.5.5 (#422)\n"
  },
  {
    "path": "docs/appendix/2022.8.adoc",
    "content": "== 2022.8\n\n=== 2022.8.5\n\n==== 🐛 Bug Fixes\n\n* Apply prefixes after potential separator. (#606)\n\n==== 🔄️ Refactorings\n\n* Ensure getting the type of relationships without type is safe.\n\n==== 🛠 Build\n\n* Use `inputEncoding` for configuring checkstyle encoding.\n\n=== 2022.8.4\n\n==== 🐛 Bug Fixes\n\n* Correctly track identifiable elements. (#579)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump checker-qual from 3.29.0 to 3.30.0 (#601)\n** Bump maven-enforcer-plugin from 3.1.0 to 3.2.1 (#600)\n** Bump checkstyle from 10.6.0 to 10.7.0 (#598)\n** Bump asciidoctorj-diagram from 2.2.3 to 2.2.4 (#597)\n** Bump jackson-bom from 2.14.1 to 2.14.2 (#594)\n** Bump assertj-core from 3.24.1 to 3.24.2 (#576)\n** Bump maven-checkstyle-plugin from 3.2.0 to 3.2.1 (#564)\n** Bump junit-bom from 5.9.1 to 5.9.2 (#563)\n** Bump reactor-bom from 2022.0.1 to 2022.0.2 (#559)\n** Bump mockito.version from 4.11.0 to 5.0.0 (#558)\n** Bump annotations from 23.1.0 to 24.0.0 (#557)\n** Bump jna from 5.12.1 to 5.13.0 (#556)\n\n=== 2022.8.3\n\n==== 🔄️ Refactorings\n\n* Allow `yield *` for standalone calls with arguments, too. (#545, thanks to @zakjan taking the time and report this)\n\n==== 🧹 Housekeeping\n\n* Extend license header to 2023.\n* Dependency upgrades:\n** Bump assertj-core from 3.23.1 to 3.24.1 (#549)\n** Bump checker-qual from 3.28.0 to 3.29.0 (#548)\n** Bump checkstyle from 10.5.0 to 10.6.0 (#537)\n** Bump mockito.version from 4.10.0 to 4.11.0 (#536)\n\n=== 2022.8.2\n\nThanks to @ikwattro from @graphaware for investing his time and creating valuable tickets for this release.\n\n==== 🐛 Bug Fixes\n\n* Allow `match` after unwind as defined by OpenCypher. (#531)\n\n==== 📝 Documentation\n\n* Make clear that pretty printing does not always escape names\n\n==== 🛠 Build\n\n* Upgrade various actions to non-deprecated versions. (#519)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump annotations from 23.0.0 to 23.1.0 (#521)\n** Bump compile-testing from 0.20 to 0.21.0 (#526)\n** Bump reactor-bom from 2022.0.0 to 2022.0.1 (#527)\n** Bump mockito.version from 4.9.0 to 4.10.0 (#528)\n\n=== 2022.8.1\n\n==== 🔄️ Refactorings\n\n* Apply learnings from full JDK 17 migrations.\n* Prevent usage of `REMOVE` item inside `SET` clause (during RT). (#506)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump checker-qual from 3.27.0 to 3.28.0 (#517)\n** Bump compile-testing from 0.19 to 0.20 (#516)\n** Bump native-maven-plugin from 0.9.18 to 0.9.19 (#515)\n** Bump joda-time from 2.12.1 to 2.12.2 (#514)\n** Bump jackson-bom from 2.14.0 to 2.14.1 (#513)\n** Bump archunit from 1.0.0 to 1.0.1 (#512)\n** Bump native-maven-plugin from 0.9.17 to 0.9.18 (#511)\n** Bump checkstyle from 10.4 to 10.5.0 (#510)\n\n=== 2022.8.0\n\n==== 🚀 Features\n\n* Add `yield *` for standalone calls. (#497)\n\n==== 📝 Documentation\n\n* Add missing value to `sanitize` JavaDoc. (#496)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump testcontainers.version from 1.17.5 to 1.17.6 (#502)\n** Bump maven-install-plugin from 3.0.1 to 3.1.0 (#501)\n** Bump japicmp-maven-plugin from 0.16.0 to 0.17.1 (#499)\n** Bump mockito.version from 4.8.1 to 4.9.0 (#498)\n** Bump jackson-bom from 2.13.4.20221013 to 2.14.0 (#492)\n** Bump checker-qual from 3.26.0 to 3.27.0 (#493)\n** Bump reactor-bom from 2020.0.24 to 2022.0.0 (#495)\n** Bump native-maven-plugin from 0.9.16 to 0.9.17 (#491)\n** Bump maven-shade-plugin from 3.4.0 to 3.4.1 (#487)\n** Bump checkstyle from 10.3.4 to 10.4 (#488)\n** Bump joda-time from 2.12.0 to 2.12.1 (#486)\n** Bump spring-boot-starter-parent from 2.7.4 to 2.7.5 (#485)\n** Bump asciidoctorj from 2.5.6 to 2.5.7 (#483)\n** Bump native-maven-plugin from 0.9.14 to 0.9.16 (#482)\n** Bump mockito.version from 4.8.0 to 4.8.1 (#481)\n"
  },
  {
    "path": "docs/appendix/2022.9.adoc",
    "content": "== 2022.9\n\n=== 2022.9.2\n\n==== 🚀 Features\n\n* Allow calling of raw Cypher strings in sub queries. (Backport from 2023.x)\n\n==== 🐛 Bug Fixes\n\n* Driving symbolic names for list predicate function must not be scoped. (#905)\n\n==== 🔄️ Refactorings\n\n* Allow unit-subqueries (Backport from 2023.x)\n\n==== 🧰 Tasks\n\n* Extend license header to 2024.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump spring-boot-starter-parent from 2.7.5 to 2.7.18\n** Update Spring Data Neo4j from 6.3.14 to 6.3.18\n** Bump reactor-bom from 2022.0.2 to 2022.0.15\n** Update Neo4j from 4.4.23 to 4.4.29\n** Update Neo4j Java Driver from 4.4.12 to 4.4.13\n** Update Neo4j Java Driver from 4.4.13 to 4.4.15\n** Bump testcontainers.version from 1.17.6 to 1.19.7\n\n==== 🛠 Build\n\n* Update various build related plugins.\n\n=== 2022.9.1\n\n==== 🐛 Bug Fixes\n\n* Apply the correct includesAll and includesAny semantics (#819)\n\n=== 2022.9.0\n\n==== 🚀 Features\n\n* Add callbacks for function and procedure invocations. (#758)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Update Spring Data Neo4j from 6.3.5 to 6.3.14\n** Update Neo4j from 4.4.12 to 4.4.23\n** Update Neo4j Java Driver from 4.4.9 to 4.4.12\n"
  },
  {
    "path": "docs/appendix/2023.0.adoc",
    "content": "== 2023.0\n\n=== 2023.0.5\n\n==== 🐛 Bug Fixes\n\n* Apply the correct includesAll and includesAny semantics (#819)\n\n=== 2023.0.4\n\n2023.0.4 is a bug fix release and fully compatible with 2023.0.3.\n\n==== 🐛 Bug Fixes\n\n* Correctly shadow visible nodes in a subquery. (#616)\n* Parse Node pattern predicates correctly. (#615)\n* Ensure getting the type of relationships without type is safe.\n* Apply prefixes after potential separator. (#606)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump neo4j-java-driver from 5.5.0 to 5.6.0 (#621)\n** Bump spring-boot-starter-parent from 3.0.2 to 3.0.3 (#619)\n** Bump checkstyle from 10.7.0 to 10.8.0 (#620)\n** Bump spring-data-neo4j from 7.0.0 to 7.0.2 (#614)\n** Bump maven-surefire-plugin from 3.0.0-M8 to 3.0.0-M9 (#613)\n** Bump maven-failsafe-plugin from 3.0.0-M8 to 3.0.0-M9 (#612)\n** Bump checker-qual from 3.30.0 to 3.31.0 (#611)\n** Bump reactor-bom from 2022.0.1 to 2022.0.3 (#610)\n** Bump native-maven-plugin from 0.9.19 to 0.9.20 (#608)\n** Bump maven-javadoc-plugin from 3.4.1 to 3.5.0 (#607)\n** Bump neo4j-cypher-javacc-parser from 5.4.0 to 5.5.0 (#609)\n\n=== 2023.0.3\n\nThanks to @Andy2003 for their input on several bugs!\n\n==== 🐛 Bug Fixes\n\n* Resolve symbolic names when looking for visited items. (#602)\n* Open implicit scope when entering a `UNION` clause. (#590)\n* Move resolved symbolic names into `StatementContext`. (#588)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump maven-surefire-plugin from 3.0.0-M7 to 3.0.0-M8 (#555)\n** Bump maven-failsafe-plugin from 3.0.0-M7 to 3.0.0-M8 (#560)\n** Bump checker-qual from 3.29.0 to 3.30.0 (#601)\n** Bump maven-enforcer-plugin from 3.1.0 to 3.2.1 (#600)\n** Bump mockito.version from 4.11.0 to 5.1.1 (#599)\n** Bump checkstyle from 10.6.0 to 10.7.0 (#598)\n** Bump asciidoctorj-diagram from 2.2.3 to 2.2.4 (#597)\n** Bump jackson-bom from 2.14.1 to 2.14.2 (#594)\n** Bump neo4j-java-driver from 5.3.1 to 5.5.0 (#592)\n** Bump neo4j-cypher-javacc-parser from 5.3.0 to 5.4.0 (#593)\n\n=== 2023.0.2\n\nThanks to @ikwattro, @lukaseder and @bonelli for their input!\n\n==== 🚀 Features\n\n* Add missing string functions. (#584)\n* Add support for rewriting the `MATCH` clause after parsing. (#580)\n\n==== 🐛 Bug Fixes\n\n* Add support for label expressions. (#582)\n* Correctly track identifiable elements. (#579)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump spring-boot-starter-parent from 3.0.1 to 3.0.2 (#577)\n** Bump assertj-core from 3.24.1 to 3.24.2 (#576)\n\n==== 🛠 Build\n\n* Move the fixed `module-info.java` somewhere out of IDEAs reach.\n\n=== 2023.0.1\n\nThis patch releases adds a build-in `length` function for paths (thanks @Lukasmp3 for the request) and fixes issues when running Cypher-DSL on the module path (see c7747ca35 on main for more information).\n\n==== 🚀 Features\n\n* Add `length()` function. (#569)\n\n==== 🔄️ Refactorings\n\n* Replace `requires static transitive` with `requires static`.\n\n=== 2023.0.0\n\nWelcome to 2023, welcome Java 17, welcome Neo4j 5 clauses. This is the first release of the Cypher-DSL requiring Java 17. This is in line with Neo4j itself, Spring Data Neo4j 7 and several other frameworks out there. This allows for more concise code (which is nice for us) as well as using the Neo4j 5 parser in `neo4j-cypher-dsl-parser` module. Bumping the JDK warrants a major upgrade already.\n\nApart from that we have been very reluctant on breaking changes. As a matter of fact, close to none has been necessary. One of the few improvements that might need changes on your side is #551 (Commit 10080df) in which we improved the `WITH` clause: You might see ambiguous method errors and the fix can be seen https://github.com/neo4j-contrib/cypher-dsl/commit/10080df4c537742218584d80bf4682dd74088a15#diff-dd86a606c4e4fe3151d8d7bb6af70b1aeecb25b5a32bcc9e9862483ca666a261[here] for example: Either use JDK 17 reserved name `var` for local variable type-inference or use explicit `IdentifiableElement`.\n\nThere's a lot of new stuff as well: You can now use `Expressions.count` to build new Neo4j 5 `COUNT` expressions and we do support the `USE` clause for composite database queries as well.\n\nPlease fear not if you are still on JDK 8: We will maintain the 2022.8.x branch at least as long as Spring Data Neo4j 6.3 is maintained, as the latter is build on top of the Cypher-DSL and is JDK 8, too.\n\nThanks a lot to our friend @ikwattro from @graphaware for his continuous and well appreciated feedback and input to this project.\n\n==== 🚀 Features\n\n* Add support for the `COUNT {}` sub-query expressions. (#546)\n* Pretty print `USE` clause proper. (#543, thanks to @ikwattro for contributing this)\n* Add support for the `USE` clause in the DSL. (#542)\n\n==== 🐛 Bug Fixes\n\n* Allow `match` after unwind as defined by OpenCypher. (#531)\n\n==== 🔄️ Refactorings\n\n* Improve `returning` and `with`. (#551)\n* Allow `yield *` for standalone calls with arguments, too. (#545, thanks to @zakjan taking the time and report this)\n* Upgrade the parser module to use the new Neo4j 5 parser. (#503)\n* Migrate the project to Java 17. (#518)\n* Prevent usage of `REMOVE` item inside `SET` clause (during RT). (#506)\n\n==== 📖 Documentation\n\n* Update changelog.\n* Add section about dialect support.\n* Make clear that pretty printing does not always escape names.\n* Document correct Java version in `README.adoc`.\n\n==== 🧰 Tasks\n\n* Extend license header to 2023.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump assertj-core from 3.23.1 to 3.24.1 (#549)\n** Bump checker-qual from 3.28.0 to 3.29.0 (#548)\n** Bump neo4j-java-driver from 5.3.0 to 5.3.1 (#535)\n** Bump spring-boot-starter-parent from 3.0.0 to 3.0.1 (#534)\n** Bump checkstyle from 10.5.0 to 10.6.0 (#537)\n** Bump mockito.version from 4.10.0 to 4.11.0 (#536)\n** Bump neo4j-cypher-javacc-parser from 5.2.0 to 5.3.0 (#529)\n** Bump annotations from 23.0.0 to 23.1.0 (#521)\n** Bump compile-testing from 0.20 to 0.21.0 (#526)\n** Bump reactor-bom from 2022.0.0 to 2022.0.1 (#527)\n** Bump mockito.version from 4.9.0 to 4.10.0 (#528)\n** Bump spring-boot-starter-parent from 2.7.5 to 3.0.0 (#509)\n** Bump neo4j-java-driver from 4.4.9 to 5.3.0 (#508)\n** Bump checker-qual from 3.27.0 to 3.28.0 (#517)\n** Bump compile-testing from 0.19 to 0.20 (#516)\n** Bump native-maven-plugin from 0.9.18 to 0.9.19 (#515)\n** Bump joda-time from 2.12.1 to 2.12.2 (#514)\n** Bump jackson-bom from 2.14.0 to 2.14.1 (#513)\n** Bump archunit from 1.0.0 to 1.0.1 (#512)\n** Bump native-maven-plugin from 0.9.17 to 0.9.18 (#511)\n** Bump checkstyle from 10.4 to 10.5.0 (#510)\n\n==== 🛠 Build\n\n* Add more tests for GH-547.\n* Define JaCoCo config in plugin-management. (#541)\n* Add `license-maven-plugin` for checking Apache 2 compatible license and header formatting.\n* Fix quality gate.\n* Verify examples on Java LTS and next version.\n* Fix docs build.\n* Upgrade various actions to non-deprecated versions. (#519)\n"
  },
  {
    "path": "docs/appendix/2023.1.adoc",
    "content": "== 2023.1\n\n=== 2023.1.0\n\n2023.1.0 is the first feat release after 2023.0.0 and contains several ideas and improvements that stem from https://github.com/neo4j-contrib/sql2cypher[sql2cypher] and from input by @lukaseder. Thank you!\n\nAdditionally, we worked again with @ikwattro from https://graphaware.com[Graph Aware] on building the catalog feature. Each statement - regardless of being built or parsed with the Cypher-DSL - can be analyzed via it's catalog now. The catalog will contain labels, types and properties used in a statement and the filters created based on those tokens. You can access the catalog like this:\n\n[source,java]\n----\nvar input = \"\"\"\n    MATCH (m:`Movie` {title: 'The Matrix'})<-[a:`ACTED_IN`]-(p:`Person`)\n    WHERE p.born >= $born\n    RETURN p\n    \"\"\";\nvar statement = CypherParser.parse(input);\n\nvar catalog = statement.getCatalog();\n----\n\nAlso: All AST elements will now render themselves to Cypher-Fragments when used in `toString()` scenarios. Apart from that, all bug fixes and dependency upgrades from 2022.8.5 and 2023.0.4 are included:\n\n==== 🚀 Features\n\n* Add overloads for `count` and `exists` taking in a statement and optional imports. (#623)\n* Add label existences conditions to catalog. (#622)\n* Provide a catalog for identifiable items in a statement. (#617)\n* Allow retrieving parameter names\n* Add missing string functions. (#584)\n* Add support for rewriting the `MATCH` clause after parsing. (#580)\n* Add `length()` function. (#569)\n* Allow direct rendering of `Visitable` objects. (#554)\n\n==== 🐛 Bug Fixes\n\n* Correctly shadow visible nodes in a subquery. (#616)\n* Parse Node pattern predicates correctly. (#615)\n* Ensure getting the type of relationships without type is safe.\n* Apply prefixes after potential separator. (#606)\n* Resolve symbolic names when looking for visited items. (#602)\n* Open implicit scope when entering a `UNION` clause. (#590)\n* Move resolved symbolic names into `StatementContext`. (#586)\n* Add support for label expressions. (#583)\n* Correctly track identifiable elements. (#579)\n\n==== 🔄️ Refactorings\n\n* Replace `requires static transitive` with `requires static`.\n* Allow covariant collection overloads for `PatternElement` and `Expression` where sensible. (#566)\n\n==== 📖 Documentation\n\n* Fix title.\n* Improve JavaDoc.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump neo4j-java-driver from 5.5.0 to 5.6.0 (#621)\n** Bump spring-boot-starter-parent from 3.0.2 to 3.0.3 (#619)\n** Bump checkstyle from 10.7.0 to 10.8.0 (#620)\n** Bump spring-data-neo4j from 7.0.1 to 7.0.2 (#614)\n** Bump maven-surefire-plugin from 3.0.0-M8 to 3.0.0-M9 (#613)\n** Bump maven-failsafe-plugin from 3.0.0-M8 to 3.0.0-M9 (#612)\n** Bump checker-qual from 3.30.0 to 3.31.0 (#611)\n** Bump reactor-bom from 2022.0.2 to 2022.0.3 (#610)\n** Bump native-maven-plugin from 0.9.19 to 0.9.20 (#608)\n** Bump maven-javadoc-plugin from 3.4.1 to 3.5.0 (#607)\n** Bump neo4j-cypher-javacc-parser from 5.4.0 to 5.5.0 (#609)\n** Bump maven-deploy-plugin from 3.0.0 to 3.1.0 (#603)\n** Bump checker-qual from 3.29.0 to 3.30.0 (#601)\n** Bump maven-enforcer-plugin from 3.1.0 to 3.2.1 (#600)\n** Bump mockito.version from 5.0.0 to 5.1.1 (#599)\n** Bump checkstyle from 10.6.0 to 10.7.0 (#598)\n** Bump asciidoctorj-diagram from 2.2.3 to 2.2.4 (#597)\n** Bump jackson-bom from 2.14.1 to 2.14.2 (#594)\n** Bump neo4j-java-driver from 5.4.0 to 5.5.0 (#592)\n** Bump neo4j-cypher-javacc-parser from 5.3.0 to 5.4.0 (#593)\n** Bump spring-boot-starter-parent from 3.0.1 to 3.0.2 (#577)\n** Bump assertj-core from 3.24.1 to 3.24.2 (#576)\n** Bump maven-checkstyle-plugin from 3.2.0 to 3.2.1 (#564)\n** Bump junit-bom from 5.9.1 to 5.9.2 (#563)\n** Bump maven-failsafe-plugin from 3.0.0-M7 to 3.0.0-M8 (#560)\n** Bump reactor-bom from 2022.0.1 to 2022.0.2 (#559)\n** Bump mockito.version from 4.11.0 to 5.0.0 (#558)\n** Bump annotations from 23.1.0 to 24.0.0 (#557)\n** Bump jna from 5.12.1 to 5.13.0 (#556)\n** Bump maven-surefire-plugin from 3.0.0-M7 to 3.0.0-M8 (#555)\n** Bump spring-data-neo4j from 7.0.0 to 7.0.1 (#562)\n** Bump neo4j-java-driver from 5.3.1 to 5.4.0 (#561)\n\n==== 🛠 Build\n\n* Improve configuration of the license plugin.\n* Move the fixed `module-info.java` somewhere out of IDEAs reach.\n"
  },
  {
    "path": "docs/appendix/2023.2.adoc",
    "content": "== 2023.2\n\n=== 2023.2.1\n\n==== 🚀 Features\n\n* Add adapter for Neo4j driver value.\n* Add support for `Duration` and `Period` literals.\n\n==== 🔄️ Refactorings\n\n* Use `StringBuilder` with `Matcher#appendReplacement`.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump neo4j-cypher-javacc-parser from 5.5.0 to 5.6.0 (#657)\n** Bump maven-install-plugin from 3.1.0 to 3.1.1 (#664)\n** Bump joda-time from 2.12.2 to 2.12.4 (#663)\n** Bump spring-boot-starter-parent from 3.0.4 to 3.0.5 (#662)\n** Bump asm from 9.4 to 9.5 (#661)\n** Bump checkstyle from 10.9.2 to 10.9.3 (#660)\n** Bump maven-deploy-plugin from 3.1.0 to 3.1.1 (#659)\n** Bump spring-data-neo4j from 7.0.3 to 7.0.4 (#658)\n** Bump maven-resources-plugin from 3.3.0 to 3.3.1 (#656)\n\n=== 2023.2.0\n\nThanks to @Andy2003 for his input on the 2023.2.0 release. The main topic of this release is https://github.com/neo4j-contrib/cypher-dsl/issues/596[adding support for semantic comparison]. The Cypher-DSLs builder method creates an AST, so that is in theory an excellent and doable request. The AST has originally been created as good enough means of rendering Cypher proper when we invented the Cypher-DSL for Spring Data Neo4j 6 back in 2019. Good enough here means that it has optimizing potential and a full-blown analysis is - at least at the moment - out of scope.\n\nInstead, we went with another approach: We added ways of normalizing\n\n* Variable names (identifiers for entities (nodes and relationships) and variables of lists and map comprehensions)\n* Parameter names\n* Aliases\n\ninto generated names and optionally make the parsing of literal Cypher maps constant (maps sorted alphabetically and not by order of key appearance).\n\nThis allows now for a \"poor man's\" semantic comparison. Imagine 2 Cypher-DSL `Statement` objects that you either created using the builder or parsed through our parser module. You can compare them like this:\n\n[source,java]\n----\nstatic boolean areSemanticallyEquivalent(Statement statement1, Map<String, Object> args1, Statement statement2, Map<String, Object> args2) {\n\n    if (!areSemanticallyEquivalent(statement1, statement2)) {\n        return false;\n    }\n\n    var mapping1 = statement1.getCatalog().getRenamedParameters();\n    var mapping2 = statement2.getCatalog().getRenamedParameters();\n    for (Map.Entry<String, String> entry : mapping1.entrySet()) {\n        String key1 = entry.getKey();\n        String mapped = entry.getValue();\n\n        String key2 = mapping2.entrySet().stream().filter(e -> e.getValue().equals(mapped))\n            .map(Map.Entry::getKey).findFirst().orElseThrow();\n        if (!args1.get(key1).equals(args2.get(key2))) {\n            return false;\n        }\n    }\n\n    return true;\n}\n----\n\nThe catalog featured added in 2023.1.0 has been enhanced so that it can return now the mapping of the renamed parameters as well, allowing for inspection of parameters from different sources.\n\nAlso thanks to @hindog for contributing map literals in #642 and to @sathishkumar294 for inspiring the new dedicated overloads for `type` and `labels` that now work with symbolic names, too.\n\n==== 🚀 Features\n\n* Allow map literals to be parsed into sorted maps. (#644)\n* Add support for Map literals. (#642)\n* Use generated names for aliases too if possible. (#640)\n* Make the `Asterisk` proper identifiable. (#641)\n* Add `Cypher.withAll` to create a with clause importing all (`*`) variables. (#639)\n* Add overloads of `Functions.type` and `Functions.labels` taking in a symbolic name. (#633)\n* Add extended meta data and the ability to use generated variables. (#631)\n\n==== 🔄️ Refactorings\n\n* Replace identifiers in list / pattern comprehensions, too. (#647)\n* Use scope for generated names. (#646)\n* Some general housekeeping. (#643 and #632)\n* Optimize structure of `UNWIND`.\n\n==== 📖 Documentation\n\n* Add a list comprehension example.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump checkstyle from 10.8.1 to 10.9.2 (#653)\n** Bump reactor-bom from 2022.0.4 to 2022.0.5 (#652)\n** Bump asciidoctor-maven-plugin from 2.2.2 to 2.2.3 (#651)\n** Bump maven-failsafe-plugin from 3.0.0-M9 to 3.0.0 (#650)\n** Bump maven-surefire-plugin from 3.0.0-M9 to 3.0.0 (#649)\n** Bump flatten-maven-plugin from 1.3.0 to 1.4.0 (#648)\n** Bump moditect-maven-plugin from 1.0.0.RC2 to 1.0.0.RC3 (#637)\n** Bump checkstyle from 10.8.0 to 10.8.1 (#638)\n** Bump mockito.version from 5.1.1 to 5.2.0 (#636)\n** Bump spring-boot-starter-parent from 3.0.3 to 3.0.4 (#629)\n** Bump annotations from 24.0.0 to 24.0.1 (#628)\n** Bump checker-qual from 3.31.0 to 3.32.0 (#627)\n** Bump spring-data-neo4j from 7.0.2 to 7.0.3 (#626)\n** Bump reactor-bom from 2022.0.3 to 2022.0.4 (#625)\n** Bump japicmp-maven-plugin from 0.17.1 to 0.17.2 (#624)\n\n==== 🛠 Build\n\n* Use correct version numbers for tags.\n* Replace symlink in gh-pages with static href.\n"
  },
  {
    "path": "docs/appendix/2023.3.adoc",
    "content": "== 2023.3\n\n=== 2023.3.2\n\n==== 🐛 Bug Fixes\n\n* Relationship chains didn't explicitly enter their elements. (#718)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump spring-boot-starter-parent from 3.0.6 to 3.1.0 (#711)\n** Bump neo4j-cypher-javacc-parser from 5.7.0 to 5.8.0 (#709)\n** Bump guava from 31.1-jre to 32.0.0-jre (#714)\n** Bump checkstyle from 10.11.0 to 10.12.0 (#717)\n** Bump asciidoctor-maven-plugin from 2.2.3 to 2.2.4 (#716)\n** Bump maven-checkstyle-plugin from 3.2.2 to 3.3.0 (#715)\n** Bump neo4j-java-driver from 5.8.0 to 5.9.0 (#713)\n** Bump jackson-bom from 2.15.0 to 2.15.1 (#710)\n** Bump maven-source-plugin from 3.2.1 to 3.3.0 (#708)\n** Bump testcontainers.version from 1.18.0 to 1.18.1 (#704)\n** Bump native-maven-plugin from 0.9.21 to 0.9.22 (#707)\n** Bump reactor-bom from 2022.0.6 to 2022.0.7 (#706)\n** Bump asciidoctorj-diagram from 2.2.7 to 2.2.8 (#705)\n** Bump checkstyle from 10.10.0 to 10.11.0 (#703)\n** Bump flatten-maven-plugin from 1.4.1 to 1.5.0 (#702)\n** Bump spring-data-neo4j from 7.0.5 to 7.1.0 (#701)\n\n=== 2023.3.1\n\n==== 📖 Documentation\n\n* Add an example combining existential sub-queries and custom procedure calls (#694)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump maven-failsafe-plugin from 3.0.0 to 3.1.0 (#698)\n** Bump checker-qual from 3.33.0 to 3.34.0 (#697)\n** Bump maven-surefire-plugin from 3.0.0 to 3.1.0 (#696)\n** Bump moditect-maven-plugin from 1.0.0.RC3 to 1.0.0.Final (#695)\n** Bump checkstyle from 10.9.3 to 10.10.0 (#692)\n** Bump junit-bom from 5.9.2 to 5.9.3 (#691)\n** Bump neo4j-java-driver from 5.7.0 to 5.8.0 (#690)\n** Bump jacoco-maven-plugin from 0.8.9 to 0.8.10 (#689)\n** Bump neo4j-cypher-javacc-parser from 5.6.0 to 5.7.0 (#685)\n** Bump jackson-bom from 2.14.2 to 2.15.0 (#688)\n** Bump spring-boot-starter-parent from 3.0.5 to 3.0.6 (#687)\n** Bump maven-checkstyle-plugin from 3.2.1 to 3.2.2 (#686)\n** Bump mockito.version from 5.3.0 to 5.3.1 (#684)\n\n=== 2023.3.0\n\n==== 🚀 Features\n\n* Allow retrieval of relationship details from the catalog.\n\n==== 🐛 Bug Fixes\n\n* Collect `LabelExpression`'s into the catalog, too. (#676)\n\n==== 🔄️ Refactorings\n\n* Deprecate `Functions.id()` in favor of `elementId()`. (#678)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump native-maven-plugin from 0.9.20 to 0.9.21 (#683)\n** Bump reactor-bom from 2022.0.5 to 2022.0.6 (#682)\n** Bump asciidoctorj from 2.5.7 to 2.5.8 (#681)\n** Bump mockito.version from 5.2.0 to 5.3.0 (#680)\n** Bump spring-data-neo4j from 7.0.4 to 7.0.5 (#679)\n** Bump jacoco-maven-plugin from 0.8.8 to 0.8.9 (#672)\n** Bump testcontainers.version from 1.17.6 to 1.18.0 (#671)\n** Bump maven-enforcer-plugin from 3.2.1 to 3.3.0 (#673)\n** Bump asciidoctorj-diagram from 2.2.4 to 2.2.7 (#670)\n** Bump checker-qual from 3.32.0 to 3.33.0 (#669)\n** Bump flatten-maven-plugin from 1.4.0 to 1.4.1 (#668)\n** Bump joda-time from 2.12.4 to 2.12.5 (#667)\n** Bump neo4j-java-driver from 5.6.0 to 5.7.0 (#666)\n\n==== 🛠 Build\n\n* Skip driver IT without docker. (#665)\n"
  },
  {
    "path": "docs/appendix/2023.4.adoc",
    "content": "== 2023.4\n\n=== 2023.4.0\n\n2023.4.0 comes with a whole list of new features.\nAs we deprecated two things (the `DEFAULT` dialect and `org.neo4j.cypherdsl.core.Cypher.use(org.neo4j.cypherdsl.core.SymbolicName, org.neo4j.cypherdsl.core.Statement)`), your project might break depending on your warning settings. The `DEFAULT` dialect is now `org.neo4j.cypherdsl.core.renderer.Dialect.NEO4J_4` (which keeps on being the default) and the `use` method has a new overload taking in an expression. You might need to explicitly cast here until we remove the deprecated method for good. This change was necessary to be able to put all functions in the `graph.*` namespace to use.\n\nThanks to our reporters, contributors and supporters @xdelox, @ikwattro, @nmervaillie and Rohan Kharwar.\n\n==== 🚀 Features\n\n* Introduce event to capture parsed literals. (#742)\n* Allow retrieval of literals. (#741)\n* Add builder methods for `FOREACH`. (#740)\n* Provide all functions in the `graph.*` namespaces. (#734)\n* Provide a way to fill parsed parameters with values. (#732)\n\n==== 🐛 Bug Fixes\n\n* Strip off octal prefix.\n\n==== 🔄️ Refactorings\n\n* Replace `DEFAULT` dialect with explicit `NEO4J_4` dialect. (#736)\n* Use sorted sets everywhere to keep orders of identifiables in the catalog close to users expectations. (#733)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump neo4j-cypher-javacc-parser from 5.8.0 to 5.9.0 (#743)\n** Bump reactor-bom from 2022.0.7 to 2022.0.8 (#748)\n** Bump mockito.version from 5.3.1 to 5.4.0 (#747)\n** Bump spring-data-neo4j from 7.1.0 to 7.1.1 (#746)\n** Bump native-maven-plugin from 0.9.22 to 0.9.23 (#745)\n** Bump maven-shade-plugin from 3.4.1 to 3.5.0 (#744)\n** Bump guava from 32.0.0-jre to 32.0.1-jre (#726)\n** Bump maven-surefire-plugin from 3.1.0 to 3.1.2 (#725)\n** Bump maven-failsafe-plugin from 3.1.0 to 3.1.2 (#724)\n** Bump asciidoctorj-diagram from 2.2.8 to 2.2.9 (#723)\n** Bump jackson-bom from 2.15.1 to 2.15.2 (#722)\n** Bump testcontainers.version from 1.18.1 to 1.18.3 (#721)\n** Bump checker-qual from 3.34.0 to 3.35.0 (#720)\n** Bump asciidoctorj from 2.5.8 to 2.5.10 (#719)\n"
  },
  {
    "path": "docs/appendix/2023.5.adoc",
    "content": "== 2023.5\n\n=== 2023.5.0\n\nWait what, another minor?\nYes, we added new methods to some builders for #753 and a new method in #756 that takes in the direction of a relationship.\nWhile these are not interfaces for you to implemented and the methods are defaulted, semver requires a minor bump nevertheless.\n\nThanks to @israelstmz and ss with almost every release this year, to @ikwattro, for your input!\n\n==== 🚀 Features\n\n* Provide non-builder method for creating relationships. (#756)\n* Allow `REMOVE` being used after `MERGE`. (#753)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump guava from 32.0.1-jre to 32.1.1-jre (#755)\n** Bump neo4j-java-driver from 5.9.0 to 5.10.0 (#754)\n** Bump checkstyle from 10.12.0 to 10.12.1 (#752)\n** Bump spring-boot-starter-parent from 3.1.0 to 3.1.1 (#751)\n"
  },
  {
    "path": "docs/appendix/2023.6.adoc",
    "content": "== 2023.6\n\n=== 2023.6.1\n\n==== 🚀 Features\n\n* Add `isEmpty()`. (#784)\n\n==== 🐛 Bug Fixes\n\n* Use unmodifiable maps instead of copyOf to allow `null` parameters. (#789)\n\n==== 🔄️ Refactorings\n\n* Add tests demonstrating prevention of function calls.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#788)\n** Bump org.neo4j.driver:neo4j-java-driver (#787)\n** Bump org.checkerframework:checker-qual (#786)\n** Bump org.springframework.boot:spring-boot-starter-parent (#783)\n** Bump com.puppycrawl.tools:checkstyle (#782)\n** Bump mockito.version from 5.4.0 to 5.5.0 (#781)\n** Bump org.graalvm.buildtools:native-maven-plugin (#780)\n** Bump testcontainers.version from 1.18.3 to 1.19.0 (#779)\n** Bump org.apache.maven.plugins:maven-enforcer-plugin (#778)\n** Bump org.springframework.data:spring-data-neo4j (#775)\n** Bump org.neo4j:neo4j-cypher-javacc-parser (#774)\n** Bump io.projectreactor:reactor-bom (#773)\n** Bump com.tngtech.archunit:archunit from 1.0.1 to 1.1.0 (#772)\n** Bump org.asciidoctor:asciidoctorj-diagram (#771)\n** Bump org.graalvm.buildtools:native-maven-plugin (#770)\n\nThanks to @zakjan for a great bug-report again and ofc @ikwattro for your ongoing support and feedback.\n\n=== 2023.6.0\n\n==== 🚀 Features\n\n* Add callbacks for function and procedure invocations. (#764, #758, also backported as 2022.9.0, thanks to @ClemDoum for your input here)\n\n==== 🔄️ Refactorings\n\n* Make TreeNode pretty printing prettier.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump com.google.guava:guava (#769)\n** Bump org.checkerframework:checker-qual (#768)\n** Bump com.puppycrawl.tools:checkstyle (#767)\n** Bump org.asciidoctor:asciidoctorj-diagram (#766)\n** Bump org.neo4j.driver:neo4j-java-driver (#765)\n** Bump org.neo4j:neo4j-cypher-javacc-parser from 5.9.0 to 5.10.0 (#761)\n** Bump checker-qual from 3.35.0 to 3.36.0 (#757)\n** Bump spring-data-neo4j from 7.1.1 to 7.1.2 (#759)\n** Bump reactor-bom from 2022.0.8 to 2022.0.9 (#760)\n** Bump org.junit:junit-bom from 5.9.3 to 5.10.0 (#762)\n** Bump org.springframework.boot:spring-boot-starter-parent (#763)\n"
  },
  {
    "path": "docs/appendix/2023.7.adoc",
    "content": "== 2023.7\n\n=== 2023.7.1\n\nThanks to @jrsperry for a great bug-report and the fix for `includesAll` and `includesAny`.\n\n==== 🐛 Bug Fixes\n\n* Apply the correct includesAll and includesAny semantics (#819)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump mockito.version from 5.5.0 to 5.6.0 (#812)\n** Bump org.springframework.data:spring-data-neo4j (#817)\n** Bump com.google.guava:guava (#816)\n** Bump org.checkerframework:checker-qual (#809)\n** Bump net.bytebuddy:byte-buddy-parent from 1.14.8 to 1.14.9 (#818)\n** Bump io.projectreactor:reactor-bom (#815)\n** Bump com.fasterxml.jackson:jackson-bom (#814)\n** Bump org.neo4j.driver:neo4j-java-driver (#811)\n** Bump testcontainers.version from 1.19.0 to 1.19.1 (#810)\n** Bump com.puppycrawl.tools:checkstyle (#807)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#808)\n** Bump org.ow2.asm:asm from 9.5 to 9.6 (#806)\n** Bump com.mycila:license-maven-plugin from 4.2.rc2 to 4.3 (#805)\n** Bump org.springframework.boot:spring-boot-starter-parent (#804)\n** Bump org.apache.maven.plugins:maven-shade-plugin (#803)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#802)\n** Bump org.graalvm.buildtools:native-maven-plugin (#800)\n** Bump io.projectreactor:reactor-bom (#799)\n** Bump org.neo4j:neo4j-cypher-javacc-parser (#798)\n** Bump org.springframework.data:spring-data-neo4j (#797)\n** Bump org.sonarsource.scanner.maven:sonar-maven-plugin (#796)\n** Bump org.asciidoctor:asciidoctorj-diagram (#795)\n** Bump org.apache.maven.plugins:maven-javadoc-plugin (#794)\n** Bump com.opencsv:opencsv from 5.7.1 to 5.8 (#793)\n** Bump org.apache.maven.plugins:maven-enforcer-plugin (#792)\n** Bump org.graalvm.buildtools:native-maven-plugin (#791)\n\n==== 🛠 Build\n\n* Upgrade Maven wrapper to ASF wrapper 3.2.0 and Maven 3.9.4\n* Build and release with Java 21 targeting Java 17. (#801)\n\n=== 2023.7.0\n\n==== 🚀 Features\n\n* Add basic schema enforcement when rendering statements.\n* Add basic support for parsing negated types.\n* Add basic support for parenthesized path patterns.\n"
  },
  {
    "path": "docs/appendix/2023.8.adoc",
    "content": "== 2023.8\n\n=== 2023.8.1\n\n==== 🐛 Bug Fixes\n\n* Including aliasing in scoping strategy, too. (#839)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.moditect:moditect-maven-plugin (#843)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#845)\n** Bump com.tngtech.archunit:archunit from 1.1.0 to 1.2.0 (#846)\n** Bump org.checkerframework:checker-qual (#844)\n** Bump mockito.version from 5.6.0 to 5.7.0 (#842)\n** Bump org.junit:junit-bom from 5.10.0 to 5.10.1 (#841)\n\n=== 2023.8.0\n\nThis minor release is drop-in compatible with 2023.7, but it adds support for using `COLLECT {}` sub-queries, which required enhancing some interfaces (that only we should implement, but still, it's a minor upgrade then).\n\nThe price for finding the most bugs in the scoping strategy applied for sub-queries in this release goes to @Andy2003, thank you!\n\n==== 🚀 Features\n\n* Add support for `COLLECT` subqueries. (#831)\n* Make fieldname generator configurable. (#830)\n\n==== 🐛 Bug Fixes\n\n* Make sure local scope is cleared after leaving subquery expressions. (#837)\n* Recognize entities defined in sub-queries correctly. (#827)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#836)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#835)\n** Bump org.apache.maven.plugins:maven-checkstyle-plugin (#834)\n** Bump org.neo4j.driver:neo4j-java-driver (#833)\n** Bump org.neo4j:neo4j-cypher-javacc-parser from 5.12.0 to 5.13.0 (#821)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#823)\n** Bump org.graalvm.buildtools:native-maven-plugin (#824)\n** Bump org.jacoco:jacoco-maven-plugin from 0.8.10 to 0.8.11 (#822)\n** Bump org.springframework.boot:spring-boot-starter-parent (#820)\n\n==== 🛠 Build\n\n* Remove explicit management of bytebuddy. (#828)\n"
  },
  {
    "path": "docs/appendix/2023.9.adoc",
    "content": "== 2023.9\n\n=== 2023.9.8\n\n==== 🐛 Bug Fixes\n\n* Don’t introduce new names in pattern expressions. (#1017)\n\n=== 2023.9.7\n\nNot everything goes as planned ;) Another 2023.9 release, enjoy.\n\n==== 🐛 Bug Fixes\n\n* Use proper generics when generating extensible models. (#974)\n* Treat the asterisk correctly in an importing with. (#973)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.neo4j.driver:neo4j-java-driver (#978)\n** Bump org.apache.maven.plugins:maven-shade-plugin (#977)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#976)\n** Bump com.puppycrawl.tools:checkstyle (#975)\n** Bump neo4j.version from 5.18.1 to 5.19.0 (#965)\n** Bump com.tngtech.archunit:archunit from 1.2.1 to 1.3.0 (#966)\n** Bump org.springframework.data:spring-data-neo4j (#967)\n** Bump io.projectreactor:reactor-bom (#968)\n** Bump org.springframework.boot:spring-boot-starter-parent (#971)\n** Bump org.apache.maven.plugins:maven-jar-plugin (#972)\n\n==== 🛠 Build\n\n* Fix doc generation.\n\n=== 2023.9.6\n\n**Heads up** this is the last _planned_ release in the 2023.x series.\nThe next release will be 2024.0.0, in which all deprecations apart from `internalId` on nodes and relationships will be removed.\nWith that change, the Cypher-DSL will have one single entry point for all operations: `org.neo4j.cypherdsl.core.Cypher`.\n\nNothing will change in terms of JDK compatibility.\nCypher-DSL 2024 will still require JDK 17, and will run just fine on JDK 21 and higher.\n\n==== 🚀 Features\n\n* Allow calling of raw Cypher strings in sub queries. (#961)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.jacoco:jacoco-maven-plugin from 0.8.11 to 0.8.12 (#960)\n** Bump org.neo4j.driver:neo4j-java-driver (#959)\n** Bump org.apache.maven.plugins:maven-source-plugin (#958)\n** Bump com.puppycrawl.tools:checkstyle (#957)\n** Bump org.moditect:moditect-maven-plugin (#956)\n** Bump neo4j.version from 5.18.0 to 5.18.1 (#955)\n** Bump org.ow2.asm:asm from 9.6 to 9.7 (#954)\n** Bump org.springframework.boot:spring-boot-starter-parent (#953)\n\n=== 2023.9.5\n\n==== 🚀 Features\n\n* Add a bom project\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.springframework.data:spring-data-neo4j\n** Bump neo4j.version from 5.17.0 to 5.18.0 (#944)\n** Bump com.google.guava:guava (#952)\n** Bump io.projectreactor:reactor-bom (#951)\n** Bump org.asciidoctor:asciidoctorj from 2.5.11 to 2.5.12 (#950)\n** Bump com.fasterxml.jackson:jackson-bom (#949)\n** Bump org.sonarsource.scanner.maven:sonar-maven-plugin (#947)\n** Bump org.moditect:moditect-maven-plugin (#946)\n** Bump com.puppycrawl.tools:checkstyle (#945)\n** Bump testcontainers.version from 1.19.6 to 1.19.7 (#942)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#941)\n** Bump com.fasterxml.jackson:jackson-bom (#940)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#938)\n** Bump org.neo4j.driver:neo4j-java-driver (#937)\n** Bump com.puppycrawl.tools:checkstyle (#936)\n** Bump mockito.version from 5.10.0 to 5.11.0 (#935)\n\n=== 2023.9.4\n\nChange parser license to The Apache Software License, Version 2.0 (same as the Neo4j JavaCC based parser, which we use under the hoods).\n\nThanks a lot @hindog, @fbiville and @Andy2003 for agreeing to relicense your contributions, too.\n\n==== 📖 Documentation\n\n* Use `compile` scope in Gradle dependencies.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump neo4j.version from 5.16.0 to 5.17.0 (#933)\n** Bump testcontainers.version from 1.19.5 to 1.19.6 (#934)\n** Bump org.apache.maven.plugins:maven-shade-plugin (#932)\n** Bump org.springframework.boot:spring-boot-starter-parent (#931)\n** Bump org.graalvm.buildtools:native-maven-plugin (#930)\n** Bump org.codehaus.mojo:exec-maven-plugin (#929)\n** Bump org.asciidoctor:asciidoctor-maven-plugin (#927)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#928)\n** Bump org.springframework.data:spring-data-neo4j (#926)\n** Bump io.projectreactor:reactor-bom (#925)\n** Bump org.asciidoctor:asciidoctorj-diagram (#924)\n** Bump org.graalvm.buildtools:native-maven-plugin (#919)\n** Bump org.assertj:assertj-core from 3.25.2 to 3.25.3 (#918)\n** Bump org.asciidoctor:asciidoctorj-diagram (#916)\n** Bump org.junit:junit-bom from 5.10.1 to 5.10.2 (#915)\n** Bump testcontainers.version from 1.19.4 to 1.19.5 (#923)\n** Bump org.asciidoctor:asciidoctor-maven-plugin (#922)\n** Bump org.neo4j.driver:neo4j-java-driver (#920)\n** Bump joda-time:joda-time from 2.12.6 to 2.12.7 (#917)\n\n=== 2023.9.3\n\n==== 🚀 Features\n\n* Add a parser option to unify the direction of relationships. (#906)\n\n==== 🐛 Bug Fixes\n\n* Driving symbolic names for list predicate function must not be scoped. (#905)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump neo4j.version from 5.15.0 to 5.16.0 (#910)\n** Bump org.assertj:assertj-core from 3.25.1 to 3.25.2 (#914)\n** Bump com.querydsl:querydsl-core from 5.0.0 to 5.1.0 (#913)\n** Bump mockito.version from 5.9.0 to 5.10.0 (#912)\n** Bump com.puppycrawl.tools:checkstyle (#911)\n** Bump testcontainers.version from 1.19.3 to 1.19.4 (#909)\n** Bump org.springframework.boot:spring-boot-starter-parent (#904)\n\n=== 2023.9.2\n\n*Please read the updated stance wrt calver/semver in the README. This release is current and the first one in 2024, including some new, additive and non-breaking features contributed by @Andy2003*\n\n==== 🚀 Features\n\n* Add possibility to define inheritance for the static model. (#894)\n\n==== 🔄️ Refactorings\n\n* Allow unit-subqueries. (#895)\n\n==== 📖 Documentation\n\n* Clarify calver and semver wording.\n\n==== 🧰 Tasks\n\n* Extend license header to 2024.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.asciidoctor:asciidoctor-maven-plugin (#902)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#901)\n** Bump mockito.version from 5.8.0 to 5.9.0 (#900)\n** Bump org.codehaus.mojo:flatten-maven-plugin (#899)\n** Bump org.springframework.data:spring-data-neo4j (#898)\n** Bump io.projectreactor:reactor-bom (#897)\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#896)\n** Bump org.assertj:assertj-core from 3.25.0 to 3.25.1 (#893)\n** Bump org.neo4j.driver:neo4j-java-driver (#892)\n** Bump joda-time:joda-time from 2.12.5 to 2.12.6 (#891)\n** Bump org.asciidoctor:asciidoctorj-diagram (#890)\n** Bump com.fasterxml.jackson:jackson-bom (#887)\n** Bump org.assertj:assertj-core from 3.24.2 to 3.25.0 (#889)\n** Bump com.puppycrawl.tools:checkstyle (#888)\n** Bump org.asciidoctor:asciidoctorj from 2.5.10 to 2.5.11 (#886)\n** Bump com.google.guava:guava (#885)\n** Bump org.springframework.boot:spring-boot-starter-parent (#884)\n\n=== 2023.9.1\n\n==== 🐛 Bug Fixes\n\n* for #840 add missing casts in constructor super calls for relations with generic start or / and end node (#866)\n\n==== 🔄️ Refactorings\n\n* Officially allow label value to be accessed.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump neo4j.version from 5.14.0 to 5.15.0 (#880)\n** Bump org.checkerframework:checker-qual (#883)\n** Bump io.projectreactor:reactor-bom (#882)\n** Bump org.springframework.data:spring-data-neo4j (#881)\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#879)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#878)\n** Bump com.puppycrawl.tools:checkstyle (#876)\n** Bump net.java.dev.jna:jna from 5.13.0 to 5.14.0 (#877)\n** Bump org.checkerframework:checker-qual (#875)\n** Bump org.apache.maven.plugins:maven-javadoc-plugin (#874)\n** Bump org.neo4j.driver:neo4j-java-driver (#873)\n** Bump com.tngtech.archunit:archunit from 1.2.0 to 1.2.1 (#872)\n** Bump mockito.version from 5.7.0 to 5.8.0 (#871)\n** Bump neo4j.version from 5.13.0 to 5.14.0 (#868)\n** Bump testcontainers.version from 1.19.2 to 1.19.3 (#867)\n\n=== 2023.9.0\n\n2023.9 contains several new features: It brings support for parsing and rendering https://neo4j.com/docs/cypher-manual/current/patterns/concepts/#quantified-path-patterns[Quantified Path Patterns (QPP)], shifts to a single, easy to find main entry point to the DSL via just `Cypher` and makes the static code generator a bit more powerful.\n\nWhile QPP are a powerful feature (have a look at https://medium.com/neo4j/getting-from-denmark-hill-to-gatwick-airport-with-quantified-path-patterns-bed38da27ca1[\"Getting From Denmark Hill to Gatwick Airport With Quantified Path Patterns\"]) to see what you can do with them, I find them hard to read, with all the parentheses and I did not expect them to really fit in well with our builder. However, it turned out that the elements we need to provide in our own AST to render what we parsed do work well: If you decide to build QPP with Cypher-DSL, you can now quantify relationship patterns as a whole or only the relationship, making up already for many uses cases.\n\nThe single entry point to our API makes the whole system a lot more discoverable.\n@lukaseder did create a ticket for that in the beginning of 2023 and if someone knows the importance of that, he is that someone as the creator of jOOQ.\nThank you, Lukas and of course earlier this week, @Andy2003 for actually doing the work of adding all those methods to `Cypher`.\n\nIf you don't care about deprecation warnings, 2023.9.0 will be a drop-in replacement.\nThe existing entry points won't go away until the next major release, in which they will be made package private.\nUntil then, they are deprecated.\n\nIt my sound like a broken record by now, but again: Thank you, @zakjan and @ikwattro for your input on QPP, now we are waiting for your bug-reports.\n\n==== 🚀 Features\n\n* Provide a single DSL API entry point. (#862)\n* Allow parsing of `collect` expression. (#861)\n* Add support for quantified path patterns. (#860)\n* Add support for predicates inside pattern elements. (#859)\n* Add ability to add additional factory methods for relationship models to a node in the static model (#840)\n\n==== 📖 Documentation\n\n* Add example how to access properties of a list element.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump spring-boot-starter-parent from 3.1.5 to 3.2.0\n** Bump auto-common to 1.2.2\n** Bump errorprone from 2.12.1 to 2.23.0\n** Bump sortpom from 2.15.0 to 3.3.0\n** Bump com.opencsv:opencsv from 5.8 to 5.9\n** Bump testcontainers.version from 1.19.2 to 1.19.3\n** Bump testcontainers.version from 1.19.1 to 1.19.2 (#857)\n** Bump org.codehaus.mojo:exec-maven-plugin (#856)\n** Bump io.projectreactor:reactor-bom (#855)\n** Bump com.puppycrawl.tools:checkstyle (#854)\n** Bump com.fasterxml.jackson:jackson-bom (#853)\n** Bump org.jetbrains:annotations from 24.0.1 to 24.1.0 (#852)\n** Bump org.springframework.data:spring-data-neo4j (#851)\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#850)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#849)\n** Bump org.apache.maven.plugins:maven-javadoc-plugin (#848)\n\n==== 🛠 Build\n\n* Address several warnings appearing in the build. (#847)\n"
  },
  {
    "path": "docs/appendix/2024.0.adoc",
    "content": "== 2024.0\n\n=== 2024.0.3\n\nThis is mostly a release that upgrades dependency, with the noteworthy exception of having now a unified property accessor.\n\nThanks to @fbiville for his contribution to the documentation, @loveleif for his support and making the latest Neo4j Cypher parser and its improvements work on the module path again and to @Andy2003 for his latest suggestion of the unified property accessor.\n\n==== 🚀 Features\n\n* Add a common interface `PropertyAccessor` (#908)\n\n==== 📖 Documentation\n\n* Update latest version supporting JDK 8 in README. (#1041)\n* Fix documentation link in README (#1026)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump com.google.guava:guava (#1049)\n** Bump org.junit:junit-bom from 5.10.3 to 5.11.0 (#1048)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#1047)\n** Bump org.codehaus.mojo:exec-maven-plugin (#1046)\n** Bump org.springframework.data:spring-data-neo4j (#1045)\n** Bump io.projectreactor:reactor-bom (#1044)\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#1043)\n** Bump org.apache.maven.plugins:maven-site-plugin (#1042)\n** Bump org.codehaus.mojo:exec-maven-plugin (#1040)\n** Bump org.checkerframework:checker-qual (#1039)\n** Bump testcontainers.version from 1.20.0 to 1.20.1 (#1038)\n** Bump neo4j.version from 5.20.0 to 5.22.0 (#1036)\n** Bump org.neo4j.driver:neo4j-java-driver (#1037)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1035)\n** Bump testcontainers.version from 1.19.8 to 1.20.0 (#1034)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#1033)\n** Bump org.apache.maven.plugins:maven-javadoc-plugin (#1032)\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#1030)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#1029)\n** Bump org.springframework.data:spring-data-neo4j (#1028)\n** Bump org.assertj:assertj-core from 3.26.0 to 3.26.3 (#1027)\n\n=== 2024.0.2\n\n🎉 The big party release! 🎉\n\nWith this release we move the repository from http://github.com/neo4j-contrib/[github.com/neo4j-contrib] to https://github.com/neo4j-contrib[github.com/neo4j] with Neo4j adding Cypher-DSL to the list of supported modules.\nWhat we have now on our todo list is to incorporate our http://neo4j.github.io/cypher-dsl[documentation] into the official Neo4j docs, but apart from that, little will change immediate. Even our Maven coordinates will stay the same. You can however rely on the fact that Cypher-DSL is not going anywhere anytime soon.\n\nThanks to @stumoore for supporting this!\n\n==== 🐛 Bug Fixes\n\n* Don’t introduce new names in pattern expressions. (#1017)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades\n** Bump io.projectreactor:reactor-bom (#1025)\n** Bump org.checkerframework:checker-qual (#1024)\n** Bump com.fasterxml.jackson:jackson-bom (#1023)\n** Bump org.moditect:moditect-maven-plugin (#1019)\n** Bump org.asciidoctor:asciidoctorj-diagram (#1021)\n** Bump org.junit:junit-bom from 5.10.2 to 5.10.3 (#1020)\n** Bump org.neo4j.driver:neo4j-java-driver (#1018)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1016)\n** Bump org.apache.maven.plugins:maven-jar-plugin (#1015)\n\n==== 🛠 Build\n\n* Change license for examples that depend on the parser to Apache 2.0, too.\n\n=== 2024.0.1\n\nThis is a pure bug-fix release. Thanks to @Andy2003 for spotting yet another scoping issue.\n\n==== 🐛 Bug Fixes\n\n* Include implicit new variables in seed for name generator. (#999)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump io.projectreactor:reactor-bom (#1013)\n** Bump org.springframework.data:spring-data-neo4j (#1012)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#1011)\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#1010)\n\n=== 2024.0.0\n\nWe're finally going 2024 with this release.\nThe biggest new feature in this release is that we now allow chaining statements that end with a `YIELD` clause, which lets you compose complex queries in a nicer way.\n\nWe also removed all deprecated constructs and methods we accumulated until now. If you ignored the warnings until now, you cannot do any longer. The latest SDN release is prepared for this Cypher-DSL release already, as we did the necessary changes over there already (See this https://github.com/spring-projects/spring-data-neo4j/commit/2861e771333d8b9443026669763ddccd5be7659d[commit] for the necessary changes for example).\n\n==== 🚀 Features\n\n* Allow chaining statements to yielding calls. (#964)\n* Allow chainable foreach. (#988)\n\n==== 🐛 Bug Fixes\n\n* Actually make `sortOrderDefaultExpression` test what it is supposed to test.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.apache.maven.plugins:maven-shade-plugin (#1006)\n** Bump org.neo4j.driver:neo4j-java-driver (#1005)\n** Bump org.sonarsource.scanner.maven:sonar-maven-plugin (#1004)\n** Bump com.google.guava:guava (#1003)\n** Bump org.apache.maven.plugins:maven-enforcer-plugin (#1002)\n** Bump org.apache.maven.plugins:maven-javadoc-plugin (#1001)\n** Bump com.github.ekryd.sortpom:sortpom-maven-plugin (#992)\n** Bump org.assertj:assertj-core from 3.25.3 to 3.26.0 (#998)\n** Bump org.springframework.boot:spring-boot-starter-parent (#997)\n** Bump com.puppycrawl.tools:checkstyle (#996)\n** Bump org.codehaus.mojo:exec-maven-plugin (#995)\n** Bump org.asciidoctor:asciidoctorj from 2.5.12 to 2.5.13 (#993)\n** Bump org.springframework.data:spring-data-neo4j (#991)\n** Bump io.projectreactor:reactor-bom (#990)\n** Bump org.graalvm.buildtools:native-maven-plugin (#989)\n** Bump com.mycila:license-maven-plugin from 4.3 to 4.5 (#987)\n** Bump mockito.version from 5.11.0 to 5.12.0 (#986)\n** Bump testcontainers.version from 1.19.7 to 1.19.8 (#985)\n** Bump com.google.guava:guava (#982)\n** Bump org.checkerframework:checker-qual (#984)\n** Bump org.apache.maven.plugins:maven-install-plugin (#983)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#981)\n** Bump com.fasterxml.jackson:jackson-bom (#980)\n** Bump org.apache.maven.plugins:maven-deploy-plugin (#979)\n"
  },
  {
    "path": "docs/appendix/2024.1.adoc",
    "content": "== 2024.1\n\n=== 2024.1.0\n\nThis new minor release adds a third dialect: Neo4j 5.23, catering for Neo4j >= 5.23.\nThe initial release will rewrite sub-query `CALL` statements with importing `WITH` into sub-queries with variable scoped `CALL` clause.\nWhile the former is still available in Neo4j 5.23, it will cause deprecation warnings, hence, if you want to get rid of those, change the dialect accordingly.\nNo need to rewrite any query on your own.\n\n==== 🚀 Features\n\n* Add a Neo4j 5.23 dialect. (#1069)\n\n==== 🐛 Bug Fixes\n\n* Unwrap `PatternList` proper if unique.\n\n==== 📖 Documentation\n\n* Add an example of building a stand-alone `WHERE` clause.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.checkerframework:checker-qual (#1072)\n** Bump actions/download-artifact from 1 to 4.1.7 in /.github/workflows (#1070)\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#1068)\n** Bump mockito.version from 5.12.0 to 5.13.0 (#1067)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#1066)\n** Bump org.neo4j.driver:neo4j-java-driver (#1065)\n** Bump com.puppycrawl.tools:checkstyle (#1064)\n** Bump org.apache.maven.plugins:maven-javadoc-plugin (#1063)\n** Bump neo4j.version from 5.22.0 to 5.23.0 (#1053)\n** Bump org.apache.maven.plugins:maven-install-plugin (#1057)\n** Bump org.asciidoctor:asciidoctorj from 2.5.13 to 3.0.0 (#1056)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1055)\n** Bump org.apache.maven.plugins:maven-deploy-plugin (#1054)\n** Bump com.puppycrawl.tools:checkstyle (#1052)\n** Bump org.apache.maven.plugins:maven-checkstyle-plugin (#1051)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#1050)\n"
  },
  {
    "path": "docs/appendix/2024.2.adoc",
    "content": "== 2024.2\n\n=== 2024.2.0\n\nA new minor release so shortly after the last?\nWe changed the behaviour of the renderer when using generated names.\nBefore and upto including 2024.1.0 we didn't allow aliases to be reused.\nIf in the original query alias `x` would have been legally reused, we would not have reused them with generated names, i.e. we would have usd `v0` and then `v1`.\nI think this is wrong, and we changed this behaviour, hence a new minor is due.\n\nIf you are using generated names, you can opt out of this behaviour like this:\n\n[source,java]\n----\nvar generatedNamesConfig = EnumSet.complementOf(EnumSet.of(Configuration.GeneratedNames.REUSE_ALIASES));\nvar renderer = Renderer.getRenderer(Configuration.newConfig()\n\t.withGeneratedNames(generatedNamesConfig)\n\t.build());\n----\n\nApart from that, this is a drop-in replacement for 2024.1 and 2024.0.\n\nCongratulations to @ali-ince for contributing his first feature.\n\nAnd last but not least, @Andy2003 gave our AST factory and the scoping mechanism a real good test run, and we have been able to fix several bugs again.\nThank you!\n\n==== 🚀 Features\n\n* Apply sorting of maps when parsing to projections, too. (#1085)\n* Add call raw cypher to top level entry point (#1073)\n\n==== 🐛 Bug Fixes\n\n* Don’t introduce new aliases on for each alias used. (#1084)\n* Export return variables from unions into scope proper. (#1075)\n* Correctly compute imports. (#1076)\n\n==== 📖 Documentation\n\n* Add example test for `LabelExpression`.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump neo4j.version from 5.23.0 to 5.24.0 (#1092)\n** Bump com.google.guava:guava (#1095)\n** Bump com.mycila:license-maven-plugin from 4.5 to 4.6 (#1090)\n** Bump mockito.version from 5.13.0 to 5.14.0 (#1094)\n** Bump org.neo4j.driver:neo4j-java-driver (#1093)\n** Bump com.fasterxml.jackson:jackson-bom (#1091)\n** Bump com.puppycrawl.tools:checkstyle (#1089)\n** Bump org.jetbrains:annotations from 24.1.0 to 25.0.0 (#1088)\n** Bump org.junit:junit-bom from 5.11.0 to 5.11.1 (#1087)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1083)\n** Bump net.java.dev.jna:jna from 5.14.0 to 5.15.0 (#1082)\n** Bump joda-time:joda-time from 2.12.7 to 2.13.0 (#1081)\n** Bump io.projectreactor:reactor-bom (#1080)\n** Bump org.springframework.data:spring-data-neo4j (#1079)\n** Bump org.graalvm.buildtools:native-maven-plugin (#1078)\n"
  },
  {
    "path": "docs/appendix/2024.3.adoc",
    "content": "== 2024.3\n\n=== 2024.3.2\n\n==== 🐛 Bug Fixes\n\n* Restore wrongly deleted `module-info.java`\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.springframework.data:spring-data-neo4j (#1150)\n** Bump io.projectreactor:reactor-bom (#1149)\n** Bump com.puppycrawl.tools:checkstyle (#1148)\n\n=== 2024.3.1\n\n==== 🐛 Bug Fixes\n\n* `$` must be escaped in future Cypher versions.\n\n=== 2024.3.0\n\nThanks to @nk-coding for the idea of supporting label expressions as conditions.\n\n==== 🚀 Features\n\n* Add `hasLabels(LabelExpression labels)` for nodes. (#1146)\n\n==== 📖 Documentation\n\n* Fix typo (#1127)\n* Add another example for list comprehensions.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump neo4j.version from 5.25.1 to 5.26.0 (#1142)\n** Bump org.checkerframework:checker-qual (#1144)\n** Bump org.graalvm.buildtools:native-maven-plugin (#1145)\n** Bump org.apache.maven.plugins:maven-javadoc-plugin (#1143)\n** Bump com.puppycrawl.tools:checkstyle (#1140)\n** Bump com.fasterxml.jackson:jackson-bom (#1139)\n** Bump org.neo4j.driver:neo4j-java-driver (#1138)\n** Bump testcontainers.version from 1.20.3 to 1.20.4 (#1137)\n** Bump org.springframework.data:spring-data-neo4j from 7.3.5 to 7.4.0 (#1133)\n** Bump io.projectreactor:reactor-bom (#1136)\n** Bump org.neo4j.driver:neo4j-java-driver (#1135)\n** Bump org.asciidoctor:asciidoctor-maven-plugin (#1134)\n** Bump org.sonarsource.scanner.maven:sonar-maven-plugin (#1132)\n** Bump org.neo4j.driver:neo4j-java-driver (#1131)\n** Bump org.apache.maven.plugins:maven-site-plugin (#1130)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1129)\n** Bump com.puppycrawl.tools:checkstyle (#1128)\n** Bump neo4j.version from 5.24.2 to 5.25.1 (#1117)\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#1121)\n** Bump com.puppycrawl.tools:checkstyle (#1120)\n** Bump org.apache.maven.plugins:maven-checkstyle-plugin (#1119)\n** Bump org.asciidoctor:asciidoctor-maven-plugin (#1122)\n** Bump testcontainers.version from 1.20.2 to 1.20.3 (#1123)\n** Bump com.fasterxml.jackson:jackson-bom (#1124)\n** Bump org.apache.maven.plugins:maven-javadoc-plugin (#1125)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#1126)\n** Bump org.checkerframework:checker-qual (#1118)\n** Bump com.puppycrawl.tools:checkstyle (#1114)\n** Bump org.neo4j.driver:neo4j-java-driver (#1112)\n** Bump org.junit:junit-bom from 5.11.2 to 5.11.3 (#1116)\n** Bump org.codehaus.mojo:exec-maven-plugin (#1115)\n** Bump io.projectreactor:reactor-bom (#1111)\n** Bump org.jetbrains:annotations from 25.0.0 to 26.0.1 (#1110)\n** Bump org.springframework.data:spring-data-neo4j (#1109)\n** Bump neo4j.version from 5.24.1 to 5.24.2 (#1108)\n** Bump mockito.version from 5.14.1 to 5.14.2 (#1107)\n** Bump org.checkerframework:checker-qual (#1105)\n** Bump org.junit:junit-bom from 5.11.1 to 5.11.2 (#1104)\n** Bump org.apache.maven.plugins:maven-javadoc-plugin (#1103)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#1102)\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#1101)\n** Bump mockito.version from 5.14.0 to 5.14.1 (#1100)\n** Bump neo4j.version from 5.24.0 to 5.24.1 (#1099)\n** Bump org.checkerframework:checker-qual (#1098)\n** Bump testcontainers.version from 1.20.1 to 1.20.2 (#1097)\n** Bump org.ow2.asm:asm from 9.7 to 9.7.1 (#1096)\n"
  },
  {
    "path": "docs/appendix/2024.4.adoc",
    "content": "== 2024.4\n\n=== 2024.4.0\n\nThanks to @meistermeier for both the bugfix in scoping of existential subqueries and kicking off the support for the `FINISH` clause, to finish of 2024 in style.\nHappy holidays and all the best for 2025, we are looking forward helping more projects with Cypher-DSL 2025 next year.\n\n==== 🚀 Features\n\n* Add support for creating and parsing the `FINISH` clause.\n\n==== 🐛 Bug Fixes\n\n* Fix scoping issue with existential subquery (#1151)\n\n=== 2024.4.1\n\n==== 🧰 Tasks\n\n* Extend license header to 2025.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump neo4j.version from 5.26.1 to 5.26.2 (#1176)\n** Bump org.checkerframework:checker-qual (#1177)\n** Bump org.neo4j.driver:neo4j-java-driver (#1175)\n** Bump joda-time:joda-time from 2.13.0 to 2.13.1 (#1174)\n** Bump org.graalvm.buildtools:native-maven-plugin (#1173)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1172)\n** Bump com.puppycrawl.tools:checkstyle (#1171)\n** Bump org.jetbrains:annotations from 26.0.1 to 26.0.2 (#1170)\n** Bump org.assertj:assertj-core from 3.27.2 to 3.27.3 (#1168)\n** Bump io.projectreactor:reactor-bom (#1167)\n** Bump org.springframework.data:spring-data-neo4j (#1166)\n** Bump neo4j.version from 5.26.0 to 5.26.1 (#1165)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#1164)\n** Bump com.opencsv:opencsv from 5.9 to 5.10 (#1163)\n** Bump com.puppycrawl.tools:checkstyle (#1159)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1154)\n** Bump net.java.dev.jna:jna from 5.15.0 to 5.16.0 (#1155)\n** Bump org.junit:junit-bom from 5.11.3 to 5.11.4 (#1157)\n** Bump com.google.guava:guava (#1158)\n** Bump org.checkerframework:checker-qual (#1160)\n** Bump mockito.version from 5.14.2 to 5.15.2 (#1161)\n** Bump org.assertj:assertj-core from 3.26.3 to 3.27.2 (#1162)\n\n==== 🛠 Build\n* Add announcement notifier.\n"
  },
  {
    "path": "docs/appendix/2024.5.adoc",
    "content": "== 2024.5\n\n=== 2024.5.2\n\nTake note that this release deprecates direct integrations with the Neo4j Java Driver. They have never been used widely and can be easily added when needed in calling code.\nRemoving them from Cypher-DSL avoid unnessary complexity in dependency management.\n\n==== 🔄️ Refactorings\n\nrefactor: Deprecate all driver integrations from Cypher-DSL side. (#1211)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.checkerframework:checker-qual (#1233)\n** Bump com.puppycrawl.tools:checkstyle (#1232)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1231)\n** Bump com.google.guava:guava (#1230)\n** Bump io.projectreactor:reactor-bom (#1229)\n** Bump org.junit:junit-bom from 5.12.1 to 5.12.2 (#1228)\n** Bump org.jacoco:jacoco-maven-plugin from 0.8.12 to 0.8.13 (#1226)\n** Bump org.asciidoctor:asciidoctorj-diagram (#1223)\n** Bump mockito.version from 5.16.1 to 5.17.0 (#1222)\n** Bump neo4j.version from 5.26.4 to 5.26.5 (#1221)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#1220)\n** Bump org.asciidoctor:asciidoctor-maven-plugin (#1219)\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#1218)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1217)\n** Bump com.google.guava:guava (#1216)\n** Bump com.puppycrawl.tools:checkstyle (#1215)\n** Bump org.sonarsource.scanner.maven:sonar-maven-plugin (#1214)\n** Bump joda-time:joda-time from 2.13.1 to 2.14.0 (#1213)\n** Bump org.ow2.asm:asm from 9.7.1 to 9.8 (#1212)\n** Bump testcontainers.version from 1.20.5 to 1.20.6 (#1207)\n** Bump org.junit:junit-bom from 5.12.0 to 5.12.1 (#1209)\n** Bump io.projectreactor:reactor-bom (#1210)\n** Bump org.graalvm.buildtools:native-maven-plugin (#1208)\n** Bump net.java.dev.jna:jna from 5.16.0 to 5.17.0 (#1206)\n** Bump org.springframework.data:spring-data-neo4j (#1205)\n** Bump com.mycila:license-maven-plugin from 4.6 to 5.0.0 (#1204)\n** Bump com.google.guava:guava (#1203)\n** Bump neo4j.version from 5.26.3 to 5.26.4 (#1202)\n** Bump mockito.version from 5.16.0 to 5.16.1 (#1201)\n\n\n=== 2024.5.1\n\n==== 🐛 Bug Fixes\n\n* Use a `Pattern` typed subtree for a list of patterns in an existential subquery. (#1200)\n\n==== 📖 Documentation\n\n* Add an example for setting multiple labels. (#1199)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.neo4j.driver:neo4j-java-driver (#1198)\n** Bump com.puppycrawl.tools:checkstyle (#1197)\n** Bump org.checkerframework:checker-qual (#1195)\n** Bump mockito.version from 5.15.2 to 5.16.0 (#1194)\n** Bump org.codehaus.mojo:flatten-maven-plugin (#1192)\n** Bump org.apache.maven.plugins:maven-deploy-plugin (#1191)\n** Bump com.fasterxml.jackson:jackson-bom (#1190)\n** Bump neo4j.version from 5.26.2 to 5.26.3 (#1189)\n** Bump org.apache.maven.plugins:maven-install-plugin (#1188)\n** Bump org.jreleaser:jreleaser-maven-plugin (#1187)\n\n\n=== 2024.5.0\n\nThis new minor release does not have any breaking changes.\nA new dialect dubbed 5.26 has been introduced.\nWhen configured, the renderer will prefix all queries with `CYPHER 5`, which is compatible with Neo4j 5.26 as well as the main line 2025.x.\nIt ensures that a future version of Neo4j will treat all queries generated with Cypher-DSL as Cypher 5, even when newer Cypher versions become available.\n\n==== 🚀 Features\n\n* Introduce Dialect 5.26 (#1185)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump testcontainers.version from 1.20.4 to 1.20.5 (#1184)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1183)\n** Bump org.junit:junit-bom from 5.11.4 to 5.12.0 (#1182)\n** Bump com.puppycrawl.tools:checkstyle (#1181)\n** Bump io.projectreactor:reactor-bom (#1180)\n** Bump org.springframework.data:spring-data-neo4j (#1179)\n** Bump com.tngtech.archunit:archunit from 1.3.0 to 1.4.0 (#1178)\n\n==== 🛠 Build\n\n* fix: The default of `structuredMessage` is `false`. (Internal release announcer)\n"
  },
  {
    "path": "docs/appendix/2024.6.adoc",
    "content": "== 2024.6\n\n=== 2024.6.1\n\n==== 🐛 Bug Fixes\n\n* Don't change simple case to generic case.\n\n==== 🔄️ Refactorings\n\n* Add better error messages when attempting to continue subquery without `with`.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.neo4j.driver:neo4j-java-driver (#1242)\n** Bump org.springframework.data:spring-data-neo4j (#1239)\n** Bump com.opencsv:opencsv from 5.10 to 5.11 (#1237)\n** Bump com.tngtech.archunit:archunit from 1.4.0 to 1.4.1 (#1243)\n** Bump org.jreleaser:jreleaser-maven-plugin (#1241)\n** Bump com.fasterxml.jackson:jackson-bom (#1240)\n** Bump testcontainers.version from 1.20.6 to 1.21.0 (#1238)\n** Bump neo4j.version from 5.26.5 to 5.26.6 (#1236)\n\n\n=== 2024.6.0\n\nTake note that this release deprecates direct integrations with the Neo4j Java Driver. They have never been used widely and can be easily added when needed in calling code.\nRemoving them from Cypher-DSL avoid unnessary complexity in dependency management.\n\n==== 🔄️ Refactorings\n\n* refactor: Deprecate all driver integrations from Cypher-DSL side. (#1211)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.checkerframework:checker-qual (#1233)\n** Bump com.puppycrawl.tools:checkstyle (#1232)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1231)\n** Bump com.google.guava:guava (#1230)\n** Bump io.projectreactor:reactor-bom (#1229)\n** Bump org.junit:junit-bom from 5.12.1 to 5.12.2 (#1228)\n** Bump org.jacoco:jacoco-maven-plugin from 0.8.12 to 0.8.13 (#1226)\n** Bump org.asciidoctor:asciidoctorj-diagram (#1223)\n** Bump mockito.version from 5.16.1 to 5.17.0 (#1222)\n** Bump neo4j.version from 5.26.4 to 5.26.5 (#1221)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#1220)\n** Bump org.asciidoctor:asciidoctor-maven-plugin (#1219)\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#1218)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1217)\n** Bump com.google.guava:guava (#1216)\n** Bump com.puppycrawl.tools:checkstyle (#1215)\n** Bump org.sonarsource.scanner.maven:sonar-maven-plugin (#1214)\n** Bump joda-time:joda-time from 2.13.1 to 2.14.0 (#1213)\n** Bump org.ow2.asm:asm from 9.7.1 to 9.8 (#1212)\n** Bump testcontainers.version from 1.20.5 to 1.20.6 (#1207)\n** Bump org.junit:junit-bom from 5.12.0 to 5.12.1 (#1209)\n** Bump io.projectreactor:reactor-bom (#1210)\n** Bump org.graalvm.buildtools:native-maven-plugin (#1208)\n** Bump net.java.dev.jna:jna from 5.16.0 to 5.17.0 (#1206)\n** Bump org.springframework.data:spring-data-neo4j (#1205)\n** Bump com.mycila:license-maven-plugin from 4.6 to 5.0.0 (#1204)\n** Bump com.google.guava:guava (#1203)\n** Bump neo4j.version from 5.26.3 to 5.26.4 (#1202)\n** Bump mockito.version from 5.16.0 to 5.16.1 (#1201)\n"
  },
  {
    "path": "docs/appendix/2024.7.adoc",
    "content": "== 2024.7\n\n=== 2024.7.4\n\n==== 🚀 Features\n\n* Add support for `ORDER BY` after match.\n\n=== 2024.7.3\n\n==== 🐛 Bug Fixes\n\n* Improve rendering of the importing `CALL` clause.\n* Clearing the scoping strategy could lead to a premature resolution of symbolic names.\n* Add back a test-class deleted by accident.\n\n=== 2024.7.2\n\nThis is a dependency upgrade release only.\nThe next release will most likely be the first 2025.x release with some new features, removal of deprecations and some of the meta-annotations that we use.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 (#1290)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1289)\n** Bump org.junit:junit-bom from 5.13.3 to 5.13.4 (#1288)\n** Bump org.neo4j.driver:neo4j-java-driver (#1280)\n** Bump com.fasterxml.jackson:jackson-bom (#1285)\n** Bump org.springframework.data:spring-data-neo4j (#1284)\n** Bump org.graalvm.buildtools:native-maven-plugin (#1283)\n** Bump io.projectreactor:reactor-bom (#1282)\n** Bump org.apache.maven.plugins:maven-enforcer-plugin (#1281)\n** Bump org.moditect:moditect-maven-plugin (#1279)\n** Bump org.neo4j.driver:neo4j-java-driver from 5.28.5 to 5.28.8 (#1277)\n** Bump org.junit:junit-bom from 5.13.1 to 5.13.3 (#1274)\n** Bump org.checkerframework:checker-qual (#1272)\n** Bump neo4j.version from 5.26.8 to 5.26.9 (#1278)\n** Bump org.apache.maven.plugins:maven-enforcer-plugin (#1276)\n** Bump org.jreleaser:jreleaser-maven-plugin (#1275)\n** Bump testcontainers.version from 1.21.2 to 1.21.3 (#1269)\n** Bump com.puppycrawl.tools:checkstyle (#1268)\n\n=== 2024.7.1\n\n==== 📖 Documentation\n\n* Fix copyright date.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump testcontainers.version from 1.21.1 to 1.21.2 (#1263)\n** Bump com.opencsv:opencsv from 5.11.1 to 5.11.2 (#1266)\n** Bump org.asciidoctor:asciidoctorj-diagram (#1265)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1264)\n** Bump com.puppycrawl.tools:checkstyle (#1262)\n** Bump io.projectreactor:reactor-bom (#1261)\n** Bump org.springframework.data:spring-data-neo4j (#1260)\n** Bump com.fasterxml.jackson:jackson-bom (#1259)\n** Bump org.codehaus.mojo:flatten-maven-plugin (#1267)\n** Bump neo4j.version from 5.26.7 to 5.26.8 (#1258)\n** Bump org.checkerframework:checker-qual (#1257)\n** Bump org.junit:junit-bom from 5.13.0 to 5.13.1 (#1256)\n** Bump com.opencsv:opencsv from 5.11 to 5.11.1 (#1254)\n** Bump org.codehaus.mojo:exec-maven-plugin (#1255)\n** Bump neo4j.version from 5.26.6 to 5.26.7 (#1253)\n** Bump org.junit:junit-bom from 5.12.2 to 5.13.0 (#1252)\n** Bump com.puppycrawl.tools:checkstyle (#1251)\n** Bump testcontainers.version from 1.21.0 to 1.21.1 (#1250)\n\n=== 2024.7.0\n\nThis is a feature release that is fully compatible with the previous 2024.6 and earlier series.\n\n==== 🚀 Features\n\n* Add support for `SHORTEST k`, `SHORTEST k GROUPS`, `ALL SHORTEST` and `ANY` path selectors. (#1247)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump mockito.version from 5.17.0 to 5.18.0 (#1249)\n** Bump com.puppycrawl.tools:checkstyle (#1248)\n** Bump org.springframework.data:spring-data-neo4j from 7.4.5 to 7.5.0 (#1245)\n** Bump io.projectreactor:reactor-bom (#1246)\n"
  },
  {
    "path": "docs/appendix/2025.0.adoc",
    "content": "== 2025.0\n\n=== 2025.0.3\n\n==== 🚀 Features\n\n* Add support for `ORDER BY` after match.\n* Make dynamic labels configurable even on latest dialects.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.springframework.boot:spring-boot-starter-parent (#1349)\n** Bump org.apache.maven.plugins:maven-javadoc-plugin (#1348)\n** Bump quarkus.platform.version from 3.26.3 to 3.26.4 (#1347)\n** Bump org.neo4j:neo4j-ogm-quarkus from 3.16.0 to 3.16.1 (#1346)\n** Bump mockito.version from 5.19.0 to 5.20.0 (#1344)\n** Bump org.assertj:assertj-core from 3.27.4 to 3.27.5 (#1343)\n** Bump org.codehaus.mojo:flatten-maven-plugin (#1342)\n\n\n=== 2025.0.2\n\n==== 🚀 Features\n\n* Add support for rendering some label expressions for older Neo4j versions.\n* Deduplicate parameters while collecting.\n* Add support for dynamic label expression in the `REMOVE` clause. (#1325)\n* Add support for dynamic label expression in the `SET` clause. (#1324)\n* Add support for dynamic label expressions. (#1323)\n\n==== 🐛 Bug Fixes\n\n* Extract parameters from Label expressions, too.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump Neo4j-OGM and OGM-Quarkus example to 4.0.20.\n** Bump org.checkerframework:checker-qual (#1338)\n** Bump com.google.testing.compile:compile-testing (#1336)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#1335)\n** Bump quarkus.platform.version from 3.26.2 to 3.26.3 (#1334)\n** Bump org.springframework.data:spring-data-neo4j (#1333)\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#1332)\n** Bump org.apache.maven.plugins:maven-shade-plugin (#1331)\n** Bump com.google.testing.compile:compile-testing from 0.21.0 to 0.22.0 (#1328)\n** Bump quarkus.platform.version from 3.26.1 to 3.26.2 (#1330)\n** Bump neo4j.version from 5.26.11 to 5.26.12 (#1329)\n* Restore `QueryDSLAdapterTests` once again.\n\n\n=== 2025.0.1\n\n==== 🔄️ Refactorings\n\n* Existential subqueries in latest Neo4j do work with multiple matches, too. (#1322)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.checkerframework:checker-qual (#1321)\n** Bump quarkus.platform.version from 3.25.4 to 3.26.1 (#1320)\n** Bump neo4j.version from 5.26.10 to 5.26.11 (#1319)\n** Bump org.sonarsource.scanner.maven:sonar-maven-plugin (#1318)\n** Bump org.jreleaser:jreleaser-maven-plugin (#1317)\n** Bump com.fasterxml.jackson:jackson-bom (#1316)\n** Bump com.puppycrawl.tools:checkstyle from 11.0.0 to 11.0.1 (#1315)\n** Bump quarkus.platform.version from 3.25.3 to 3.25.4 (#1312)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1311)\n\n=== 2025.0.0\n\nIt's about time to create a 2025 major release of Cypher-DSL.\nFirst things first: We removed the deprecated, direct integration of the Neo4j Java driver.\nThat integration used to allow making all Cypher-DSL statements \"executable\", that is: You were able to pass a query executor to them and get results back.\nIt has been used in https://github.com/spring-projects/spring-data-neo4j[Spring Data Neo4j] testing code, but not much anywhere else.\nWe removed it because it started to became costly: The common Neo4j Java driver and it's dependency will change a lot in their 6.x series, and especially the dependencies will drag us down.\nCypher-DSL is a project that is used by Spring Data Neo4j, https://github.com/neo4j/neo4j-jdbc[Neo4j JDBC Driver] and many more. All of them need to keep an eye on dependency management, hence we prefer to be more lightweight here again.\nYou won't notice a difference in most use-cases.\n\nWith this major we welcome and thank @Shinigami92 as first-time contributor to the ecosystem.\nThey took inspiration of the Spring Data Neo4j annotation processor and started off a similar processor for https://github.com/neo4j/neo4j-ogm[Neo4j-OGM], so that you can now enjoy a static metamodel based on Cypher-DSL for Neo4j-OGM as well.\nA usecase might be in a Quarkus application.\n\n==== 🚀 Features\n\n* Enhance old dialects to render `ALL SHORTEST` and `SHORTEST 1` as legacy functions.\n* Add an annotation processor for Neo4j-OGM annotations. (#1287)\n\n==== 🐛 Bug Fixes\n\n* Improve rendering of the importing `CALL` clause.\n* Clearing the scoping strategy could lead to a premature resolution of symbolic names.\n\n==== 🔄️ Refactorings\n\n* Make Neo4j 5 the default dialect, promote the usage of a dialect without Cypher prefix.\n* Remove the remaining bits of driver dependencies.\n* Use Spring-Java-Formatter and corresponding checkstyle config. (#1308)\n* Remove JetBrains annotations. (#1294)\n* Remove deprecated features and unnecessary suppressions. (#1292)\n\n==== 🧹 Housekeeping\n\n* Remove superfluous .editorconfig\n* Dependency upgrades:\n** Bump org.springframework.data:spring-data-neo4j (#1307)\n** Bump quarkus.platform.version from 3.24.5 to 3.25.3 (#1306)\n** Bump io.projectreactor:reactor-bom (#1305)\n** Bump mockito.version from 5.18.0 to 5.19.0 (#1304)\n** Bump org.apache.maven.plugins:maven-javadoc-plugin (#1303)\n** Bump neo4j.version from 5.26.9 to 5.26.10 (#1302)\n** Bump com.puppycrawl.tools:checkstyle from 10.26.1 to 11.0.0 (#1301)\n** Bump org.assertj:assertj-core from 3.27.3 to 3.27.4 (#1299)\n** Bump org.codehaus.mojo:flatten-maven-plugin (#1297)\n"
  },
  {
    "path": "docs/appendix/2025.1.adoc",
    "content": "== 2025.1\n\n=== 2025.1.0\n\n==== 🚀 Features\n\n* Add option `org.neo4j.cypherdsl.codegen.excludes` for excluding types from processing. (#1363, codegen)\n\n==== 🐛 Bug Fixes\n\n* Generate relationship meta model always per package and in the package of the start node. (codegen)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Upgrade to latest OGM and OGM Quarkus including driver 6.\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#1367)\n** Bump org.ow2.asm:asm from 9.8 to 9.9 (#1372)\n** Bump com.puppycrawl.tools:checkstyle from 11.1.0 to 12.0.1 (#1371)\n** Bump org.codehaus.mojo:exec-maven-plugin (#1370)\n** Bump neo4j.version from 5.26.12 to 5.26.13 (#1369)\n** Bump quarkus.platform.version from 3.28.2 to 3.28.3 (#1368)\n** Bump org.jacoco:jacoco-maven-plugin from 0.8.13 to 0.8.14 (#1366)\n** Bump org.junit:junit-bom from 5.13.4 to 6.0.0 (#1365)\n** Bump org.checkerframework:checker-qual (#1357)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#1362)\n** Bump org.apache.maven.plugins:maven-enforcer-plugin (#1361)\n** Bump quarkus.platform.version from 3.26.4 to 3.28.2 (#1356)\n** Bump org.assertj:assertj-core from 3.27.5 to 3.27.6 (#1355)\n** Bump com.puppycrawl.tools:checkstyle from 11.0.1 to 11.1.0 (#1354)\n** Bump org.graalvm.buildtools:native-maven-plugin (#1352)\n"
  },
  {
    "path": "docs/appendix/2025.2.adoc",
    "content": "== 2025.2\n\n=== 2025.2.7\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump com.puppycrawl.tools:checkstyle from 13.4.0 to 13.4.2 (#1508)\n** Bump org.testcontainers:testcontainers-bom (#1502)\n** Bump org.graalvm.buildtools:native-maven-plugin (#1503)\n** Bump neo4j.version from 5.26.24 to 5.26.25 (#1504)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1506)\n** Bump org.sonarsource.scanner.maven:sonar-maven-plugin (#1507)\n** Bump org.checkerframework:checker-qual (#1509)\n** Bump quarkus.platform.version from 3.34.5 to 3.35.1 (#1510)\n** Bump com.fasterxml.jackson:jackson-bom (#1511)\n** Bump org.neo4j.driver:neo4j-java-driver (#1512)\n** Bump slf4j to 2.0.17.\n** Bump com.puppycrawl.tools:checkstyle from 13.3.0 to 13.4.0 (#1489)\n** Bump neo4j.version from 5.26.23 to 5.26.24 (#1491)\n** Bump org.checkerframework:checker-qual (#1495)\n** Bump org.springframework.data:spring-data-neo4j (#1496)\n** Bump quarkus.platform.version from 3.32.4 to 3.34.5 (#1497)\n** Bump org.neo4j.driver:neo4j-java-driver (#1498)\n** Bump com.tngtech.archunit:archunit from 1.4.1 to 1.4.2 (#1499)\n** Bump com.google.guava:guava (#1500)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#1501)\n\n=== 2025.2.6\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.neo4j:neo4j-ogm-quarkus from 4.2.4 to 4.2.5\n** Bump org.neo4j:neo4j-ogm-core from 5.0.3 to 5.0.4 (#1476)\n** Bump neo4j.version from 5.26.22 to 5.26.23 (#1477)\n** Bump org.asciidoctor:asciidoctorj-diagram (#1478)\n** Bump com.fasterxml.jackson:jackson-bom (#1480)\n** Bump org.springframework.data:spring-data-neo4j (#1481)\n** Bump quarkus.platform.version from 3.32.2 to 3.32.4 (#1482)\n** Bump org.testcontainers:testcontainers-bom (#1483)\n** Bump org.neo4j.driver:neo4j-java-driver (#1485)\n** Bump org.graalvm.buildtools:native-maven-plugin (#1486)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1487)\n\n=== 2025.2.5\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.neo4j:neo4j-ogm-quarkus from 4.2.3 to 4.2.4 (#1475)\n** Bump neo4j.version from 5.26.21 to 5.26.22 (#1474)\n** Bump mockito.version from 5.22.0 to 5.23.0 (#1473)\n** Bump org.checkerframework:checker-qual (#1472)\n** Bump org.asciidoctor:asciidoctorj-diagram (#1471)\n** Bump joda-time:joda-time from 2.14.0 to 2.14.1 (#1470)\n** Bump org.graalvm.buildtools:native-maven-plugin (#1469)\n** Bump org.apache.maven.plugins:maven-resources-plugin (#1468)\n** Bump quarkus.platform.version from 3.32.1 to 3.32.2 (#1467)\n** Bump org.apache.maven.plugins:maven-shade-plugin (#1466)\n** Bump org.jreleaser:jreleaser-maven-plugin (#1465)\n** Bump quarkus.platform.version from 3.31.4 to 3.32.1 (#1464)\n** Bump com.puppycrawl.tools:checkstyle from 13.2.0 to 13.3.0 (#1463)\n** Bump mockito.version from 5.21.0 to 5.22.0 (#1462)\n** Bump org.neo4j:neo4j-ogm-core from 5.0.2 to 5.0.3 (#1461)\n** Bump org.apache.maven.plugins:maven-surefire-plugin (#1460)\n** Bump org.apache.maven.plugins:maven-failsafe-plugin (#1459)\n** Bump com.fasterxml.jackson:jackson-bom (#1458)\n** Bump org.neo4j:neo4j-ogm-quarkus from 4.2.2 to 4.2.3 (#1457)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1456)\n** Bump quarkus.platform.version from 3.31.3 to 3.31.4 (#1455)\n** Bump org.neo4j.driver:neo4j-java-driver (#1454)\n\n=== 2025.2.4\n\n==== 🐛 Bug Fixes\n\n* Don’t generate meta model that cannot be initialized. (#1450)\n\n==== 🔄️ Refactorings\n\n* Don’t use date parts for duration literals. (#1449)\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.springframework.data:spring-data-neo4j (#1453)\n** Bump quarkus.platform.version from 3.31.1 to 3.31.3 (#1452)\n** Bump org.junit:junit-bom from 6.0.2 to 6.0.3 (#1451)\n** Bump org.checkerframework:checker-qual (#1448)\n** Bump com.puppycrawl.tools:checkstyle from 13.1.0 to 13.2.0 (#1447)\n** Bump neo4j.version from 5.26.20 to 5.26.21 (#1445)\n** Bump com.puppycrawl.tools:checkstyle from 13.0.0 to 13.1.0 (#1444)\n** Bump quarkus.platform.version from 3.30.8 to 3.31.1 (#1443)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1442)\n** Bump org.assertj:assertj-core from 3.27.6 to 3.27.7 (#1441)\n** Bump quarkus.platform.version from 3.30.6 to 3.30.8 (#1440)\n** Bump neo4j.version from 5.26.19 to 5.26.20 (#1439)\n** Bump org.graalvm.buildtools:native-maven-plugin (#1438)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#1437)\n** Bump org.springframework.data:spring-data-neo4j (#1435)\n** Bump com.fasterxml.jackson:jackson-bom (#1434)\n** Bump org.neo4j:neo4j-ogm-core and quarkus integration to latest.\n\n==== 🛠 Build\n\n* Disable testing of all Neo4j versions for schema names on GitHub.\n\n=== 2025.2.3\n\nHappy new year. This first Cypher-DSL release of 2026 just contains updated dependencies.\n\n==== 🧰 Tasks\n\n* Extend license header to 2026.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump com.puppycrawl.tools:checkstyle from 12.3.0 to 13.0.0 (#1429)\n** Bump org.springframework.data:spring-data-neo4j (#1431)\n** Bump org.junit:junit-bom from 6.0.1 to 6.0.2 (#1430)\n** Bump org.checkerframework:checker-qual (#1428)\n** Bump org.jreleaser:jreleaser-maven-plugin (#1427)\n** Bump quarkus.platform.version from 3.30.4 to 3.30.6 (#1426)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#1425)\n** Bump org.ow2.asm:asm from 9.9 to 9.9.1 (#1424)\n** Bump quarkus.platform.version from 3.30.2 to 3.30.4 (#1423)\n** Bump org.testcontainers:testcontainers-bom (#1422)\n** Bump org.codehaus.mojo:exec-maven-plugin (#1421)\n** Bump com.puppycrawl.tools:checkstyle from 12.2.0 to 12.3.0 (#1420)\n** Bump neo4j.version from 5.26.18 to 5.26.19 (#1419)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1418)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#1417)\n** Bump mockito.version from 5.20.0 to 5.21.0 (#1416)\n** Bump org.apache.maven.plugins:maven-resources-plugin (#1415)\n\n==== 🛠 Build\n\n* Require Java 25 for the build consistently, release with 17. (#1432)\n* Ignore `.git-blame-ignore-revs` during license check.\n* Add shims to start Maven warning free on JDK 25.\n* Update required Maven version and Maven wrapper to 3.9.12.\n\n=== 2025.2.2 🎅🏻\n\nThanks for another year of Cypher-DSL, with good feedback, excellent bug-reports and more.\nMerry Christmas and happy holidays. This release contains only updated dependencies.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.neo4j:neo4j-ogm-core from 5.0.0 to 5.0.1 (#1414)\n** Bump org.checkerframework:checker-qual (#1411)\n** Bump neo4j.version from 5.26.17 to 5.26.18 (#1405)\n** Bump org.testcontainers:testcontainers-bom (#1406)\n** Bump org.asciidoctor:asciidoctorj-diagram (#1407)\n** Bump quarkus.platform.version from 3.29.4 to 3.30.2 (#1409)\n** Bump org.apache.maven.plugins:maven-source-plugin (#1410)\n** Bump org.sonarsource.scanner.maven:sonar-maven-plugin (#1412)\n** Bump com.puppycrawl.tools:checkstyle from 12.1.2 to 12.2.0 (#1413)\n\n=== 2025.2.1\n\nNo breaking changes. The updated Spring Boot bits only do affect our own testing. Cypher-DSL does not use anything, either from Spring, Spring Boot or Quarkus directly, hence you can use this release equally with Spring Boot 3 or 4. The same is true for Spring Data Neo4j and OGM, in case you use the Cypher-DSL annotation processor. None of the annotations Cypher-DSL understands has changed in their major releases.\n\nThanks to @pecollet for finding another—and quite some nasty— bug in the way Cypher-DSL traverses Label expressions.\n\n==== 🚀 Features\n\n==== 🐛 Bug Fixes\n\n* Leave the `Labels` expression in all cases and handlers if a delegation had been made.\n\n==== 🔄️ Refactorings\n\n* Adapt to changes in Spring Boot 4.\n\n==== 🧰 Tasks\n\n* Configure ignored blame revs.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Bump org.neo4j:neo4j-ogm-quarkus from 4.1.0 to 4.2.0\n** Bump org.springframework.data:spring-data-neo4j\n** Bump org.springframework.boot:spring-boot-starter-parent\n** Bump org.sonarsource.scanner.maven:sonar-maven-plugin (#1402)\n** Bump com.puppycrawl.tools:checkstyle from 12.1.1 to 12.1.2 (#1401)\n** Bump quarkus.platform.version from 3.29.2 to 3.29.4 (#1399)\n** Bump neo4j.version from 5.26.16 to 5.26.17 (#1397)\n** Bump org.apache.maven.plugins:maven-jar-plugin (#1396)\n** Bump org.graalvm.buildtools:native-maven-plugin (#1395)\n** Bump com.github.siom79.japicmp:japicmp-maven-plugin (#1394)\n** Bump org.asciidoctor:asciidoctorj from 3.0.0 to 3.0.1 (#1393)\n** Bump org.neo4j.driver:neo4j-java-driver (#1392)\n** Bump org.checkerframework:checker-qual (#1391)\n** Bump quarkus.platform.version from 3.29.0 to 3.29.2 (#1390)\n** Bump neo4j.version from 5.26.15 to 5.26.16 (#1389)\n** Bump com.fasterxml.jackson:jackson-bom (#1388)\n** Bump org.neo4j:neo4j-ogm-quarkus from 4.0.0 to 4.1.0 (#1387)\n** Bump quarkus.platform.version from 3.28.5 to 3.29.0 (#1386)\n** Bump neo4j.version from 5.26.14 to 5.26.15 (#1385)\n** Bump org.junit:junit-bom from 6.0.0 to 6.0.1 (#1384)\n** Bump org.jreleaser:jreleaser-maven-plugin (#1383)\n\n=== 2025.2.0 🎃\n\nNo breaking changes in this release (as most of the time), only a small new feature needed for the https://github.com/neo4j/neo4j-jdbc[Neo4j JDBC Driver] which you definitely check out.\n\n==== 🚀 Features\n\n* Add support for parameter inside literal maps. (#1382)\n\n==== 🔄️ Refactorings\n\n* Prevent anonymous parameters from being used in literals.\n\n==== 🧹 Housekeeping\n\n* Dependency upgrades:\n** Upgrade testcontainers.version to 2.0.1\n** Bump org.graalvm.buildtools:native-maven-plugin (#1377)\n** Bump org.springframework.data:spring-data-neo4j (#1376)\n** Bump org.codehaus.mojo:exec-maven-plugin (#1375)\n** Bump com.puppycrawl.tools:checkstyle from 12.0.1 to 12.1.1 (#1380)\n** Bump quarkus.platform.version from 3.28.3 to 3.28.5 (#1381)\n** Bump neo4j.version from 5.26.13 to 5.26.14 (#1379)\n** Bump org.springframework.boot:spring-boot-starter-parent (#1378)\n"
  },
  {
    "path": "docs/appendix/building.adoc",
    "content": "== Building the Neo4j Cypher-DSL\n\ninclude::{manualIncludeDir}../CONTRIBUTING.adoc[tags=building-manual]\n"
  },
  {
    "path": "docs/appendix/changes.adoc",
    "content": "== Change log\n\n:leveloffset: +1\n\ninclude::2025.2.adoc[]\n\ninclude::2025.1.adoc[]\n\ninclude::2025.0.adoc[]\n\ninclude::2024.7.adoc[]\n\ninclude::2024.6.adoc[]\n\ninclude::2024.5.adoc[]\n\ninclude::2024.4.adoc[]\n\ninclude::2024.3.adoc[]\n\ninclude::2024.2.adoc[]\n\ninclude::2024.1.adoc[]\n\ninclude::2024.0.adoc[]\n\ninclude::2023.9.adoc[]\n\ninclude::2023.8.adoc[]\n\ninclude::2023.7.adoc[]\n\ninclude::2023.6.adoc[]\n\ninclude::2023.5.adoc[]\n\ninclude::2023.4.adoc[]\n\ninclude::2023.3.adoc[]\n\ninclude::2023.2.adoc[]\n\ninclude::2023.1.adoc[]\n\ninclude::2023.0.adoc[]\n\ninclude::2022.11.adoc[]\n\ninclude::2022.10.adoc[]\n\ninclude::2022.9.adoc[]\n\ninclude::2022.8.adoc[]\n\ninclude::2022.7.adoc[]\n\ninclude::2022.6.adoc[]\n\ninclude::2022.5.adoc[]\n\ninclude::2022.4.adoc[]\n\ninclude::2022.3.adoc[]\n\ninclude::2022.2.adoc[]\n\ninclude::2022.1.adoc[]\n\ninclude::2022.0.adoc[]\n\ninclude::2021.4.adoc[]\n\ninclude::2021.3.adoc[]\n\ninclude::2021.2.adoc[]\n\ninclude::2021.1.adoc[]\n\ninclude::2021.0.adoc[]\n\ninclude::2020.1.adoc[]\n\ninclude::2020.0.adoc[]\n\n:leveloffset: -1\n"
  },
  {
    "path": "docs/appendix/index.adoc",
    "content": "[[appendix]]\n= Appendix\n\n:numbered!:\n\ninclude::query-dsl-support.adoc[]\n\ninclude::building.adoc[]\n\ninclude::../../etc/architecture/index.adoc[]\n\ninclude::changes.adoc[]\n"
  },
  {
    "path": "docs/appendix/query-dsl-support.adoc",
    "content": "[[query-dsl-support]]\n== Query-DSL support\n\nThe Neo4j Cypher-DSL has some support for http://www.querydsl.com[Query-DSL]. It can\n\n* turn instances of `com.querydsl.core.types.Predicate` into `org.neo4j.cypherdsl.core.Condition`,\n* turn instances of `com.querydsl.core.types.Expression` into `org.neo4j.cypherdsl.core.Expression`,\n* create `org.neo4j.cypherdsl.core.Node` instances from `com.querydsl.core.types.Path` and also\n* create `org.neo4j.cypherdsl.core.SymbolicName`\n\nWith this, many static meta models based on Query-DSL can be used to create Queries and match on nodes.\nMost operations supported by Query-DSL are translated into Cypher that is understood by Neo4j 4.0+, so that most predicates\nshould work - at least from a syntactic point of view - out of the box.\n\nExpressions are most useful to address properties in return statements and the like.\n\nHere's one example on how to use it:\n\n[[appendix.query-dsl-support.query-dsl-simple]]\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/querydsl/QueryDSLAdapterTests.java[tags=query-dsl-simple]\n----\n<.> This makes use of a \"Q\"-class generated by Query-DSL APT (using the general processor).\n    `alias` and class based paths works, too.\n    Please make sure to name the instance accordingly when you use it as node (see next step)\n<.> Adapt the \"Q\"-class into a node. Please note it must be named accordingly, otherwise your query\n    won't return the expected results\n<.> Create some Query-DSL predicate based on the properties and adapt it as condition\n<.> Return some Query-DSL properties and adapt it as expression\n\nThe `Statement` offers a way to render all constants as parameters, so that they don't bust the query cache:\n\n[[appendix.query-dsl-support.query-dsl-simple-avoid-constants]]\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/querydsl/QueryDSLAdapterTests.java[tags=query-dsl-simple-avoid-constants]\n----\n<.> Set this to true before accessing parameters of the statement or rendering the statement\n<.> Access the statements parameters for generated parameter names\n<.> Compare the statement to the first listening. Constants are gone now\n\nThe Neo4j Cypher-DSL will collect all parameters defined via Query-DSL for you:\n\n[[appendix.query-dsl-support.query-dsl-parameters]]\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/querydsl/QueryDSLAdapterTests.java[tags=query-dsl-parameters]\n----\n<.> Basically the same predicate as above, but with parameters, which will be turned into correct placeholders\n<.> Access the parameter names via the `Statement` object\n\n=== Required dependencies\n\nThe Query-DSL support in the Neo4j Cypher-DSL is optional, and the Query-DSL dependency is only in the `provided` scope.\nTo make use of `Cypher.adapt()`, you must add the following dependency in addition to the Cypher-DSL:\n\n==== Maven\n\n[source,xml]\n----\n<dependency>\n    <groupId>com.querydsl</groupId>\n    <artifactId>querydsl-core</artifactId>\n    <version>4.4.0</version>\n    <scope>provided</scope>\n</dependency>\n----\n\n==== Gradle\n\n[source,groovy]\n----\ndependencies {\n    implementation 'com.querydsl:query-dsl-core:4.4.0'\n}\n----\n\nIn case you want to use an annotation processor, you have to add additional dependencies and depending on your Java environment.\nWe use the following in our tests:\n\n[source,xml]\n----\n<dependencies>\n    <dependency>\n        <groupId>com.querydsl</groupId>\n        <artifactId>querydsl-apt</artifactId>\n        <version>4.4.0</version>\n        <classifier>general</classifier>\n    </dependency>\n    <dependency>\n        <groupId>javax.annotation</groupId>\n        <artifactId>javax.annotation-api</artifactId>\n        <version>1.3.2</version>\n    </dependency>\n</dependencies>\n----\n"
  },
  {
    "path": "docs/cypher-parser/cypher-parser.adoc",
    "content": "== Introduction\n\nThe `cypher-dsl-parser` module ins an optional add-on to the Cypher-DSL that takes your existing Cypher - either whole statements\nor fragments like clauses or expressions - and turn them into Cypher-DSL statements or expressions.\nThose fragments can be used to add custom Cypher to your generated statements without resorting to raw String literals.\nIt allows sanitizing user input, add additional filters for labels and types to rewrite queries and more.\n\nThe parser itself is based on Neo4j's official Cypher-Parser, thus supporting the same constructs as Neo4j itself.\nHowever, while we could theoretically parse all expressions that Neo4j {neo4j-version} supports, we might cannot translate all of them\ninto elements of the Cypher-DSL. In such cases an `UnsupportedOperationException` will be thrown.\n\n== Getting started\n\n=== Add additional dependencies\n\n==== Maven\n\n[source,xml,subs=\"verbatim,attributes\"]\n.Cypher-DSL parser added via Maven\n----\n<dependency>\n    <groupId>{groupId}</groupId>\n    <artifactId>neo4j-cypher-dsl-parser</artifactId>\n    <version>{the-version}</version>\n</dependency>\n----\n\n==== Gradle\n\n[source,groovy,subs=\"verbatim,attributes\"]\n.Gradle variant for additional dependencies\n----\ndependencies {\n    implementation '{groupId}:neo4j-cypher-dsl-parser:{the-version}'\n}\n----\n\n=== Minimum JDK version\n\nThe Cypher-Parser requires JDK 11 to run which is the same version that Neo4j {neo4j-version} requires.\n\n=== Main entry point\n\nThe main entry point to parsing Cypher strings into Cypher-DSL objects is\n\n[[main-entry-pint]]\n.Cypher Parser\n[source, java,indent=0,tabsize=4]\n----\nimport org.neo4j.cypherdsl.parser.CypherParser;\n----\n\nIt provides a list of static methods:\n\n[cols=2*,options=header]\n|===\n|Method\n|What it does\n\n|`parseNode`\n|Parses a pattern like `(n:Node {withOrWithout: 'properties'})` into a `Node`\n\n|`parseRelationship`\n|Parses a pattern like `(m)-[{a: 'b', c: 'd'}]->(n)` into a `RelationshipPattern`.\n The pattern might be a `Relationship` or `RelationshipChain`.\n\n|`parseExpression`\n|Parses an arbitrary expression.\n\n|`parseClause`\n|Parses a full clause like `MATCH (m:Movie)` or `DELETE n` etc. These clauses might be modified via\n callbacks and then passed on into `org.neo4j.cypherdsl.core.Statement.of`. This will take them\n in order and create a whole statement out of it. It is your responsibility to make sure those clauses are\n meaningful in the given order.\n\n|`parseStatement`\n|Parses a whole statement. The result can be rendered or used in a union or subquery call.\n\n|`parse`\n|An alias for `parseStatement`.\n\n|===\n\nThe `README` for the parser module itself contains not only our whole TCK for the parser,\nbut also several examples of calling it. Have a look here: https://github.com/neo4j-contrib/cypher-dsl/blob/main/neo4j-cypher-dsl-parser/README.adoc[neo4j-cypher-dsl-parser/README.adoc].\n\nAll the methods mention above provide an overload taking in an additional `org.neo4j.cypherdsl.parser.Option` instance\nallowing to interact with the parser. Please have a look at the JavaAPI for information about the options class.\nThe following examples show some ways of using it.\nMost of the configurable options represent ways to provide filters for labels or types or are callbacks when certain expressions are created.\n\n[[cypher-parser-examples]]\n== Examples\n\n=== Parsing user input and call in a subquery\n\nThis is helpful when you create an outer query that maybe enriched by a user.\nHere we assume the user does the right thing and don't modify the query any further:\n\n[[example-using-input]]\n.Just using the user supplied input\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-parser/src/test/java/org/neo4j/cypherdsl/examples/parser/CypherDSLParserExamplesTests.java[tag=example-using-input]\n----\n<.> A valid standalone query that is also a valid subquery\n<.> Just parse it into a `Statement` object\n<.> Use the Cypher-DSL as explained throughout the docs\n<.> Use the overload of `call` that takes a `Statement` and a collection of expression that should be imported into the subquery\n<.> Notice how to `WITH` clauses are generated: The first one is the importing one, the second one the aliasing one\n<.> This is the original query\n\n=== Ensure an alias for the return clause\n\nWe are going to work with the same test as in <<example-using-input>>, so this is not repeated.\nHere we  make sure the query supplied by the user returns something with a required alias.\n\n[[example-required-alias]]\n.Using a callback to make sure that a query has an alias\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-parser/src/test/java/org/neo4j/cypherdsl/examples/parser/CypherDSLParserExamplesTests.java[tag=example-required-alias]\n----\n<.> This is a `Function` that receives an expressions and returns a new one. It\n    checks if the provided expressions obeys to some criteria: Here being something that is aliased or not\n<.> We start building new options\n<.> The callback from step one is passed as callback to the event `ON_RETURN_ITEM` and will be called for every item\n<.> The final option instance will be applied to the parser. The statement will render to the same result as <<example-using-input,the first example>>.\n\n=== Preventing certain things\n\nCallbacks can of course be used to prevent things.\nAny exception thrown will halt the parsing.\n<<example-preventing-things>> shows how:\n\n[[example-preventing-things]]\n.Preventing input that deletes properties\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-parser/src/test/java/org/neo4j/cypherdsl/examples/parser/CypherDSLParserExamplesTests.java[tag=example-preventing-things]\n----\n<.> Create a callback that just throws an unchecked exception\n<.> Configure it for the event that should be prevented\n<.> Parsing will not be possible\n\n=== Shape the return clause the way you want\n\nThe parser provides `ReturnDefinition` as value object. It contains information to be passed to the `Clauses` factory to shape\na `RETURN` clause the way you need:\n\n[[example-example-shape-the-return-clause]]\n.Shaping the return clause\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-parser/src/test/java/org/neo4j/cypherdsl/examples/parser/CypherDSLParserExamplesTests.java[tag=example-shape-the-return-clause]\n----\n<.> Create a factory method that takes in a definition and uses its information to build the `RETURN`.\n    Or examples filters the attributes being returned and enforces an alias.\n    It also adds some arbitrary sorting and keeps sort and limit values from the original\n<.> It than is parsed to the options\n<.> The statement has the new `RETURN` clause.\n\n=== Enforcing labels\n\nThe parser can enforce labels to be present or absent with filters. This can be individually achieved when parsing node patterns,\nsetting or removing labels with a `BiFunction` like the following:\n\n[[a-label-enforcing-functions]]\n.Shaping the return clause\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/RewriteTests.java[tag=enforcing-labels-function]\n----\n<.> Decide on the event type what is supposed to happen\n\nPutting this function in action involves the `Options` class again:\n\n[[enforcing-on-parse]]\n.Enforcing a label is always set on the pattern\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/RewriteTests.java[tag=enforcing-on-parse]\n----\n\nThis can safely be used to match only nodes spotting such a label for example.\n\n[[enforcing-on-set]]\n.Enforcing that a new collection of labels always contains a specific\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/RewriteTests.java[tag=enforcing-on-set]\n----\n\nOf course, we can prevent a label to be removed:\n\n[[enforcing-on-remove]]\n.Preventing a specific label to be removed\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/RewriteTests.java[tag=enforcing-on-remove]\n----\n\nChanging relationship types via a filter is possible as well, but as relationships might only have one type, the number of\nusecases is smaller.\n\n\n=== Combining the parser with SDN's `CypherdslConditionExecutor`\n\nSpring Data Neo4j 6 provides `CypherdslConditionExecutor`. This is a fragment that adds the capability to execute\nstatements with added conditions to a `Neo4jRepository`.\n\nGiven the following repository:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/PeopleRepository.java[tag=additional-fragments]\n----\n<.> Allows to just add conditions to our generated queries\n<.> Provides an alternative to using @Query with strings\n\nOne possible use case is presented in this service:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/PeopleService.java[tag=using-parser-with-spring]\n----\n<.> The condition that only people born later than 1980 is hard coded in the service.\n    An arbitrary String is than parsed into a condition and attached via `AND`.\n    Thus, only valid cypher can go in there and with filters and callbacks, preconditions of that Cypher can be asserted.\n\nThe downside to the above solution is that the query fragment passed to the service and eventually the repository must\nknow the root node (which is `n` in case of SDN 6) and the caller code might look like this:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/test/java/org/neo4j/cypherdsl/examples/sdn6/ApplicationIT.java[tag=exchange1]\n----\n\nNotice `n.name` etc.\nWe could change the service method slightly and apply a callback like this:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/PeopleService.java[tag=using-parser-with-spring2]\n----\n<.> Create a function that takes the value of a variable created in the fragment and use it to look up a property on the\n    SDN root node.\n<.> Create an instance of parsing options. It's probably a good idea todo this once and store them away in an instance variable.\n    Options are thread safe.\n<.> Apply them when calling the corresponding parse method\n\nNow it's enough to pass `\"name contains \\\"Ricci\\\" OR name ends with 'Hirsch'\"` into the exchange presented above and things\nwill work out of the box.\nFurther validation and sanitiy checks are of course up to you.\n"
  },
  {
    "path": "docs/cypher-parser/index.adoc",
    "content": "[[cypher-parser]]\n= Parsing existing Cypher\n\ninclude::cypher-parser.adoc[]\n"
  },
  {
    "path": "docs/functions/arbitrary-procedures-and-functions.adoc",
    "content": "== Calling arbitrary procedures and functions\n\nNeo4j has plethora of built-in procedures and functions.\nThe Cypher-DSL does cover a lot of them already, and they can be called in a typesafe way on many `Expression`-instances\ntaking in various expressions such as the results of other calls, literals or parameters.\n\nHowever, there will probably always be a gap between what the Cypher-DSL includes and what the Neo4j database brings.\nMore so, there are fantastic libraries out there like https://neo4j.com/labs/apoc/[APOC].\nAPOC has so many procedures and functions in so many categories that it is rather futile to add shims\nfor all of them consistently.\n\nProbably the most important aspect of all: many Neo4j users bring their knowledge to the database themselves,\nin the form of their stored procedures. Those should be callable as well.\n\nThe Cypher-DSL is flexible enough to call all those procedures and functions.\n\n=== Calling custom procedures\n\nProcedures are called via the Cypher https://neo4j.com/docs/cypher-manual/current/clauses/call/[CALL-Clause].\nThe CALL-Clause can appear as a https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/StandaloneCall.html[StandAlone call]\nand as an https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/InQueryCall.html[InQuery call].\nBoth are supported by the Cypher-DSL.\n\n==== Standalone procedure calls\n\nStandalone calls are particular useful for `VOID` procedures.\nA VOID procedure is a procedure that does not declare any result fields and returns no result records and that has explicitly been declared as `VOID`.\nLet's take the first example https://neo4j.com/docs/cypher-manual/current/clauses/call/#call-call-a-procedure-using-call[from here]\n\n[source,java,indent=0]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/ArbitraryProceduresAndFunctionsTests.java[tag=standalone-call]\n----\n<.> `Cypher.call` returns a buildable statement that can be rendered.\n    `Cypher.call` can be used with separate namespace and procedure name as shown here or\n<.> with a single argument equal to the name of the procedure.\n\nOf course, arguments can be specified as expressions.\nExpressions can be literals as in <<standalone-call-with-args>>, Cypher parameters (via `Cypher.parameter`) that bind your input or nested calls:\n\n[[standalone-call-with-args]]\n[source,java,indent=0]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/ArbitraryProceduresAndFunctionsTests.java[tag=standalone-call-with-args]\n----\n\nLast but not least, the Cypher-DSL can of course `YIELD` the results from a standalone call:\n\n[[standalone-call-yielding]]\n[source,java,indent=0]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/ArbitraryProceduresAndFunctionsTests.java[tag=standalone-call-yielding]\n----\n<.> Yielded items can be specified via string…\n<.> …or with symbolic names created earlier\n\nA standalone call can spot a `WHERE` clause as well:\n\n[[standalone-call-where]]\n[source,java,indent=0]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/ArbitraryProceduresAndFunctionsTests.java[tag=standalone-call-where]\n----\n\n==== In-query procedure calls\n\nIn-query calls are only possible with non-void procedures. An In-query call happens inside the flow of a normal query.\nThe mechanics to construct those calls via the Cypher-DSL are identical to standalone calls:\n\n[[in-query-calls]]\n[source,java,indent=0]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/ArbitraryProceduresAndFunctionsTests.java[tag=in-query-calls]\n----\n\nA `CALL` can be used after a `MATCH`, a `WITH` and also a `WHERE` clause.\n\n=== Use stored-procedure-calls as expressions (Calling custom functions)\n\nAll the mechanics described and shown above - how to define a custom call statement, supply it with arguments etc. - doesn't\ndistinguish between procedures and functions.\nEvery stored procedure can be treated as a function - as long as the stored procedure returns a single value.\nIt doesn't matter if the single value returns a scalar or a list of objects.\nA list of objects is still a single value, in contrast to a stream of objects returned by a non-void procedure.\n\nSo the question is not how to call a stored custom function, but how to turn a call statement into an expression that can be used in any place in a query where an expression is valid.\nThis is where `asFunction` comes in.\n\n[[as-function]]\n[source,java,indent=0]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/ArbitraryProceduresAndFunctionsTests.java[tag=as-function]\n----\n<.> First we define a call as seen earlier and turn it into an expression\n<.> This expression is than used as any other expression\n\nOf course, arguments to those functions can be expressed as well, either as literals or expressions.\n\n[[as-function-with-args]]\n[source,java,indent=0]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/ArbitraryProceduresAndFunctionsTests.java[tag=as-function-with-args]\n----\n<.> Same as before\n<.> A call to APOC's `camelCase` function, taking in the literal of `first name`.\n<.> A call to another APOC function to which a parameter is passed. You find that corresponding placeholder as `$nameParam` in the following assert\n\n=== Summary\n\nThrough `Cypher.call` any procedure or function can be called in case one of your favorite procedures is missing in `org.neo4j.cypherdsl.core.Functions`.\nAll clauses, including `YIELD` and `WHERE` on procedures are supported.\nAll procedures can be turned into functions.\nThe Cypher-DSL however does not check if the procedure that is used as a function is actually eligible to do so.\n\nIf the Cypher-DSL misses an important builtin Neo4j function, please raise a https://github.com/neo4j-contrib/cypher-dsl/issues/new[ticket].\n"
  },
  {
    "path": "docs/functions/index.adoc",
    "content": "[[functions]]\n= Functions\n\nNOTE: There are many more functions implemented in `org.neo4j.cypherdsl.core.Functions`. Not all of them are already documented here.\n\ninclude::lists.adoc[]\n\ninclude::mathematical.adoc[]\n\ninclude::arbitrary-procedures-and-functions.adoc[]\n"
  },
  {
    "path": "docs/functions/lists.adoc",
    "content": "== Lists\n\n[[functions-list-range]]\n=== range()\n\nCreates an invocation of https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-range[`range()`].\n\nGiven the following imports\n\n[source,java,indent=0]\n----\nimport org.neo4j.cypherdsl.core.Cypher;\n----\n\n[source,java,indent=0]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/FunctionsListTests.java[tag=functions-list-range]\n----\n\nGives you `range(0,10)`.\nThe step size can be specified as well:\n\n[source,java,indent=0]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/FunctionsListTests.java[tag=functions-list-range-step]\n----\n\nThis gives you `range(0,10,1)`.\n\nBoth variants of `range` also take a `NumberLiteral` for the start and end index and the step size.\n\n=== Inserting a list operator\n\nThe _list operator_ `[]` selects a specific value of a list or a range of values from a list.\nA range can either be closed or open.\n\nFind examples to select a value at a given index, a sublist based on a closed range and sublist based on open ranges below.\nWhile the examples use <<functions-list-range>>, the list operator doesn't put any restrictions on the expression at the moment.\n\n[source,java,indent=0]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/FunctionsListTests.java[tag=functions-list-operator]\n----\n"
  },
  {
    "path": "docs/functions/mathematical.adoc",
    "content": "== Mathematical functions\n\nThe Cypher-DSL supports all mathematical functions as of Neo4j 4.2. Please find\ntheir description in the Neo4j cypher manual:\n\n* https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/[Numeric]\n* https://neo4j.com/docs/cypher-manual/current/functions/mathematical-logarithmic/[Logarithmic]\n* https://neo4j.com/docs/cypher-manual/current/functions/mathematical-trigonometric/[Trigonometric]\n"
  },
  {
    "path": "docs/getting-started/getting-started.adoc",
    "content": "== Prepare dependencies\n\nPlease use a dependency management system. We recommend either Maven or Gradle.\n\n=== Maven configuration\n\n[source,xml,subs=\"verbatim,attributes\"]\n.Inclusion of the Neo4j Cypher-DSL in a Maven project\n----\n<dependency>\n\t<groupId>{groupId}</groupId>\n\t<artifactId>{artifactId}</artifactId>\n\t<version>{the-version}</version>\n</dependency>\n----\n\n=== Gradle configuration\n\n[source,groovy,subs=\"verbatim,attributes\"]\n.Inclusion of the Neo4j Cypher-DSL in a Gradle project\n----\ndependencies {\n    implementation '{groupId}:{artifactId}:{the-version}'\n}\n----\n\n[[how-to-use-it]]\n== How to use it\n\nYou use the Cypher-DSL as you would write Cypher:\nit allows to write down even complex Cypher queries from top to bottom in a type safe, compile time checked way.\n\nThe examples to follow are using JDK 11.\nWe find the `var` keyword especially appealing in such a DSL as the types returned by the DSL are much less important than\nthe further building methods they offer.\n\nIMPORTANT: The AST parts and intermediate build steps are immutable. That is, the methods create new intermediate steps.\nFor example, you cannot reuse an `ExposesLimit` step, but have to use the returned object from its `skip` method.\n\nAn instance of a `org.neo4j.cypherdsl.core.Statement` is provided at the end of every query building step.\nThis `Statement` needs to be rendered into a string or passed to methods supporting it as input.\n\nPlease get an instance of the default renderer via `org.neo4j.cypherdsl.renderer.Renderer#getDefaultRenderer()`.\nThe renderer provides a single method `render` for rendering the AST into a string representation.\n\nFurthermore, the `Statement` will collect parameter names and if provided, parameter values.\nParameter names and values are available after the statement has been built and can for example be used directly with the Neo4j-Java-Driver.\n\n[[how-to-use-it.examples]]\n=== Examples\n\nThe following examples are 1:1 copies of the queries you will find in the Neo4j browser after running `:play movies`.\n\nThey use the following imports:\n\n.Imports needed for the examples to compile\n[source, java]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=cypher-dsl-imports]\n----\n\nTo match and return all the movie, build your statement like this:\n\n.Simple match\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=cypher-dsl-e1]\n----\n<.> Declare a variable storing your node labeled `Movie` and named `m`, so that you can\n<.> reuse it in both the match and the return part.\n<.> The `build` method becomes only available when a compilable Cypher statement can be rendered.\n\n==== Find\n\nMatch all nodes with a given set of properties:\n\n.Find the actor named \"Tom Hanks\"...\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=cypher-dsl-e2]\n----\n\nLimit the number of returned things and return only one attribute\n\n.Find 10 people...\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=cypher-dsl-e4]\n----\n\nCreate complex conditions\n\n.Find movies released in the 1990s...\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=cypher-dsl-e5]\n----\n\n==== Query\n\nBuild relationships\n\n.List all Tom Hanks movies...\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=cypher-dsl-e6]\n----\n\n.Who directed \"Cloud Atlas\"?\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=cypher-dsl-e7]\n----\n\n.Tom Hanks' co-actors...\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=cypher-dsl-e8]\n----\n\n.How people are related to \"Cloud Atlas\"...\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=cypher-dsl-e9]\n----\n\n==== Solve\n\n.Movies and actors up to 4 \"hops\" away from Kevin Bacon\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=cypher-dsl-bacon]\n----\n\n==== Recommend\n\n.Extend Tom Hanks co-actors, to find co-co-actors who haven't worked with Tom Hanks...\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=cypher-dsl-r]\n----\n\n=== More features\n\n[[retrieving-parameters]]\n==== Retrieving parameters being defined\n\nA placeholder for a parameter can be defined via `Cypher.parameter(\"param\")`.\nThis placeholder will be rendered as `$param` and must be filled with the appropriate means of the environment you're working with.\n\nIn addition, an arbitrary value can be bound to the name via `Cypher.parameter(\"param\", \"a value\")` or `Cypher.parameter(\"param\").withValue(\"a value\")`.\n`NULL` is a valid value.\nThe Cypher-DSL will not use those values, but collect them for you.\n\nThe following example shows how to access them and how to use it:\n\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=collecting-params]\n----\n<.> The names contain all placeholders, also those without a value\n<.> The parameter map contains only parameters with defined values\n\nIf you define a parameter with conflicting values, a `ConflictingParametersException` will be thrown the moment you try to retrieve the collected parameters.\n\n==== Using the default renderer\n\nA statement can render itself as well:\n\n[source, java]\n----\nvar statement = Cypher.returning(literalTrue().as(\"t\")).build();\nvar cypher = this.statement.getCypher();\nassertThat(cypher).isEqualTo(\"RETURN true AS t\");\n----\n\nThis, together with <<retrieving-parameters, the above>>, makes the statement a complete accessor for a Cypher-statement and its parameters.\n\n[[retrieving-identifiable-expressions]]\n==== Retrieving identifiable expressions\n\nThe `Statement` as well as the intermediate build steps after defining a `WITH` or `RETURN` clause allow to retrieve identifiable expressions\nvia `getIdentifiableExpressions()`. All expressions identifiable via a name such as named nodes and relationships, symbolic names or aliased\nexpressions are included. In addition, properties are also available.\n\nThose information can be used when dynamically building a query to verify the presence of required expressions\nor use them for further refinement.\n\nStatements parsed via the optional <<cypher-parser,parser module>> are also able to return their identifiable expressions.\nThe use case here might be evaluating a statement defined by a user being parsed and then checked if everything required is returned.\n\n==== Generating formatted Cypher\n\nThe Cypher-DSL can also format the generated Cypher to some extend.\nThe `Renderer` offers the overload `Renderer getRenderer(Configuration configuration)`, taking in an instance of `org.neo4j.cypherdsl.core.renderer.Configuration`.\n\nInstances of `Configuration` are thread-safe and reusable.\nThe class offers a couple of static convenience methods for retrieving some variants.\n\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=pretty-printing-examle]\n----\n<.> Get a \"pretty printing\" instance of the renderer configuration and retrieve a renderer based on it\n<.> Enjoy formatted Cypher.\n\n==== Escaping names\n\nThe default renderer in its default configuration will escape all names (labels and relationship types) by default.\nSo `Movie` becomes `++`Movie`++` and `ACTED_IN` becomes `++`ACTED_IN`++`.\nIf you don't want this, you can either create a dedicated configuration for a renderer with that setting turned off or use\nthe pretty printing renderer:\n\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=escaping]\n----\n\n==== Inserting raw Cypher\n\n`Cypher.raw` allows for creating arbitrary expressions from raw String literals.\nUsers discretion is advised:\n\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java[tag=raw-cypher]\n----\n<.> The Cypher-DSL doesn't support a dynamic lookup of properties on expression at the moment.\n    We use a raw Cypher string with the placeholder `$E` which resolves to the symbolic name also passed to the `raw` function.\n\n[[dialect-support]]\n== Dialect support\n\nThere is limited dialect support. The default dialect `org.neo4j.cypherdsl.core.renderer.Dialect.DEFAULT` is Neo4j 4.4 and earlier whereas `org.neo4j.cypherdsl.core.renderer.Dialect.NEO4J_5` is designated to work with Neo4j 5.\n\nThe Neo4j 5 dialect will render some things differently:\n\n* `org.neo4j.cypherdsl.core.Functions.distance` will be rendered as `point.distance` instead of just `distance`\n* `elementId` will be rendered \"as is\"\n* `EXISTS(n.property)` will be rendered as `n.property IS NOT NULL`\n\nAdditional features might be added.\n\nNOTE: It is especially noteworthy that `elementId(node)` will be rendered as `toString(id(node))` with the default dialect. This is helpful for building queries that must work a) without deprecation warnings and b) on both Neo4j 4 and 5. Of course this is not portable and the returned values must only be used for comparison inside one statement. But Neo4j advices strongly against making the internal entity ids available outside a transaction (See https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-elementid[elementID]: \"Outside of the scope of a single transaction, no guarantees are given about the mapping between ID values and elements.\")\n\nHere is one example how to use a dialect:\n\n[source, java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/DialectIT.java[tag=dialect-example]\n----\n\n[[catalog-support]]\n== Catalog support\n\nThe Cypher-DSL offers a catalog view on statements. After a statement has been build, a catalog can be retrieved like this:\n\n.Using the statement catalog from a constructed statement\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/StatementCatalogBuildingVisitorTests.java[tag=catalog-example]\n----\n\nIn the above example the catalog contains all labels and types used (`Movie`, `Person`, `ACTED_IN`) and all conditions\nthat involves a property of an entity combining the labels or types into a node or relationship. In addition, the catalog\ncontains the identifiable elements.\n\nThis becomes especially powerful when combining with the optional <<cypher-parser,parser module>>:\n\n.Using the statement catalog from a parsed statement\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-parser/src/test/java/org/neo4j/cypherdsl/examples/parser/StatementCatalogBuildingVisitorViaParserTests.java[tag=catalog-example]\n----\n"
  },
  {
    "path": "docs/getting-started/index.adoc",
    "content": "[[getting-started]]\n= Getting started\n\ninclude::getting-started.adoc[]\n"
  },
  {
    "path": "docs/index.adoc",
    "content": "= The Neo4j Cypher-DSL\nGerrit Meier <gerrit.meier@neo4j.com>; Michael Simons <michael.simons@neo4j.com>\n:toc:\n:doctype: book\n:lang: en\n:listing-caption: Listing\n:source-highlighter: coderay\n:icons: font\n:sectlink: true\n:sectanchors: true\n:numbered: true\n:xrefstyle: short\n:use-latest-version-for-docs: 0\n\nifndef::manualIncludeDir[]\n:manualIncludeDir: ../\nendif::[]\n\ninclude::{manualIncludeDir}/README.adoc[tags=properties]\n\nifeval::[{use-latest-version-for-docs} == 1]\n:the-version: {neo4j-cypher-dsl-version-latest}\nendif::[]\n\nifeval::[{use-latest-version-for-docs} == 0]\n:the-version: {neo4j-cypher-dsl-version}\nendif::[]\n\n:copyright: 2020-2025 Neo4j, Inc.,\n:gh-base: https://github.com/neo4j/sdn-rx\n:java-driver-starter-href: https://github.com/neo4j/neo4j-java-driver-spring-boot-starter\n:springVersion: 5.2.0.RELEASE\n:spring-framework-docs: https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference\n:spring-framework-javadoc: https://docs.spring.io/spring/docs/{springVersion}/javadoc-api\n\n\n(C) {copyright}\n\n[abstract]\n--\nThis is the Neo4j Cypher-DSL manual version {the-version}.\n--\n\n_Who should read this?_\n\nThis manual is written for people interested in creating Cypher queries in a typesafe way on the JVM.\n\nNOTE: All public classes inside `org.neo4j.cypherdsl` still subject to breaking changes are annotated with `@API(status = EXPERIMENTAL)`.\n\ninclude::introduction-and-preface/index.adoc[leveloffset=+1]\n\ninclude::getting-started/index.adoc[leveloffset=+1]\n\ninclude::properties/index.adoc[leveloffset=+1]\n\ninclude::functions/index.adoc[leveloffset=+1]\n\ninclude::cypher-parser/index.adoc[leveloffset=+1]\n\ninclude::static-meta-model/index.adoc[leveloffset=+1]\n\ninclude::appendix/index.adoc[leveloffset=+1]\n"
  },
  {
    "path": "docs/introduction-and-preface/index.adoc",
    "content": "[[introduction]]\n= Introduction\n\ninclude::introduction.adoc[]\n"
  },
  {
    "path": "docs/introduction-and-preface/introduction.adoc",
    "content": "== Purpose\n\nThe Cypher-DSL has been developed with the needs of Spring Data Neo4j.\nWe wanted to avoid string concatenations in our query generation and decided do go with a builder approach, much like we\nfind with https://www.jooq.org[jOOQ] or in the relational module of https://github.com/spring-projects/spring-data-jdbc/tree/1.1.6.RELEASE/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql[Spring Data JDBC], but for Cypher.\n\nWhat we don't have - and don't need for our mapping purpose - at the moment is a code generator that reads the database schema\nand generates static classes representing labels and relationship types.\nThat is still up to the mapping framework (in our case SDN).\nWe however have a type safe API for Cypher that allows only generating valid Cypher constructs.\n\nWe worked closely with the https://www.opencypher.org[OpenCypher spec] here and you find a lot of these concepts in the API.\n\nThe Cypher-DSL can also be seen in the same area as the https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/query/Criteria.html[Criteria API] of Spring Data Mongo.\n\n== Where to use it\n\nThe Cypher-DSL creates an https://en.wikipedia.org/wiki/Abstract_syntax_tree[Abstract Syntax Tree (AST)] representing your Cypher-Statements.\nAn instance of a `org.neo4j.cypherdsl.core.Statement` representing that AST is provided at the end of query building step.\nA `Renderer` is then used to create literal Java-Strings.\nThose can be used in any context supporting String-based queries, for example with the https://github.com/neo4j/neo4j-java-driver[Neo4j Java driver] or inside embedded procedures and of course with Spring Data's https://github.com/spring-projects/spring-data-neo4j/blob/master/src/main/java/org/springframework/data/neo4j/core/Neo4jClient.java[Neo4j-Client].\n\nParameters in the generated queries will use the `$form` and as such be compatible with all current versions of Neo4j.\n\nUsers of SDN 6+ can use the generated `org.neo4j.cypherdsl.core.Statement` directly with the `Neo4jTemplate` or the `ReactiveNeo4jTemplate`.\nBoth the imperative and the reactive variants allow the retrieval and counting of entities without rendering a String first,\nfor example through `Neo4jTemplate#findAll(Statement, Class<T>)`.\n\n== Java API\n\nFind the Java-API and a generated project info here: link:project-info/apidocs/index.html[API] and link:project-info/index.html[project info].\n"
  },
  {
    "path": "docs/properties/index.adoc",
    "content": "[[properties]]\n= Properties\n\nNodes and Relationships expose properties.\nThis reflects directly in the Cypher-DSL:\n\n[[properties-on-nodes-and-rel]]\n[source,java,indent=0]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/PropertiesTests.java[tag=properties-on-nodes-and-rel]\n----\n<.> Create a property expression from a `Node`\n<.> Create a property expression from a `Relationship`\n\nBoth Node and Relationship should be named as in the example.\nThe Cypher-DSL generates names if they are not named, to refer to them in the statements.\nWithout the explicit names, the generated statement would look like this:\n\n[source,cypher]\n----\nMATCH (geIcWNUD000:`Person`)-[TqfqBNcc001:`RATED`]->(:`Movie`) RETURN geIcWNUD000.name, TqfqBNcc001.rating\n----\n\nThe name is of course random.\n\nThe `Cypher` class exposes the `property` method, too. This methods takes in one name (as symbolic name or as string literal) OR one expression\nand  at least one further string, referring to the name of the property.\n\nPassing in a symbolic name would lead to a similar result like in <<properties-on-nodes-and-rel>>, an expression can refer\nto the results of functions etc.:\n\n[[properties-on-expressions]]\n[source,java,indent=0]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/PropertiesTests.java[tag=properties-on-expressions]\n----\n<.> Here an expression, the `datetime()` function is passed in and the `epocheSeconds` property is dereferenced.\n\nNested properties are of course possible as well, either directly on nodes and relationships or via the static builder:\n\n[[nested-properties]]\n[source,java,indent=0]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/PropertiesTests.java[tag=nested-properties]\n----\n\n"
  },
  {
    "path": "docs/static-meta-model/concepts.adoc",
    "content": "== Concepts\n\n=== A static meta model is optional\n\nFirst let's stress this: a static meta model is optional for the Cypher-DSL. It is completely OK to use the Cypher-DSL\nas shown in the <<how-to-use-it.examples,examples in the \"How to use it\" part>>:\nall labels, types and properties can be named as you go.\nThe Cypher-DSL will still give you type-safety in regard to the Cypher's syntax.\n\nThis fits nicely with Neo4j's capabilities: Neo4j is a schemaless database. Nodes, their relationships between each other,\ntheir labels and properties can be changed as you go but all of this information can still be queried.\n\nIn a schemaless database or a database with dynamic scheme the scheme is often defined by the application.\nThis definition takes many forms: It can be through an object mapper like https://github.com/neo4j/neo4j-ogm[Neo4j-OGM] or\nhttps://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#reference[Spring Data Neo4j 6+], or maybe in form of\nGraph-QL schemes.\n\nAnother source may be the information we can retrieve from the database itself via https://neo4j.com/docs/operations-manual/current/reference/procedures/#procedure_db_schema_nodetypeproperties[`db.schema.nodeTypeProperties`] and\nhttps://neo4j.com/docs/operations-manual/current/reference/procedures/#procedure_db_schema_reltypeproperties[`db.schema.relTypeProperties`].\n\n[[static-meta-model.building-blocks]]\n=== Building blocks\n\nThe Cypher DSL offers the following building blocks as part of the public API:\n\n* Two pattern elements:\n** Nodes via `Node` (and its default implementation `NodeBase`)\n** Relationships via `Relationship` (and its default implementation `RelationshipBase`)\n* `Property`, which is a holder for properties\n\nWhen you use Cypher-DSL like this:\n\n[source,java]\n----\nvar m = Cypher.node(\"Movie\").named(\"m\");\nvar statement = Cypher.match(m).returning(this.m).build();\n----\n\n`m` will be a `Node` instance having the label `Movie` and an alias of `m`. `m` can be used everywhere where a pattern element\ncan be used according to the openCypher spec.\nYou don't have to care about its type. That's why we vouched for the JDK11+ local type inference here and omitted the\ndeclaration of the type `Node`: it just reads better.\n\n=== A very simple, static model\n\nBoth `NodeBase` and  `RelationshipBase` are meant to be extended to put your static model into something that is usable\nwith the Cypher-DSL.\n\n==== Nodes\n\nStart by extending `NodeBase` like this:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/Movie.java[tag=simple-model]\n----\n<.> Extend from `NodeBase` and specify your class as a \"self\" type-argument\n<.> Optional: Create one static instance of your model\n<.> This is where you specify one or more label\n<.> This constructor is optional, it is used in the next two steps\n<.> `named` must be overridden and must return new copies of the node, with the changed symbolic name.\n    It must be overridden to guarantee type integrity.\n<.> Same as above\n\nWith that in place, you can already use it like this:\n\n[source,java,indent=0,tabsize=4]\n[[static-movie]]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/StaticModelIT.java[tag=simple-model]\n----\n\nand it would generate a Cypher string like this: `\"MATCH (jwKyXzwS000:`Movie`) RETURN jwKyXzwS000\"`, with generated variable names.\n\nIf you don't like them, you can just rename one instance of the movie-model like this:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/StaticModelIT.java[tag=simple-model-renamed]\n----\n\nOf course, properties belong into a model as well. You add them like this:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/Movie.java[tag=add-properties]\n----\n<.> Same class before, extending from `NodeBase`.\n<.> Use `this` and the `property` method to create a new `Property` instance, stored on the given instance\n\nA possible usage scenario looks like this:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/StaticModelIT.java[tag=add-properties]\n----\n<.> Make sure to use the renamed instance everywhere. Here: For accessing the property. Alternatively, don't rename.\n\n==== Relationships\n\nRelationships are a bit more complicated. Relationships of the same type can be used between nodes with different labels.\nWe have these scenarios:\n\n* `(s:LabelA) - (r:SomeType) -> (e:LabelB)`:\n* `(s:LabelA) - (r:SomeType) -> (e)`\n* `(s) - (r:SomeType) -> (e)`\n\nWe either have a type that is used only between the same set of labels, or a type is used always with one fixed label or\na type is used between arbitrary labels.\n\nTo accommodate for that, the default relationship implementation, `RelationshipBase`, spots three type parameters:\n\n[source,java]\n----\npublic class RelationshipBase<S extends NodeBase<?>, E extends NodeBase<?>, SELF extends RelationshipBase<S, E, SELF>> {\n}\n----\n\n`S` is the type of a start node, `E` of an end node and `SELF` is the concrete implementation itself.\nThe public API of `RelationshipBase` enforces a direction from start to end (`LTR`, left to right).\n\nWe just have a look at the first case to make the concepts clear. We model the `ACTED_IN` relationship of the movie graph.\nIt exists between people and movies (going from person to movie) and has an attribute roles:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/ActedIn.java[tag=simple-model]\n----\n<.> The base class, with 3 concrete types. A `Person`, the `Movie` from <<static-movie>> and the type itself.\n<.> Same idea with as with nodes: Store all properties as final attributes.\n<.> There is no default constructor for a relationship: Start and end node must be specified. The type is fixed.\n<.> Copy constructor for the following two methods\n<.> Required to rename this relationship\n<.> Required for querying properties\n\nIn contrast to the movie, we don't need a static attribute allowing access to the relationship.\nThis is stored at the owner. In this case, the `Person`:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/Person.java[tag=simple-model]\n----\n<.> We create the relationship properties with `this` concrete instance pointing to another, concrete instance.\n\n=== Summary\n\nWhile there are possible other ways to define a static meta model with the Cypher-DSL, this is the way we create them with\nthe `neo4j-cypher-dsl-codegen` models.\n"
  },
  {
    "path": "docs/static-meta-model/index.adoc",
    "content": "[[static-meta-model]]\n= Building a static metamodel\n\ninclude::concepts.adoc[]\n\ninclude::possible-usage.adoc[]\n\ninclude::sdn6-annotation-processor.adoc[]\n\ninclude::ogm-annotation-processor.adoc[]\n"
  },
  {
    "path": "docs/static-meta-model/ogm-annotation-processor.adoc",
    "content": "[[ogm-annotation-processor]]\n== The Neo4j-OGM annotation processor\n\nWe provide a Java annotation processor for https://github.com/neo4j/neo4j-ogm[Neo4j-OGM] under the following coordinates:\n\n[source,subs=\"verbatim,attributes\",indent=0,tabsize=4]\n.Coordinates of the Neo4j-OGM annotation processor\n----\n{groupId}:neo4j-cypher-dsl-codegen-ogm:{the-version}\n----\n\nThe annotation processor understands classes annotated with `@NodeEntity` and `@RelationshipEntity`.\nInside those classes `@Relationship`, `@Property`, `@StartNode` and `@EndNode` are read.\n\nThe processor generates a static metamodel for each annotated class found in the same package with an underscore (`_`) added to the name.\n\nThe processor needs Neo4j-OGM 4 and the Cypher-DSL in version `2025.0.0` or later on it's classpath.\nWe recommend using it explicitly on the separate annotation processor classpath (via `--processor-path` to `javac`).\n\nThe processor does *not* support nested classes used as `@NodeEntity` or `@RelationshipEntity`.\n\nThis processor is a great choice for applications built on https://quarkus.io[Quarkus] using https://github.com/neo4j/neo4j-ogm-quarkus[Neo4j-OGM-Quarkus] but also for https://github.com/neo4j/neo4j-ogm-spring[Neo4j-OGM-Spring], our Spring Data Neo4j 5 work that supports Spring Boot >= 3 and the latest Spring Data generation with the behaviour of SDN5 and OGM.\n\n=== Configure your build\n\n==== Maven\n\nAs a Maven user, please configure the build as follows:\n\n[source,xml,subs=\"verbatim,attributes\",indent=0,tabsize=4]\n----\n<build>\n    <plugins>\n        <plugin>\n            <groupId>org.apache.maven.plugins</groupId>\n            <artifactId>maven-compiler-plugin</artifactId>\n            <configuration>\n                <annotationProcessorPaths>\n                    <annotationProcessorPath>\n                        <groupId>{groupId}</groupId>\n                        <artifactId>neo4j-cypher-dsl-codegen-ogm</artifactId>\n                        <version>{neo4j-cypher-dsl.version}</version>\n                    </annotationProcessorPath>\n                </annotationProcessorPaths>\n            </configuration>\n        </plugin>\n    </plugins>\n</build>\n----\n\n==== Gradle\n\nIn a Gradle project, please add the following:\n\n[source,groovy,subs=\"verbatim,attributes\"]\n----\ndependencies {\n    annotationProcessor '{groupId}:neo4j-cypher-dsl-codegen-ogm:{the-version}'\n}\n----\n\n==== As dependency on the classpath\n\nNOTE: We recommend the annotation processor path for two reasons: The processor needs Neo4j-OGM as dependency. While Neo4j-OGM is already on the classpath,\nit might not fit the one we build the annotation processor against exactly.\nWhile the processor is lenient in that regard, your dependency setup might not.\nFurthermore: Why should you have the annotation processor as a dependency in your final artifact? This would be unnecessary.\n\nIf you insist on having the Neo4j-OGM annotation processor on the standard class path, please include with your Neo4j-OGM\napplication like as follows to avoid dependency conflicts:\n\n[source,xml,subs=\"verbatim,attributes\",indent=0,tabsize=4]\n----\n<dependency>\n    <groupId>{groupId}</groupId>\n    <artifactId>neo4j-cypher-dsl-codegen-ogm</artifactId>\n    <version>{neo4j-cypher-dsl.version}</version>\n    <optional>true</optional>\n    <exclusions>\n        <exclusion>\n            <groupId>org.neo4j</groupId>\n            <artifactId>neo4j-ogm-core</artifactId>\n        </exclusion>\n    </exclusions>\n</dependency>\n----\n\n=== Usage\n\nThe processor supports the same arguments as the <<sdn6-annotation-processor>> except for `org.neo4j.cypherdsl.codegen.sdn.custom_converter_classes`.\nThe usage of the generated classes is identical.\n"
  },
  {
    "path": "docs/static-meta-model/possible-usage.adoc",
    "content": "== Possible Usage\n\nPlease assume we did model the \"Movie graph\" (`:play movies` in Neo4j-Browser) with the following scheme:\n\nimage::movie-graph.png[]\n\nand these classes, which have been generated with the\n<<static-meta-model.building-blocks, building blocks described earlier>> (the required functions have been omitted for brevity):\n\n[source,java,indent=0,tabsize=4]\n----\nfinal class Movie extends NodeBase<Movie> {\n\n\tpublic static final Movie MOVIE = new Movie();\n\n\tpublic final Property TAGLINE = this.property(\"tagline\");\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Property RELEASED = this.property(\"released\");\n\n\tpublic Movie() {\n\t\tsuper(\"Movie\");\n\t}\n}\n\nfinal class Person extends NodeBase<Person> {\n\n\tpublic static final Person PERSON = new Person();\n\n    public final Property NAME = this.property(\"name\");\n\n\tpublic final Property FIRST_NAME = this.property(\"firstName\");\n\n\tpublic final Directed<Movie> DIRECTED = new Directed<>(this, Movie.MOVIE);\n\n\tpublic final ActedIn ACTED_IN = new ActedIn(this, Movie.MOVIE);\n\n\tpublic final Property BORN = this.property(\"born\");\n\n\tpublic final Property DOB = this.property(\"dob\");\n\n\tpublic Person() {\n\t\tsuper(\"Person\");\n\t}\n}\n\nfinal class ActedIn extends RelationshipBase<Person, Movie, ActedIn> {\n\n\tpublic static final String $TYPE = \"ACTED_IN\";\n\n\tpublic final Property ROLE = this.property(\"role\");\n\n\tprotected ActedIn(Person start, Movie end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n}\n\nfinal class Directed<E extends NodeBase<?>> extends RelationshipBase<Person, E, Directed<E>> {\n\n\tpublic static final String $TYPE  = \"DIRECTED\";\n\n\tprotected Directed(Person start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n}\n----\n\n=== Work with properties\n\nProperties can be used like normal objects:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/StaticModelIT.java[tag=work-with-properties]\n----\n\nOf course, new properties can be derived:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/StaticModelIT.java[tag=deriving-new-properties]\n----\n\n=== Query nodes or relationships by properties\n\nUse `withProperties` (and `named` you like) to model your queries as needed.\nApplicable to properties of nodes such as the title:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/StaticModelIT.java[tag=query-node-by-properties]\n----\n\nand relationships:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/StaticModelIT.java[tag=query-rel-by-properties]\n----\n\nNote that the query will look like this, as we didn't rename the objects and they used generated names:\n\n[source,cypher]\n----\n`MATCH (dZVpwHhe000:`Person`)-[JcVKsSrn001:`ACTED_IN` {role: 'Neo'}]->(cDWeUJSI002:`Movie`) RETURN cDWeUJSI002`` as we didn't specify aliases)\n----\n\n=== Work with relationships\n\nRelationships can be worked with like with properties:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/StaticModelIT.java[tag=multiple-relationships]\n----\n\nThey are quite flexible together with the `inverse` method. The following example also shows how to include non-static parts:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/StaticModelIT.java[tag=chaining-relationships]\n----\n<.> Using a non-static fragment\n"
  },
  {
    "path": "docs/static-meta-model/sdn6-annotation-processor.adoc",
    "content": "[[sdn6-annotation-processor]]\n== The Spring Data Neo4j 6 annotation processor\n\nWe provide a Java annotation processor for https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#reference[Spring Data Neo4j] under the following coordinates:\n\n[source,subs=\"verbatim,attributes\",indent=0,tabsize=4]\n.Coordinates of the SDN 6 annotation processor\n----\n{groupId}:neo4j-cypher-dsl-codegen-sdn6:{the-version}\n----\n\nThe annotation processor understands classes annotated with `@Node` and `@RelationshipProperties`.\nInside those classes `@Relationship` and `@Property` are read.\n\nThe processor generates a static metamodel for each annotated class found in the same package with an underscore (`_`) added to the name.\n\nThe processor needs Spring Data Neo4j 6 and the Cypher-DSL in version `2021.1.0` or later on it's classpath.\nWe recommend using it explicitly on the separate annotation processor classpath (via `--processor-path` to `javac`).\n\nTIP: Please make sure to use `@Relationship` when you use the annotation processor. While we do our best to detect possible,\n     implicit associations during annotation processing, we can't load classes that are being processed that very moment\n     to check if the Spring infrastructure would provide a custom converter for them and make them a simple property.\n     We won't generate fields when in doubt but relationships if we find the corresponding class.\n\nThe processor does *not* support nested classes used as `@Node` or `@RelationshipProperties` entities.\n\n=== Configure your build\n\n==== Maven\n\nAs a Maven user, please configure the build as follows:\n\n[source,xml,subs=\"verbatim,attributes\",indent=0,tabsize=4]\n----\n<build>\n    <plugins>\n        <plugin>\n            <groupId>org.apache.maven.plugins</groupId>\n            <artifactId>maven-compiler-plugin</artifactId>\n            <configuration>\n                <annotationProcessorPaths>\n                    <annotationProcessorPath>\n                        <groupId>{groupId}</groupId>\n                        <artifactId>neo4j-cypher-dsl-codegen-sdn6</artifactId>\n                        <version>{neo4j-cypher-dsl.version}</version>\n                    </annotationProcessorPath>\n                </annotationProcessorPaths>\n            </configuration>\n        </plugin>\n    </plugins>\n</build>\n----\n\n==== Gradle\n\nIn a Gradle project, please add the following:\n\n[source,groovy,subs=\"verbatim,attributes\"]\n----\ndependencies {\n    annotationProcessor '{groupId}:neo4j-cypher-dsl-codegen-sdn6:{the-version}'\n}\n----\n\n==== As dependency on the classpath\n\nNOTE: We recommend the annotation processor path for two reasons: The processor needs SDN as dependency. While SDN is already on the classpath,\nit might not fit the one we build the annotation processor against exactly.\nWhile the processor is lenient in that regard, your dependency setup might not.\nFurthermore: Why should you have the annotation processor as a dependency in your final artifact? This would be unnecessary.\n\nIf you insist on having the SDN 6 annotation processor on the standard class path, please include with your Spring Data Neo4j 6\napplication like as follows to avoid dependency conflicts:\n\n[source,xml,subs=\"verbatim,attributes\",indent=0,tabsize=4]\n----\n<dependency>\n    <groupId>{groupId}</groupId>\n    <artifactId>neo4j-cypher-dsl-codegen-sdn6</artifactId>\n    <version>{neo4j-cypher-dsl.version}</version>\n    <optional>true</optional>\n    <exclusions>\n        <exclusion>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-simple</artifactId>\n        </exclusion>\n        <exclusion>\n            <groupId>org.springframework.data</groupId>\n            <artifactId>spring-data-neo4j</artifactId>\n        </exclusion>\n    </exclusions>\n</dependency>\n----\n\n=== Usage\n\nThe processor supports the following arguments:\n\n|===\n|Name | Meaning\n\n| org.neo4j.cypherdsl.codegen.prefix,\n| An optional prefix for the generated classes\n\n| org.neo4j.cypherdsl.codegen.suffix\n| An optional suffix for the generated classes\n\n| org.neo4j.cypherdsl.codegen.indent_style\n| The indent style (Use `TAB` for tabs, `SPACE` for spaces)\n\n| org.neo4j.cypherdsl.codegen.indent_size\n| The number of whitespaces for the indent style `SPACE`\n\n| org.neo4j.cypherdsl.codegen.timestamp\n| An optional timestamp in ISO_OFFSET_DATE_TIME format for the generated classes. Defaults to the time of generation.\n\n| org.neo4j.cypherdsl.codegen.add_at_generated\n| A flag whether `@Generated` should be added\n\n| org.neo4j.cypherdsl.codegen.sdn.custom_converter_classes\n| A comma separated list of custom Spring converter classes (Can be `Converter`, `GenericConverter`, `ConverterAware`,\n  pretty much everything you can register with `org.springframework.data.neo4j.core.convert.Neo4jConversions` ). However,\n  these converters must have a default-non-args constructor in the context of the annotation processor.\n\n| org.neo4j.cypherdsl.codegen.excludes\n| A comma separated list of fully qualified names of types that should be ignored (i.e. despite being annotated as `Node` or `RelationshipProperties`)\n\n|===\n\nThe generated classes can be used in a variety of places:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/MovieService.java[tag=as-property]\n----\n<.> Pass the name of the property `TITLE` to Spring Data's sort facility\n\nSpring Data Neo4j 6.1 has two additional query fragments, that makes working with the Cypher-DSL very efficient:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/PeopleRepository.java[tag=additional-fragments]\n----\n<.> Allows to just add conditions to our generated queries\n<.> Provides an alternative to using @Query with strings\n\nBoth interfaces are *independent*  of each other, they can be used together like in this example or separately (just picking the one you need).\nYou can read more about them in the Spring Data Neo4j 6.1 documentation, chapter https://docs.spring.io/spring-data/neo4j/docs/6.1.0-M5/reference/html/#sdn-mixins[Spring Data Neo4j Extensions].\n\nThe repository above can be used like this:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/PeopleService.java[tag=using-person-repo]\n----\n<.> Using literals\n<.> Using an optional parameter\n<.> or when it's not filled, an empty condition\n<.> Project a person onto `PersonDetails`, using a complex query.\n\nHere is another complex example. The `MovieRepository` is also a `CypherdslStatementExecutor`:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/MovieService.java[tag=more-examples]\n----\n<.> Here we use an anonymous parameter to store the `name` value\n\nThe full example is in `neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6`.\n\nAn example of using a mixture of anonymous and named parameters is shown in the following listing:\n\n[source,java,indent=0,tabsize=4]\n----\ninclude::../../neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/PeopleService.java[tag=using-temporals]\n----\n<.> An anonymous parameter with a simple `String`-value\n<.> A named parameter with an `Integer` value extracted from a complex datatype\n<.> An anonymous parameter again, but one that holds a complex datatype. Such datatype\n    can be anything that is understood by the Neo4j-Java-Driver, such as in this case, a temporal\n    but also maps and lists. It will always be passed as a value, never as a literal.\n\nThe statement above will be rendered like this:\n\n[source,console]\n----\n[http-nio-auto-1-exec-1] 2022-06-21 11:40:57,732 DEBUG    org.springframework.data.neo4j.cypher: 313 - Executing:\nMERGE (p:`Person` {name: $pcdsl01}) ON CREATE SET p.born = $arbitraryName, p.dob = $pcdsl02 RETURN p\n[http-nio-auto-1-exec-1] 2022-06-21 11:40:57,735 TRACE    org.springframework.data.neo4j.cypher: 334 - with parameters:\n:param arbitraryName => 1990\n:param pcdsl01 => 'Liv Lisa Fries'\n:param pcdsl02 => 1990-10-31T22:42Z[UTC]\n----\n"
  },
  {
    "path": "etc/architecture/api.adoc",
    "content": "[[arch-rules.api]]\n[role=group,includesConstraints=\"arch-rules.api:*\"]\n\n==== API\n\n===== General considerations\n\nWe use https://github.com/apiguardian-team/apiguardian[@API Guardian] to keep track of what we expose as public or internal API.\nTo keep things both clear and concise, we restrict the usage of those annotations to interfaces, classes (only public methods and constructors:\nand annotations.\n\n[[arch-rules.api:api-guardian-usage]]\n[source,java,indent=0,tabsize=4]\n.@API Guardian annotations must not be used on fields\n----\ninclude::../../neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/PackageAndAPIStructureTests.java[tag=arch-rules.structure:core-must-not-depend-on-renderer]\n----\n\n===== Internal API\n\nWhile we are pretty clear about the intended use of our classes (being experimental, public API or strictly internal),\nwe want to make sure that no-one can coincidentally inherit from internal classes that we couldn't restrict to default\npackage visibility.\n\nThere should not be any internal, public API inside the core package.\nEverything that needs to be public for reasons (like being used in the renderer), must go into the `internal` package.\nThis package won't be exported via `module-info.java`.\n\n[[arch-rules.api:internal]]\n[source,java,indent=0,tabsize=4]\n.Non abstract, public classes that are only part of internal API must be final\n----\ninclude::../../neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/PackageAndAPIStructureTests.java[tag=arch-rules.api:internal]\n----\n"
  },
  {
    "path": "etc/architecture/index.adoc",
    "content": "[[arch-rules]]\n[role=group,includesGroups=\"arch-rules.naming,arch-rules.api,arch-rules.structure\"]\n== Architecture\n\nThe Neo4j-Cypher-DSL consists of one main module: `org.neo4j.cypherdsl.core`.\nThe coordinates of that module `{groupId}:{artifactId}`, the JDK module name is `org.neo4j.cypherdsl.core`.\nThe rendering feature is part of the core module.\n\nAll other modules depend on the core. As the core reflects the Cypher language, it is not meant to be extendable.\nTherefore, there is little to know API to do so with the AST visitor being the exception.\n\nWe document our rules structure with https://www.archunit.org[ArchUnit] within a single unittest named `org.neo4j.cypherdsl.core.PackageAndAPIStructureTests`.\n\n=== Coding rules\n\ninclude::naming.adoc[]\n\ninclude::api.adoc[]\n\n=== Structure\n\ninclude::structure.adoc[]\n"
  },
  {
    "path": "etc/architecture/naming.adoc",
    "content": "[[arch-rules.naming]]\n[role=group,includesConstraints=\"arch-rules.naming:*\"]\n\n==== Consistent naming\n\nThe following naming conventions are used throughout the project:\n\n[[arch-rules.naming:TypeNameMustBeginWithGroupId]]\n[source,java,indent=0,tabsize=4]\n.All Java types must be located in packages that start with `org.neo4j.cypherdsl`.\n----\ninclude::../../neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/PackageAndAPIStructureTests.java[tag=arch-rules.naming:TypeNameMustBeginWithGroupId]\n----\n"
  },
  {
    "path": "etc/architecture/structure.adoc",
    "content": "[[arch-rules.structure]]\n[role=group,includesConstraints=\"arch-rules.structure:*\"]\n\n==== Neo4j-Cypher-DSL Core\n\nThe core of the Cypher-DSL is consist of a set of classes that loosely reassemble the https://www.opencypher.org[openCypher spec],\nespecially in the https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Cypher.html[railroad diagrams].\n\nThe main package of the core module is `org.neo4j.cypherdsl.core` which also reflects in the JDK module name: `org.neo4j.cypherdsl.core`.\nPart of the Cypher-DSL core is also the `renderer` package as the main goal of the core is to render Cypher.\nThe `renderer` package is a sub-package of `core` as it is an essential part of it and in addition, the above mentioned\nJDK module name should reflect exactly one package.\n\nSo while all other subpackages in `core` can be used freely from the `core` classes themselves, we don't want to access the\n`renderer` package apart from one exception: The `AbstractStatement` class can be used to invoke the rendering process without\nexplicitly specifying a renderer:\n\n[[arch-rules.structure:core-must-not-depend-on-renderer]]\n[source,java,indent=0,tabsize=4]\n.The Cypher-DSL core package must not depend on the rendering infrastructure\n----\ninclude::../../neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/PackageAndAPIStructureTests.java[tag=arch-rules.structure:core-must-not-depend-on-renderer]\n----\n\nThe `renderer` package is not only free to use the whole `core`, it must do so to fulfill its purpose.\nThe `ast` and `utils` packages however should not have dependencies outside their own:\n\n[[arch-rules.structure:supporting-packages-are-dependency-free]]\n[source,java,indent=0,tabsize=4]\n.Supporting packages must not depend on anything from the outside\n----\ninclude::../../neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/PackageAndAPIStructureTests.java[tag=arch-rules.structure:supporting-packages-are-dependency-free]\n----\n"
  },
  {
    "path": "etc/changelog.tpl",
    "content": "==== 🚀 Features\n\n==== 🐛 Bug Fixes\n\n==== 🔄️ Refactorings\n\n==== 📖 Documentation\n\n==== 🧰 Tasks\n\n==== 🧹 Housekeeping\n\n==== 🛠 Build"
  },
  {
    "path": "etc/checkstyle/config.xml",
    "content": "<?xml version=\"1.0\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<!DOCTYPE module PUBLIC\n\t\t\"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN\"\n\t\t\"https://checkstyle.org/dtds/configuration_1_3.dtd\">\n<module name=\"com.puppycrawl.tools.checkstyle.Checker\">\n\t<module name=\"io.spring.javaformat.checkstyle.SpringChecks\">\n\t\t<property name=\"excludes\" value=\"io.spring.javaformat.checkstyle.check.SpringAvoidStaticImportCheck\"/>\n\t\t<property name=\"excludes\" value=\"io.spring.javaformat.checkstyle.check.SpringHeaderCheck\"/>\n\t\t<property name=\"excludes\" value=\"io.spring.javaformat.checkstyle.check.SpringLambdaCheck\"/>\n\t\t<property name=\"excludes\" value=\"com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocMethodCheck\"/>\n\t</module>\n\t<module name=\"NewlineAtEndOfFile\"/>\n\t<module name=\"SuppressWarningsFilter\"/>\n\t<module name=\"com.puppycrawl.tools.checkstyle.TreeWalker\">\n\t\t<module name=\"SuppressWarningsHolder\"/>\n\t\t<!-- System.outs -->\n\t\t<module name=\"Regexp\">\n\t\t\t<property name=\"format\" value=\"System\\.out\\.println\"/>\n\t\t\t<property name=\"illegalPattern\" value=\"true\"/>\n\t\t</module>\n\n\t\t<module name=\"io.spring.javaformat.checkstyle.check.SpringAvoidStaticImportCheck\">\n\t\t\t<property\n\t\t\t\t\tname=\"excludes\"\n\t\t\t\t\tvalue=\"\n\t\t\t\t\torg.apiguardian.api.API.Status.*,\n\t\t\t\t\tcom.github.stefanbirkner.systemlambda.SystemLambda.*,\n\t\t\t\t\tcom.tngtech.archunit.base.DescribedPredicate.*,\n\t\t\t\t\tcom.tngtech.archunit.core.domain.JavaClass.Predicates.*,\n\t\t\t\t\tcom.tngtech.archunit.core.domain.JavaAccess.Predicates.*,\n\t\t\t\t\tcom.tngtech.archunit.core.domain.properties.HasModifiers.Predicates.*,\n\t\t\t\t\tcom.tngtech.archunit.lang.conditions.ArchPredicates.*,\n\t\t\t\t\tcom.tngtech.archunit.lang.syntax.ArchRuleDefinition.*,\n\t\t\t\t\tcom.querydsl.core.alias.Alias.*,\n\t\t\t\t\tcom.querydsl.core.types.dsl.Expressions.*,\n\t\t\t\t\torg.neo4j.jdbc.Neo4jException.*\n                \"\n\t\t\t/>\n\t\t</module>\n\n\t\t<module name=\"JavadocMethod\">\n\t\t\t<property name=\"allowInlineReturn\" value=\"true\"/>\n\t\t</module>\n\t</module>\n</module>\n"
  },
  {
    "path": "etc/checkstyle/suppressions.xml",
    "content": "<?xml version=\"1.0\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<!DOCTYPE suppressions PUBLIC\n\t\t\"-//Puppy Crawl//DTD Suppressions 1.1//EN\"\n\t\t\"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd\">\n<suppressions>\n\t<suppress checks=\"InterfaceIsType\" files=\"Neo4jDriverExtensions\\.java\"/>\n\t<suppress checks=\"InterfaceIsType\" files=\"Neo4jStatement\\.java\"/>\n\t<suppress checks=\"RegexpHeader\" files=\"package-info\\.java\"/>\n\t<suppress checks=\"[a-zA-Z0-9]*\" files=\"[\\\\/]generated-test-sources[\\\\/]\"/>\n\t<suppress checks=\"JavadocVariable\" files=\"org[\\\\/]neo4j[\\\\/]jdbc[\\\\/]internal[\\\\/]bolt\"/>\n</suppressions>\n"
  },
  {
    "path": "etc/index.tpl",
    "content": "<!DOCTYPE html>\n <html>\n     <head>\n         <title>Redirecting...</title>\n         <meta charset=\"utf-8\" />\n         <meta http-equiv=\"refresh\" content=\"0; URL=/cypher-dsl/${current}/\" />\n     </head>\n     <body>\n         <p>Please follow <a href=\"/cypher-dsl/${current}/\">this link</a>.</p>\n     </body>\n </html> \n"
  },
  {
    "path": "etc/license.tpl",
    "content": "Copyright (c) 2019-${year} \"Neo4j,\"\nNeo4j Sweden AB [https://neo4j.com]\n\nThis file is part of Neo4j.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License."
  },
  {
    "path": "etc/recipes/rewrite.yml",
    "content": "#\n# Copyright (c) 2019-2026 \"Neo4j,\"\n# Neo4j Sweden AB [https://neo4j.com]\n#\n# This file is part of Neo4j.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n# Run with\n# ./mvnw org.openrewrite.maven:rewrite-maven-plugin:run \\\n#   -Drewrite.configLocation=/full/path/to/cypher-dsl/etc/recipes/rewrite.yml \\\n#   -Drewrite.activeRecipes=cypher-dsl.rewriteIdCalls\n---\ntype: specs.openrewrite.org/v1beta/recipe\nname: cypher-dsl.rewriteIdCalls\ndisplayName: Change calls to Functions.id to Functions.elementId\nrecipeList:\n  - org.openrewrite.java.ChangeMethodName:\n      methodPattern: org.neo4j.cypherdsl.core.Functions id(..)\n      newMethodName: elementId\n      ignoreDefinition: true\n"
  },
  {
    "path": "mvnw",
    "content": "#!/bin/sh\n# ----------------------------------------------------------------------------\n# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n# ----------------------------------------------------------------------------\n\n# ----------------------------------------------------------------------------\n# Apache Maven Wrapper startup batch script, version 3.3.4\n#\n# Required ENV vars:\n# ------------------\n#   JAVA_HOME - location of a JDK home dir\n#\n# Optional ENV vars\n# -----------------\n#   MAVEN_OPTS - parameters passed to the Java VM when running Maven\n#     e.g. to debug Maven itself, use\n#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000\n#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files\n# ----------------------------------------------------------------------------\n\nif [ -z \"$MAVEN_SKIP_RC\" ]; then\n\n  if [ -f /usr/local/etc/mavenrc ]; then\n    . /usr/local/etc/mavenrc\n  fi\n\n  if [ -f /etc/mavenrc ]; then\n    . /etc/mavenrc\n  fi\n\n  if [ -f \"$HOME/.mavenrc\" ]; then\n    . \"$HOME/.mavenrc\"\n  fi\n\nfi\n\n# OS specific support.  $var _must_ be set to either true or false.\ncygwin=false\ndarwin=false\nmingw=false\ncase \"$(uname)\" in\nCYGWIN*) cygwin=true ;;\nMINGW*) mingw=true ;;\nDarwin*)\n  darwin=true\n  # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home\n  # See https://developer.apple.com/library/mac/qa/qa1170/_index.html\n  if [ -z \"$JAVA_HOME\" ]; then\n    if [ -x \"/usr/libexec/java_home\" ]; then\n      JAVA_HOME=\"$(/usr/libexec/java_home)\"\n      export JAVA_HOME\n    else\n      JAVA_HOME=\"/Library/Java/Home\"\n      export JAVA_HOME\n    fi\n  fi\n  ;;\nesac\n\nif [ -z \"$JAVA_HOME\" ]; then\n  if [ -r /etc/gentoo-release ]; then\n    JAVA_HOME=$(java-config --jre-home)\n  fi\nfi\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched\nif $cygwin; then\n  [ -n \"$JAVA_HOME\" ] \\\n    && JAVA_HOME=$(cygpath --unix \"$JAVA_HOME\")\n  [ -n \"$CLASSPATH\" ] \\\n    && CLASSPATH=$(cygpath --path --unix \"$CLASSPATH\")\nfi\n\n# For Mingw, ensure paths are in UNIX format before anything is touched\nif $mingw; then\n  [ -n \"$JAVA_HOME\" ] && [ -d \"$JAVA_HOME\" ] \\\n    && JAVA_HOME=\"$(\n      cd \"$JAVA_HOME\" || (\n        echo \"cannot cd into $JAVA_HOME.\" >&2\n        exit 1\n      )\n      pwd\n    )\"\nfi\n\nif [ -z \"$JAVA_HOME\" ]; then\n  javaExecutable=\"$(which javac)\"\n  if [ -n \"$javaExecutable\" ] && ! [ \"$(expr \"$javaExecutable\" : '\\([^ ]*\\)')\" = \"no\" ]; then\n    # readlink(1) is not available as standard on Solaris 10.\n    readLink=$(which readlink)\n    if [ ! \"$(expr \"$readLink\" : '\\([^ ]*\\)')\" = \"no\" ]; then\n      if $darwin; then\n        javaHome=\"$(dirname \"$javaExecutable\")\"\n        javaExecutable=\"$(cd \"$javaHome\" && pwd -P)/javac\"\n      else\n        javaExecutable=\"$(readlink -f \"$javaExecutable\")\"\n      fi\n      javaHome=\"$(dirname \"$javaExecutable\")\"\n      javaHome=$(expr \"$javaHome\" : '\\(.*\\)/bin')\n      JAVA_HOME=\"$javaHome\"\n      export JAVA_HOME\n    fi\n  fi\nfi\n\nif [ -z \"$JAVACMD\" ]; then\n  if [ -n \"$JAVA_HOME\" ]; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ]; then\n      # IBM's JDK on AIX uses strange locations for the executables\n      JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n      JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n  else\n    JAVACMD=\"$(\n      \\unset -f command 2>/dev/null\n      \\command -v java\n    )\"\n  fi\nfi\n\nif [ ! -x \"$JAVACMD\" ]; then\n  echo \"Error: JAVA_HOME is not defined correctly.\" >&2\n  echo \"  We cannot execute $JAVACMD\" >&2\n  exit 1\nfi\n\nif [ -z \"$JAVA_HOME\" ]; then\n  echo \"Warning: JAVA_HOME environment variable is not set.\" >&2\nfi\n\n# traverses directory structure from process work directory to filesystem root\n# first directory with .mvn subdirectory is considered project base directory\nfind_maven_basedir() {\n  if [ -z \"$1\" ]; then\n    echo \"Path not specified to find_maven_basedir\" >&2\n    return 1\n  fi\n\n  basedir=\"$1\"\n  wdir=\"$1\"\n  while [ \"$wdir\" != '/' ]; do\n    if [ -d \"$wdir\"/.mvn ]; then\n      basedir=$wdir\n      break\n    fi\n    # workaround for JBEAP-8937 (on Solaris 10/Sparc)\n    if [ -d \"${wdir}\" ]; then\n      wdir=$(\n        cd \"$wdir/..\" || exit 1\n        pwd\n      )\n    fi\n    # end of workaround\n  done\n  printf '%s' \"$(\n    cd \"$basedir\" || exit 1\n    pwd\n  )\"\n}\n\n# concatenates all lines of a file\nconcat_lines() {\n  if [ -f \"$1\" ]; then\n    # Remove \\r in case we run on Windows within Git Bash\n    # and check out the repository with auto CRLF management\n    # enabled. Otherwise, we may read lines that are delimited with\n    # \\r\\n and produce $'-Xarg\\r' rather than -Xarg due to word\n    # splitting rules.\n    tr -s '\\r\\n' ' ' <\"$1\"\n  fi\n}\n\nlog() {\n  if [ \"$MVNW_VERBOSE\" = true ]; then\n    printf '%s\\n' \"$1\"\n  fi\n}\n\nBASE_DIR=$(find_maven_basedir \"$(dirname \"$0\")\")\nif [ -z \"$BASE_DIR\" ]; then\n  exit 1\nfi\n\nMAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-\"$BASE_DIR\"}\nexport MAVEN_PROJECTBASEDIR\nlog \"$MAVEN_PROJECTBASEDIR\"\n\ntrim() {\n  # MWRAPPER-139:\n  #   Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.\n  #   Needed for removing poorly interpreted newline sequences when running in more\n  #   exotic environments such as mingw bash on Windows.\n  printf \"%s\" \"${1}\" | tr -d '[:space:]'\n}\n\n##########################################################################################\n# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central\n# This allows using the maven wrapper in projects that prohibit checking in binary data.\n##########################################################################################\nwrapperJarPath=\"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar\"\nif [ -r \"$wrapperJarPath\" ]; then\n  log \"Found $wrapperJarPath\"\nelse\n  log \"Couldn't find $wrapperJarPath, downloading it ...\"\n\n  if [ -n \"$MVNW_REPOURL\" ]; then\n    wrapperUrl=\"$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar\"\n  else\n    wrapperUrl=\"https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar\"\n  fi\n  while IFS=\"=\" read -r key value; do\n    case \"$key\" in wrapperUrl)\n      wrapperUrl=$(trim \"${value-}\")\n      break\n      ;;\n    esac\n  done <\"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties\"\n  log \"Downloading from: $wrapperUrl\"\n\n  if $cygwin; then\n    wrapperJarPath=$(cygpath --path --windows \"$wrapperJarPath\")\n  fi\n\n  if command -v wget >/dev/null; then\n    log \"Found wget ... using wget\"\n    [ \"$MVNW_VERBOSE\" = true ] && QUIET=\"\" || QUIET=\"--quiet\"\n    if [ -z \"$MVNW_USERNAME\" ] || [ -z \"$MVNW_PASSWORD\" ]; then\n      wget ${QUIET:+\"$QUIET\"} \"$wrapperUrl\" -O \"$wrapperJarPath\" || rm -f \"$wrapperJarPath\"\n    else\n      wget ${QUIET:+\"$QUIET\"} --http-user=\"$MVNW_USERNAME\" --http-password=\"$MVNW_PASSWORD\" \"$wrapperUrl\" -O \"$wrapperJarPath\" || rm -f \"$wrapperJarPath\"\n    fi\n  elif command -v curl >/dev/null; then\n    log \"Found curl ... using curl\"\n    [ \"$MVNW_VERBOSE\" = true ] && QUIET=\"\" || QUIET=\"--silent\"\n    if [ -z \"$MVNW_USERNAME\" ] || [ -z \"$MVNW_PASSWORD\" ]; then\n      curl ${QUIET:+\"$QUIET\"} -o \"$wrapperJarPath\" \"$wrapperUrl\" -f -L || rm -f \"$wrapperJarPath\"\n    else\n      curl ${QUIET:+\"$QUIET\"} --user \"$MVNW_USERNAME:$MVNW_PASSWORD\" -o \"$wrapperJarPath\" \"$wrapperUrl\" -f -L || rm -f \"$wrapperJarPath\"\n    fi\n  else\n    log \"Falling back to using Java to download\"\n    javaSource=\"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java\"\n    javaClass=\"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class\"\n    # For Cygwin, switch paths to Windows format before running javac\n    if $cygwin; then\n      javaSource=$(cygpath --path --windows \"$javaSource\")\n      javaClass=$(cygpath --path --windows \"$javaClass\")\n    fi\n    if [ -e \"$javaSource\" ]; then\n      if [ ! -e \"$javaClass\" ]; then\n        log \" - Compiling MavenWrapperDownloader.java ...\"\n        (\"$JAVA_HOME/bin/javac\" \"$javaSource\")\n      fi\n      if [ -e \"$javaClass\" ]; then\n        log \" - Running MavenWrapperDownloader.java ...\"\n        (\"$JAVA_HOME/bin/java\" -cp .mvn/wrapper MavenWrapperDownloader \"$wrapperUrl\" \"$wrapperJarPath\") || rm -f \"$wrapperJarPath\"\n      fi\n    fi\n  fi\nfi\n##########################################################################################\n# End of extension\n##########################################################################################\n\n# If specified, validate the SHA-256 sum of the Maven wrapper jar file\nwrapperSha256Sum=\"\"\nwhile IFS=\"=\" read -r key value; do\n  case \"$key\" in wrapperSha256Sum)\n    wrapperSha256Sum=$(trim \"${value-}\")\n    break\n    ;;\n  esac\ndone <\"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties\"\nif [ -n \"$wrapperSha256Sum\" ]; then\n  wrapperSha256Result=false\n  if command -v sha256sum >/dev/null; then\n    if echo \"$wrapperSha256Sum  $wrapperJarPath\" | sha256sum -c - >/dev/null 2>&1; then\n      wrapperSha256Result=true\n    fi\n  elif command -v shasum >/dev/null; then\n    if echo \"$wrapperSha256Sum  $wrapperJarPath\" | shasum -a 256 -c >/dev/null 2>&1; then\n      wrapperSha256Result=true\n    fi\n  else\n    echo \"Checksum validation was requested but neither 'sha256sum' or 'shasum' are available.\" >&2\n    echo \"Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties.\" >&2\n    exit 1\n  fi\n  if [ $wrapperSha256Result = false ]; then\n    echo \"Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.\" >&2\n    echo \"Investigate or delete $wrapperJarPath to attempt a clean download.\" >&2\n    echo \"If you updated your Maven version, you need to update the specified wrapperSha256Sum property.\" >&2\n    exit 1\n  fi\nfi\n\nMAVEN_OPTS=\"$(concat_lines \"$MAVEN_PROJECTBASEDIR/.mvn/jvm.config\") $MAVEN_OPTS\"\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin; then\n  [ -n \"$JAVA_HOME\" ] \\\n    && JAVA_HOME=$(cygpath --path --windows \"$JAVA_HOME\")\n  [ -n \"$CLASSPATH\" ] \\\n    && CLASSPATH=$(cygpath --path --windows \"$CLASSPATH\")\n  [ -n \"$MAVEN_PROJECTBASEDIR\" ] \\\n    && MAVEN_PROJECTBASEDIR=$(cygpath --path --windows \"$MAVEN_PROJECTBASEDIR\")\nfi\n\n# Provide a \"standardized\" way to retrieve the CLI args that will\n# work with both Windows and non-Windows executions.\nMAVEN_CMD_LINE_ARGS=\"$MAVEN_CONFIG $*\"\nexport MAVEN_CMD_LINE_ARGS\n\nWRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain\n\n# shellcheck disable=SC2086 # safe args\nexec \"$JAVACMD\" \\\n  $MAVEN_OPTS \\\n  $MAVEN_DEBUG_OPTS \\\n  -classpath \"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar\" \\\n  \"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}\" \\\n  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG \"$@\"\n"
  },
  {
    "path": "mvnw.cmd",
    "content": "@REM ----------------------------------------------------------------------------\r\n@REM Licensed to the Apache Software Foundation (ASF) under one\r\n@REM or more contributor license agreements.  See the NOTICE file\r\n@REM distributed with this work for additional information\r\n@REM regarding copyright ownership.  The ASF licenses this file\r\n@REM to you under the Apache License, Version 2.0 (the\r\n@REM \"License\"); you may not use this file except in compliance\r\n@REM with the License.  You may obtain a copy of the License at\r\n@REM\r\n@REM    http://www.apache.org/licenses/LICENSE-2.0\r\n@REM\r\n@REM Unless required by applicable law or agreed to in writing,\r\n@REM software distributed under the License is distributed on an\r\n@REM \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\n@REM KIND, either express or implied.  See the License for the\r\n@REM specific language governing permissions and limitations\r\n@REM under the License.\r\n@REM ----------------------------------------------------------------------------\r\n\r\n@REM ----------------------------------------------------------------------------\r\n@REM Apache Maven Wrapper startup batch script, version 3.3.4\r\n@REM\r\n@REM Required ENV vars:\r\n@REM JAVA_HOME - location of a JDK home dir\r\n@REM\r\n@REM Optional ENV vars\r\n@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands\r\n@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending\r\n@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven\r\n@REM     e.g. to debug Maven itself, use\r\n@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000\r\n@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files\r\n@REM ----------------------------------------------------------------------------\r\n\r\n@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'\r\n@echo off\r\n@REM set title of command window\r\ntitle %0\r\n@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'\r\n@if \"%MAVEN_BATCH_ECHO%\" == \"on\"  echo %MAVEN_BATCH_ECHO%\r\n\r\n@REM set %HOME% to equivalent of $HOME\r\nif \"%HOME%\" == \"\" (set \"HOME=%HOMEDRIVE%%HOMEPATH%\")\r\n\r\n@REM Execute a user defined script before this one\r\nif not \"%MAVEN_SKIP_RC%\" == \"\" goto skipRcPre\r\n@REM check for pre script, once with legacy .bat ending and once with .cmd ending\r\nif exist \"%USERPROFILE%\\mavenrc_pre.bat\" call \"%USERPROFILE%\\mavenrc_pre.bat\" %*\r\nif exist \"%USERPROFILE%\\mavenrc_pre.cmd\" call \"%USERPROFILE%\\mavenrc_pre.cmd\" %*\r\n:skipRcPre\r\n\r\n@setlocal\r\n\r\nset ERROR_CODE=0\r\n\r\n@REM To isolate internal variables from possible post scripts, we use another setlocal\r\n@setlocal\r\n\r\n@REM ==== START VALIDATION ====\r\nif not \"%JAVA_HOME%\" == \"\" goto OkJHome\r\n\r\necho. >&2\r\necho Error: JAVA_HOME not found in your environment. >&2\r\necho Please set the JAVA_HOME variable in your environment to match the >&2\r\necho location of your Java installation. >&2\r\necho. >&2\r\ngoto error\r\n\r\n:OkJHome\r\nif exist \"%JAVA_HOME%\\bin\\java.exe\" goto init\r\n\r\necho. >&2\r\necho Error: JAVA_HOME is set to an invalid directory. >&2\r\necho JAVA_HOME = \"%JAVA_HOME%\" >&2\r\necho Please set the JAVA_HOME variable in your environment to match the >&2\r\necho location of your Java installation. >&2\r\necho. >&2\r\ngoto error\r\n\r\n@REM ==== END VALIDATION ====\r\n\r\n:init\r\n\r\n@REM Find the project base dir, i.e. the directory that contains the folder \".mvn\".\r\n@REM Fallback to current working directory if not found.\r\n\r\nset MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%\r\nIF NOT \"%MAVEN_PROJECTBASEDIR%\"==\"\" goto endDetectBaseDir\r\n\r\nset EXEC_DIR=%CD%\r\nset WDIR=%EXEC_DIR%\r\n:findBaseDir\r\nIF EXIST \"%WDIR%\"\\.mvn goto baseDirFound\r\ncd ..\r\nIF \"%WDIR%\"==\"%CD%\" goto baseDirNotFound\r\nset WDIR=%CD%\r\ngoto findBaseDir\r\n\r\n:baseDirFound\r\nset MAVEN_PROJECTBASEDIR=%WDIR%\r\ncd \"%EXEC_DIR%\"\r\ngoto endDetectBaseDir\r\n\r\n:baseDirNotFound\r\nset MAVEN_PROJECTBASEDIR=%EXEC_DIR%\r\ncd \"%EXEC_DIR%\"\r\n\r\n:endDetectBaseDir\r\n\r\nIF NOT EXIST \"%MAVEN_PROJECTBASEDIR%\\.mvn\\jvm.config\" goto endReadAdditionalConfig\r\n\r\n@setlocal EnableExtensions EnableDelayedExpansion\r\nfor /F \"usebackq delims=\" %%a in (\"%MAVEN_PROJECTBASEDIR%\\.mvn\\jvm.config\") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a\r\n@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%\r\n\r\n:endReadAdditionalConfig\r\n\r\nSET MAVEN_JAVA_EXE=\"%JAVA_HOME%\\bin\\java.exe\"\r\nset WRAPPER_JAR=\"%MAVEN_PROJECTBASEDIR%\\.mvn\\wrapper\\maven-wrapper.jar\"\r\nset WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain\r\n\r\nset WRAPPER_URL=\"https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar\"\r\n\r\nFOR /F \"usebackq tokens=1,2 delims==\" %%A IN (\"%MAVEN_PROJECTBASEDIR%\\.mvn\\wrapper\\maven-wrapper.properties\") DO (\r\n    IF \"%%A\"==\"wrapperUrl\" SET WRAPPER_URL=%%B\r\n)\r\n\r\n@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central\r\n@REM This allows using the maven wrapper in projects that prohibit checking in binary data.\r\nif exist %WRAPPER_JAR% (\r\n    if \"%MVNW_VERBOSE%\" == \"true\" (\r\n        echo Found %WRAPPER_JAR%\r\n    )\r\n) else (\r\n    if not \"%MVNW_REPOURL%\" == \"\" (\r\n        SET WRAPPER_URL=\"%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar\"\r\n    )\r\n    if \"%MVNW_VERBOSE%\" == \"true\" (\r\n        echo Couldn't find %WRAPPER_JAR%, downloading it ...\r\n        echo Downloading from: %WRAPPER_URL%\r\n    )\r\n\r\n    powershell -Command \"&{\"^\r\n\t\t\"$webclient = new-object System.Net.WebClient;\"^\r\n\t\t\"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {\"^\r\n\t\t\"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');\"^\r\n\t\t\"}\"^\r\n\t\t\"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')\"^\r\n\t\t\"}\"\r\n    if \"%MVNW_VERBOSE%\" == \"true\" (\r\n        echo Finished downloading %WRAPPER_JAR%\r\n    )\r\n)\r\n@REM End of extension\r\n\r\n@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file\r\nSET WRAPPER_SHA_256_SUM=\"\"\r\nFOR /F \"usebackq tokens=1,2 delims==\" %%A IN (\"%MAVEN_PROJECTBASEDIR%\\.mvn\\wrapper\\maven-wrapper.properties\") DO (\r\n    IF \"%%A\"==\"wrapperSha256Sum\" SET WRAPPER_SHA_256_SUM=%%B\r\n)\r\nIF NOT %WRAPPER_SHA_256_SUM%==\"\" (\r\n    powershell -Command \"&{\"^\r\n       \"Import-Module $PSHOME\\Modules\\Microsoft.PowerShell.Utility -Function Get-FileHash;\"^\r\n       \"$hash = (Get-FileHash \\\"%WRAPPER_JAR%\\\" -Algorithm SHA256).Hash.ToLower();\"^\r\n       \"If('%WRAPPER_SHA_256_SUM%' -ne $hash){\"^\r\n       \"  Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';\"^\r\n       \"  Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';\"^\r\n       \"  Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';\"^\r\n       \"  exit 1;\"^\r\n       \"}\"^\r\n       \"}\"\r\n    if ERRORLEVEL 1 goto error\r\n)\r\n\r\n@REM Provide a \"standardized\" way to retrieve the CLI args that will\r\n@REM work with both Windows and non-Windows executions.\r\nset MAVEN_CMD_LINE_ARGS=%*\r\n\r\n%MAVEN_JAVA_EXE% ^\r\n  %JVM_CONFIG_MAVEN_PROPS% ^\r\n  %MAVEN_OPTS% ^\r\n  %MAVEN_DEBUG_OPTS% ^\r\n  -classpath %WRAPPER_JAR% ^\r\n  \"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%\" ^\r\n  %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*\r\nif ERRORLEVEL 1 goto error\r\ngoto end\r\n\r\n:error\r\nset ERROR_CODE=1\r\n\r\n:end\r\n@endlocal & set ERROR_CODE=%ERROR_CODE%\r\n\r\nif not \"%MAVEN_SKIP_RC%\"==\"\" goto skipRcPost\r\n@REM check for post script, once with legacy .bat ending and once with .cmd ending\r\nif exist \"%USERPROFILE%\\mavenrc_post.bat\" call \"%USERPROFILE%\\mavenrc_post.bat\"\r\nif exist \"%USERPROFILE%\\mavenrc_post.cmd\" call \"%USERPROFILE%\\mavenrc_post.cmd\"\r\n:skipRcPost\r\n\r\n@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'\r\nif \"%MAVEN_BATCH_PAUSE%\"==\"on\" pause\r\n\r\nif \"%MAVEN_TERMINATE_CMD%\"==\"on\" exit %ERROR_CODE%\r\n\r\ncmd /C exit /B %ERROR_CODE%\r\n"
  },
  {
    "path": "neo4j-cypher-dsl/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-parent</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl</artifactId>\n\n\t<name>Neo4j Cypher DSL (Core)</name>\n\t<description>The core module of the Cypher DSL, including all supported elements and the default renderer.</description>\n\n\t<properties>\n\t\t<sonar.coverage.jacoco.xmlReportPaths>${basedir}/../${aggregate.report.dir}</sonar.coverage.jacoco.xmlReportPaths>\n\t</properties>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-dsl-bom</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.apiguardian</groupId>\n\t\t\t<artifactId>apiguardian-api</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl-schema-name-support</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.querydsl</groupId>\n\t\t\t<artifactId>querydsl-core</artifactId>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl-build-annotations</artifactId>\n\t\t\t<version>${project.version}</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<!--\n\t\t\tQueryDSL proxy feature requires cglib. It's gonna be a pain in the future, I guess, quoting from cglibs GitHub:\n\n\t\t\t\"IMPORTANT NOTE: cglib is unmaintained and does not work well (or possibly at all?) in newer JDKs, particularly JDK17+.\n\t\t\tIf you need to support newer JDKs, we will accept well-tested well-thought-out patches...\n\t\t\tbut you'll probably have better luck migrating to something like ByteBuddy\"\n\t\t\t-->\n\t\t\t<groupId>cglib</groupId>\n\t\t\t<artifactId>cglib</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.tngtech.archunit</groupId>\n\t\t\t<artifactId>archunit</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.assertj</groupId>\n\t\t\t<artifactId>assertj-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.mockito</groupId>\n\t\t\t<artifactId>mockito-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-simple</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.codehaus.mojo</groupId>\n\t\t\t\t<artifactId>exec-maven-plugin</artifactId>\n\t\t\t\t<version>${exec-maven-plugin.version}</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>remove-shaded-modules</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>exec</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>generate-sources</phase>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<executable>bin/remove-shaded-modules.sh</executable>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<!-- Configuration for surefire added because the stuff is not able to deal with the optional required module and in turn, JUnit 5 falls over during test discovering -->\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<!-- -add-opens java.base/java.lang=ALL-UNNAMED added for QueryDSL proxy mechanics based on ages old cglib -->\n\t\t\t\t\t<argLine>@{argLine} -Xverify:all\n\t\t\t\t\t\t--add-modules com.querydsl.core\n\t\t\t\t\t\t--add-reads org.neo4j.cypherdsl.core=com.querydsl.core\n\t\t\t\t\t\t--add-opens java.base/java.lang=ALL-UNNAMED</argLine>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>default-compile</id>\n\t\t\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t\t\t<compilerArgs>\n\t\t\t\t\t\t\t\t<arg>-Aorg.neo4j.cypherdsl.build.native_config_dir=${project.groupId}/${project.artifactId}</arg>\n\t\t\t\t\t\t\t\t<arg>-Xlint:all,-options,-path,-processing,-exports</arg>\n\t\t\t\t\t\t\t\t<arg>-Werror</arg>\n\t\t\t\t\t\t\t</compilerArgs>\n\t\t\t\t\t\t\t<annotationProcessorPaths>\n\t\t\t\t\t\t\t\t<annotationProcessorPath>\n\t\t\t\t\t\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t\t\t\t\t\t<artifactId>neo4j-cypher-dsl-build-proc</artifactId>\n\t\t\t\t\t\t\t\t\t<version>${project.version}</version>\n\t\t\t\t\t\t\t\t</annotationProcessorPath>\n\t\t\t\t\t\t\t</annotationProcessorPaths>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>default-testCompile</id>\n\t\t\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t\t\t<compilerArgs>\n\t\t\t\t\t\t\t\t<arg>-Aquerydsl.generatedAnnotationClass=com.querydsl.core.annotations.Generated</arg>\n\t\t\t\t\t\t\t\t<arg>-Xlint:all,-options,-path,-processing,-exports,-missing-explicit-ctor,-classfile</arg>\n\t\t\t\t\t\t\t\t<arg>-Werror</arg>\n\t\t\t\t\t\t\t\t<!-- Added because QueryDSL drags in Jetbrains annotation which we won't add explicitly. Goes together with -classfile. -->\n\t\t\t\t\t\t\t\t<arg>-implicit:class</arg>\n\t\t\t\t\t\t\t</compilerArgs>\n\t\t\t\t\t\t\t<annotationProcessorPaths>\n\t\t\t\t\t\t\t\t<annotationProcessorPath>\n\t\t\t\t\t\t\t\t\t<groupId>com.querydsl</groupId>\n\t\t\t\t\t\t\t\t\t<artifactId>querydsl-apt</artifactId>\n\t\t\t\t\t\t\t\t\t<version>${querydsl.version}</version>\n\t\t\t\t\t\t\t\t\t<classifier>general</classifier>\n\t\t\t\t\t\t\t\t</annotationProcessorPath>\n\t\t\t\t\t\t\t\t<annotationProcessorPath>\n\t\t\t\t\t\t\t\t\t<groupId>javax.annotation</groupId>\n\t\t\t\t\t\t\t\t\t<artifactId>javax.annotation-api</artifactId>\n\t\t\t\t\t\t\t\t\t<version>${javax.annotation-api.version}</version>\n\t\t\t\t\t\t\t\t</annotationProcessorPath>\n\t\t\t\t\t\t\t</annotationProcessorPaths>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-shade-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>shade</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<artifactSet>\n\t\t\t\t\t\t\t\t<includes>\n\t\t\t\t\t\t\t\t\t<include>org.neo4j:neo4j-cypher-dsl-schema-name-support</include>\n\t\t\t\t\t\t\t\t</includes>\n\t\t\t\t\t\t\t</artifactSet>\n\t\t\t\t\t\t\t<relocations>\n\t\t\t\t\t\t\t\t<relocation>\n\t\t\t\t\t\t\t\t\t<pattern>org.neo4j.cypherdsl.support.schema_name</pattern>\n\t\t\t\t\t\t\t\t\t<shadedPattern>org.neo4j.cypherdsl.core.internal</shadedPattern>\n\t\t\t\t\t\t\t\t</relocation>\n\t\t\t\t\t\t\t</relocations>\n\t\t\t\t\t\t\t<createSourcesJar>true</createSourcesJar>\n\t\t\t\t\t\t\t<filters>\n\t\t\t\t\t\t\t\t<filter>\n\t\t\t\t\t\t\t\t\t<artifact>org.neo4j:neo4j-cypher-dsl-schema-name-support</artifact>\n\t\t\t\t\t\t\t\t\t<includes>\n\t\t\t\t\t\t\t\t\t\t<include>**/SchemaNames*class</include>\n\t\t\t\t\t\t\t\t\t</includes>\n\t\t\t\t\t\t\t\t\t<excludes>\n\t\t\t\t\t\t\t\t\t\t<exclude>module-info.class</exclude>\n\t\t\t\t\t\t\t\t\t</excludes>\n\t\t\t\t\t\t\t\t</filter>\n\t\t\t\t\t\t\t</filters>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.moditect</groupId>\n\t\t\t\t<artifactId>moditect-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>add-module-infos</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>add-module-info</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<overwriteExistingFiles>true</overwriteExistingFiles>\n\t\t\t\t\t\t\t<module>\n\t\t\t\t\t\t\t\t<moduleInfoFile>${project.build.directory}/modules/module-info.java</moduleInfoFile>\n\t\t\t\t\t\t\t</module>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.github.siom79.japicmp</groupId>\n\t\t\t\t<artifactId>japicmp-maven-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<parameter>\n\t\t\t\t\t\t<ignoreMissingClassesByRegularExpressions>\n\t\t\t\t\t\t\t<ignoreMissingClassesByRegularExpression>com\\.querydsl\\.core\\..*</ignoreMissingClassesByRegularExpression>\n\t\t\t\t\t\t\t<ignoreMissingClassesByRegularExpression>org\\.neo4j\\.cypherdsl\\.core\\.internal\\.LiteralBase</ignoreMissingClassesByRegularExpression>\n\t\t\t\t\t\t\t<ignoreMissingClassesByRegularExpression>org\\.neo4j\\.cypherdsl\\.core\\.internal\\.StatementContext</ignoreMissingClassesByRegularExpression>\n\t\t\t\t\t\t</ignoreMissingClassesByRegularExpressions>\n\t\t\t\t\t</parameter>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/module-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * @author Michael J. Simons\n * @since 2023.0.0\n */\n@SuppressWarnings({\"requires-automatic\", \"requires-transitive-automatic\"})\nmodule org.neo4j.cypherdsl.core {\n\n\trequires static com.querydsl.core;\n\trequires static java.sql;\n\trequires static org.neo4j.cypherdsl.build.annotations;\n\n\trequires transitive org.apiguardian.api;\n\trequires org.neo4j.cypherdsl.support.schema_name;\n\n\texports org.neo4j.cypherdsl.core;\n\texports org.neo4j.cypherdsl.core.ast;\n\texports org.neo4j.cypherdsl.core.renderer;\n\texports org.neo4j.cypherdsl.core.annotations;\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/AbstractCase.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Optional;\n\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.CaseElse;\nimport org.neo4j.cypherdsl.core.internal.CaseWhenThen;\n\n/**\n * Abstract base class for a {@link Case}.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n * @since 2021.2.3\n */\nabstract class AbstractCase implements Case {\n\n\tprivate final List<CaseWhenThen> caseWhenThens;\n\n\tprivate CaseElse caseElse;\n\n\tprivate Optional<String> prefix = Optional.empty();\n\n\tprivate Optional<String> suffix = Optional.empty();\n\n\tAbstractCase(List<CaseWhenThen> caseWhenThens) {\n\t\tthis.caseWhenThens = new ArrayList<>(caseWhenThens);\n\t}\n\n\tabstract Expression getCaseExpression();\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n\tvoid setCaseElse(CaseElse caseElse) {\n\t\tthis.caseElse = caseElse;\n\t}\n\n\t/**\n\t * Creates a new case/when expression with an additional {@code WHEN} block.\n\t * @param nextExpression the next expression to use.\n\t * @return an ongoing when builder.\n\t */\n\t@Override\n\t@CheckReturnValue\n\tpublic OngoingWhenThen when(Expression nextExpression) {\n\n\t\treturn new DefaultOngoingWhenThen(nextExpression);\n\t}\n\n\t@Override\n\tpublic Optional<String> getPrefix() {\n\t\treturn this.prefix;\n\t}\n\n\t@Override\n\tpublic Optional<String> getSuffix() {\n\t\treturn this.suffix;\n\t}\n\n\t@Override\n\tpublic Property property(String... names) {\n\n\t\tthis.prefix = Optional.of(\"(\");\n\t\tthis.suffix = Optional.of(\")\");\n\t\treturn Case.super.property(names);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tif (getCaseExpression() != null) {\n\t\t\tgetCaseExpression().accept(visitor);\n\t\t}\n\n\t\tthis.caseWhenThens.forEach(caseWhenThen -> caseWhenThen.accept(visitor));\n\n\t\tif (this.caseElse != null) {\n\t\t\tthis.caseElse.accept(visitor);\n\t\t}\n\n\t\tvisitor.leave(this);\n\t}\n\n\tstatic class SimpleCaseImpl extends AbstractCase implements SimpleCase {\n\n\t\tprivate final Expression caseExpression;\n\n\t\tSimpleCaseImpl(Expression caseExpression) {\n\t\t\tthis(caseExpression, Collections.emptyList());\n\t\t}\n\n\t\tSimpleCaseImpl(Expression caseExpression, List<CaseWhenThen> caseWhenThens) {\n\t\t\tsuper(caseWhenThens);\n\t\t\tthis.caseExpression = caseExpression;\n\t\t}\n\n\t\t@Override\n\t\tExpression getCaseExpression() {\n\t\t\treturn this.caseExpression;\n\t\t}\n\n\t\t/**\n\t\t * The renderable implementation of {@link SimpleCase}.\n\t\t */\n\t\tstatic final class EndingSimpleCase extends SimpleCaseImpl implements CaseEnding {\n\n\t\t\tprivate EndingSimpleCase(Expression caseExpression, List<CaseWhenThen> caseWhenThens) {\n\t\t\t\tsuper(caseExpression, caseWhenThens);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic Case elseDefault(Expression defaultExpression) {\n\t\t\t\tthis.setCaseElse(new CaseElse(defaultExpression));\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tstatic class GenericCaseImpl extends AbstractCase implements GenericCase {\n\n\t\tGenericCaseImpl() {\n\t\t\tthis(Collections.emptyList());\n\t\t}\n\n\t\tGenericCaseImpl(List<CaseWhenThen> caseWhenThens) {\n\t\t\tsuper(caseWhenThens);\n\t\t}\n\n\t\t@Override\n\t\tExpression getCaseExpression() {\n\t\t\treturn null;\n\t\t}\n\n\t\t/**\n\t\t * The renderable implementation of {@link GenericCase}.\n\t\t */\n\t\tstatic final class EndingGenericCase extends GenericCaseImpl implements CaseEnding {\n\n\t\t\tprivate EndingGenericCase(List<CaseWhenThen> caseWhenThens) {\n\t\t\t\tsuper(caseWhenThens);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic Case elseDefault(Expression defaultExpression) {\n\t\t\t\tthis.setCaseElse(new CaseElse(defaultExpression));\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tprivate final class DefaultOngoingWhenThen implements OngoingWhenThen {\n\n\t\tfinal Expression whenExpression;\n\n\t\tprivate DefaultOngoingWhenThen(Expression whenExpression) {\n\t\t\tthis.whenExpression = whenExpression;\n\t\t}\n\n\t\t/**\n\t\t * Ends this {@code WHEN} block with an expression.\n\t\t * @param expression the expression for the ongoing {@code WHEN} block.\n\t\t * @return an ongoing when builder.\n\t\t */\n\t\t@Override\n\t\t@CheckReturnValue\n\t\tpublic CaseEnding then(Expression expression) {\n\n\t\t\tCaseWhenThen caseWhenThen = new CaseWhenThen(this.whenExpression, expression);\n\t\t\tAbstractCase.this.caseWhenThens.add(caseWhenThen);\n\t\t\tif (getCaseExpression() != null) {\n\t\t\t\treturn new SimpleCaseImpl.EndingSimpleCase(AbstractCase.this.getCaseExpression(),\n\t\t\t\t\t\tAbstractCase.this.caseWhenThens);\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn new GenericCaseImpl.EndingGenericCase(AbstractCase.this.caseWhenThens);\n\t\t\t}\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/AbstractClause.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nabstract class AbstractClause implements Clause {\n\n\t@Override\n\tpublic final String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/AbstractNode.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Abstract base class for the {@link NodeBase node implementation} to avoid default\n * interface methods to be overridable in inheritors.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\nabstract class AbstractNode extends AbstractPropertyContainer implements Node {\n\n\t@Deprecated(forRemoval = true)\n\t@Override\n\t@SuppressWarnings(\"removal\")\n\tpublic final Condition hasLabels(LabelExpression labels) {\n\t\treturn hasLabels(Labels.of(labels));\n\t}\n\n\t@Override\n\tpublic final Condition hasLabels(String... labelsToQuery) {\n\t\treturn HasLabelCondition.create(\n\t\t\t\tthis.getSymbolicName()\n\t\t\t\t\t.orElseThrow(() -> new IllegalStateException(\"Cannot query a node without a symbolic name.\")),\n\t\t\t\tlabelsToQuery);\n\t}\n\n\t@Override\n\tpublic final Condition hasLabels(Labels labels) {\n\t\treturn HasLabelCondition.create(\n\t\t\t\tthis.getSymbolicName()\n\t\t\t\t\t.orElseThrow(() -> new IllegalStateException(\"Cannot query a node without a symbolic name.\")),\n\t\t\t\tlabels);\n\t}\n\n\t@Override\n\tpublic final Condition isEqualTo(Node otherNode) {\n\n\t\treturn this.getRequiredSymbolicName().isEqualTo(otherNode.getRequiredSymbolicName());\n\t}\n\n\t@Override\n\tpublic final Condition isNotEqualTo(Node otherNode) {\n\n\t\treturn this.getRequiredSymbolicName().isNotEqualTo(otherNode.getRequiredSymbolicName());\n\t}\n\n\t@Override\n\tpublic final Condition isNull() {\n\n\t\treturn this.getRequiredSymbolicName().isNull();\n\t}\n\n\t@Override\n\tpublic final Condition isNotNull() {\n\n\t\treturn this.getRequiredSymbolicName().isNotNull();\n\t}\n\n\t@Override\n\tpublic final SortItem descending() {\n\n\t\treturn this.getRequiredSymbolicName().descending();\n\t}\n\n\t@Override\n\tpublic final SortItem ascending() {\n\n\t\treturn this.getRequiredSymbolicName().ascending();\n\t}\n\n\t@Override\n\tpublic final AliasedExpression as(String alias) {\n\n\t\treturn this.getRequiredSymbolicName().as(alias);\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"deprecation\") // IDEA is stupid.\n\tpublic final FunctionInvocation internalId() {\n\t\treturn Functions.id(this);\n\t}\n\n\t@Override\n\tpublic final FunctionInvocation labels() {\n\t\treturn Functions.labels(this);\n\t}\n\n\t@Override\n\tpublic final Relationship relationshipTo(Node other, String... types) {\n\t\treturn new InternalRelationshipImpl(null, this, Relationship.Direction.LTR, null, other, types);\n\t}\n\n\t@Override\n\tpublic final Relationship relationshipFrom(Node other, String... types) {\n\t\treturn new InternalRelationshipImpl(null, this, Relationship.Direction.RTL, null, other, types);\n\t}\n\n\t@Override\n\tpublic final Relationship relationshipBetween(Node other, String... types) {\n\t\treturn new InternalRelationshipImpl(null, this, Relationship.Direction.UNI, null, other, types);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/AbstractPropertyContainer.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Abstract base class for all property containers to avoid default interface methods to\n * be overridable in inheritors.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\nabstract class AbstractPropertyContainer implements PropertyContainer {\n\n\tstatic IllegalStateException noNameException() {\n\t\treturn new IllegalStateException(Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_REQUIRES_NAME_FOR_MUTATION));\n\t}\n\n\t@Override\n\tpublic final Property property(String name) {\n\t\treturn InternalPropertyImpl.create(this, name);\n\t}\n\n\t@Override\n\tpublic final Property property(String... names) {\n\t\treturn InternalPropertyImpl.create(this, names);\n\t}\n\n\t@Override\n\tpublic final Property property(Expression lookup) {\n\t\treturn InternalPropertyImpl.create(this, lookup);\n\t}\n\n\t@Override\n\tpublic final Operation mutate(Parameter<?> parameter) {\n\t\treturn Operations.mutate(this.getSymbolicName().orElseThrow(AbstractPropertyContainer::noNameException),\n\t\t\t\tparameter);\n\t}\n\n\t@Override\n\tpublic final Operation mutate(MapExpression properties) {\n\t\treturn Operations.mutate(this.getSymbolicName().orElseThrow(AbstractPropertyContainer::noNameException),\n\t\t\t\tproperties);\n\t}\n\n\t@Override\n\tpublic final Operation set(Parameter<?> parameter) {\n\t\treturn Operations.set(this.getSymbolicName().orElseThrow(AbstractPropertyContainer::noNameException),\n\t\t\t\tparameter);\n\t}\n\n\t@Override\n\tpublic final Operation set(MapExpression properties) {\n\t\treturn Operations.set(this.getSymbolicName().orElseThrow(AbstractPropertyContainer::noNameException),\n\t\t\t\tproperties);\n\t}\n\n\t@Override\n\tpublic final MapProjection project(List<Object> entries) {\n\t\treturn project(entries.toArray());\n\t}\n\n\t@Override\n\tpublic final MapProjection project(Object... entries) {\n\t\treturn getRequiredSymbolicName().project(entries);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/AbstractStatement.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.internal.DefaultStatementContext;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * The abstract statement provides possible state shared across various statement\n * implementations. Use cases are collecting bound parameter values, possible\n * configuration of the renderer and similar.\n *\n * @author Michael J. Simons\n * @author Andreas Berger\n * @since 2021.0.0\n */\n@API(status = INTERNAL, since = \"2021.0.0\")\nabstract class AbstractStatement implements Statement {\n\n\t/**\n\t * Provides context during visiting of this statement.\n\t */\n\tprivate final StatementContext context = new DefaultStatementContext();\n\n\t/**\n\t * A flag that indicates whether parameters coming from QueryDSL integration should be\n\t * rendered as Cypher {@link Literal literals} or as actual parameters.\n\t */\n\tprivate boolean renderConstantsAsParameters = false;\n\n\t/**\n\t * The rendered Cypher statement.\n\t */\n\tprivate volatile String cypher;\n\n\t/**\n\t * The catalog for this statement, will be lazily available and needs refreshment if\n\t * parameter rendering changes.\n\t */\n\t@SuppressWarnings(\"squid:S3077\")\n\tprivate volatile StatementCatalog statementCatalog;\n\n\t@Override\n\tpublic StatementContext getContext() {\n\t\treturn this.context;\n\t}\n\n\t@Override\n\tpublic synchronized boolean isRenderConstantsAsParameters() {\n\t\treturn this.renderConstantsAsParameters;\n\t}\n\n\t@Override\n\tpublic void setRenderConstantsAsParameters(boolean renderConstantsAsParameters) {\n\n\t\tsynchronized (this) {\n\t\t\tthis.renderConstantsAsParameters = renderConstantsAsParameters;\n\t\t\tthis.cypher = null;\n\t\t\tthis.statementCatalog = null;\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getCypher() {\n\n\t\tString result = this.cypher;\n\t\tif (result == null) {\n\t\t\tsynchronized (this) {\n\t\t\t\tresult = this.cypher;\n\t\t\t\tif (result == null) {\n\t\t\t\t\tthis.cypher = Renderer.getDefaultRenderer().render(this);\n\t\t\t\t\tresult = this.cypher;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic StatementCatalog getCatalog() {\n\n\t\tStatementCatalog result = this.statementCatalog;\n\t\tif (result == null) {\n\t\t\tsynchronized (this) {\n\t\t\t\tresult = this.statementCatalog;\n\t\t\t\tif (result == null) {\n\t\t\t\t\tthis.statementCatalog = getCatalog0();\n\t\t\t\t\tresult = this.statementCatalog;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate StatementCatalog getCatalog0() {\n\n\t\tvar catalogBuildingVisitor = new StatementCatalogBuildingVisitor(getContext(), isRenderConstantsAsParameters());\n\t\tthis.accept(catalogBuildingVisitor);\n\t\treturn catalogBuildingVisitor.getResult();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Aliased.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * An element with an alias. An alias has a subtle difference to a symbolic name in\n * cypher. Nodes and relationships can have symbolic names which in turn can be aliased as\n * well.\n * <p>\n * Therefore, the Cypher generator needs both {@code Named} and {@code Aliased}.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface Aliased {\n\n\t/**\n\t * {@return the alias}\n\t */\n\tString getAlias();\n\n\t/**\n\t * Turns this alias into a symbolic name that can be used as an {@link Expression}.\n\t * @return a new symbolic name\n\t */\n\tdefault SymbolicName asName() {\n\t\treturn SymbolicName.of(this.getAlias());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/AliasedExpression.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * An aliased expression, that deals with named expressions when accepting visitors.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class AliasedExpression implements Aliased, Expression, IdentifiableElement {\n\n\tprivate final Expression delegate;\n\n\tprivate final String alias;\n\n\tAliasedExpression(Expression delegate, String alias) {\n\n\t\tthis.delegate = delegate;\n\t\tthis.alias = alias;\n\t}\n\n\t@Override\n\tpublic String getAlias() {\n\t\treturn this.alias;\n\t}\n\n\t/**\n\t * This takes the originally aliased expression and re-aliases it. Aliases are not\n\t * nested.\n\t * @param newAlias the new alias to use\n\t * @return a new aliased, expression.\n\t */\n\t@Override\n\tpublic AliasedExpression as(String newAlias) {\n\n\t\tAssertions.hasText(newAlias, \"The alias may not be null or empty.\");\n\t\treturn new AliasedExpression(this.delegate, newAlias);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tExpressions.nameOrExpression(this.delegate).accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\tExpression getDelegate() {\n\t\treturn this.delegate;\n\t}\n\n\t@Override\n\tpublic Expression asExpression() {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Arguments.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Optional;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.ProvidesAffixes;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Specialized list of expressions that represents the arguments of a procedure call.\n *\n * @author Michael J. Simons\n * @since 2020.0.1\n */\n@API(status = INTERNAL, since = \"2020.0.1\")\nfinal class Arguments extends TypedSubtree<Expression> implements ProvidesAffixes {\n\n\tArguments(Expression... children) {\n\t\tsuper(children);\n\t}\n\n\t@Override\n\tprotected Visitable prepareVisit(Expression child) {\n\t\treturn Expressions.nameOrExpression(child);\n\t}\n\n\t@Override\n\tpublic Optional<String> getPrefix() {\n\t\treturn Optional.of(\"(\");\n\t}\n\n\t@Override\n\tpublic Optional<String> getSuffix() {\n\t\treturn Optional.of(\")\");\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Asterisk.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * The {@code *}.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Asterisk extends LiteralBase<String> implements IdentifiableElement {\n\n\t/**\n\t * The single instance of the {@code *}.\n\t */\n\tpublic static final Asterisk INSTANCE = new Asterisk();\n\n\tprivate Asterisk() {\n\t\tsuper(\"*\");\n\t}\n\n\t@Override\n\tpublic String asString() {\n\t\treturn this.content;\n\t}\n\n\t@Override\n\tpublic Expression asExpression() {\n\t\treturn this;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/BooleanFunctionCondition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * This wraps a function into a condition so that it can be used in a where clause. The\n * function is supposed to return a boolean value.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = INTERNAL, since = \"1.0\")\nfinal class BooleanFunctionCondition implements Condition {\n\n\tprivate final FunctionInvocation delegate;\n\n\tBooleanFunctionCondition(FunctionInvocation delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tthis.delegate.accept(visitor);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/BooleanLiteral.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * The boolean literal.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class BooleanLiteral extends LiteralBase<Boolean> {\n\n\tstatic final BooleanLiteral TRUE = new BooleanLiteral(true);\n\tstatic final BooleanLiteral FALSE = new BooleanLiteral(false);\n\n\tprivate BooleanLiteral(boolean content) {\n\t\tsuper(content);\n\t}\n\n\tstatic Literal<Boolean> of(Boolean value) {\n\n\t\tif (value != null && value) {\n\t\t\treturn TRUE;\n\t\t}\n\t\telse {\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\t@Override\n\tpublic String asString() {\n\t\treturn getContent().toString();\n\t}\n\n\t@Override\n\tpublic Boolean getContent() {\n\t\treturn this.content;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/BuiltInFunctions.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.apiguardian.api.API.Status;\nimport org.neo4j.cypherdsl.core.FunctionInvocation.FunctionDefinition;\n\n/**\n * A (non-exhaustive) list of builtin functions.\n *\n * @author Michael J. Simons\n * @since 2020.1.0\n */\n@API(status = Status.INTERNAL, since = \"2020.1.0\")\nfinal class BuiltInFunctions {\n\n\tprivate BuiltInFunctions() {\n\t}\n\n\tenum Predicates implements FunctionDefinition {\n\n\t\tALL(\"all\"), ANY(\"any\"), EXISTS(\"exists\"), NONE(\"none\"), SINGLE(\"single\"), IS_EMPTY(\"isEmpty\");\n\n\t\tprivate final String implementationName;\n\n\t\tPredicates(String implementationName) {\n\t\t\tthis.implementationName = implementationName;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getImplementationName() {\n\t\t\treturn this.implementationName;\n\t\t}\n\n\t}\n\n\tenum Graph implements FunctionDefinition {\n\n\t\tNAMES(\"names\"), PROPERTIES_BY_NAME(\"propertiesByName\"), BY_NAME(\"byName\");\n\n\t\tprivate final String implementationName;\n\n\t\tGraph(String implementationName) {\n\t\t\tthis.implementationName = \"graph.\" + implementationName;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getImplementationName() {\n\t\t\treturn this.implementationName;\n\t\t}\n\n\t}\n\n\tenum Scalars implements FunctionDefinition {\n\n\t\tCOALESCE(\"coalesce\"), END_NODE(\"endNode\"), HEAD(\"head\"), ID(\"id\"), ELEMENT_ID(\"elementId\"), LAST(\"last\"),\n\t\tLENGTH(\"length\"),\n\n\t\tPROPERTIES(\"properties\"), SHORTEST_PATH(\"shortestPath\"), SIZE(\"size\"),\n\n\t\tSTART_NODE(\"startNode\"), TYPE(\"type\"),\n\n\t\tTO_STRING(\"toString\"), TO_INTEGER(\"toInteger\"), TO_FLOAT(\"toFloat\"), TO_BOOLEAN(\"toBoolean\");\n\n\t\tprivate final String implementationName;\n\n\t\tScalars(String implementationName) {\n\t\t\tthis.implementationName = implementationName;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getImplementationName() {\n\t\t\treturn this.implementationName;\n\t\t}\n\n\t}\n\n\tenum Strings implements FunctionDefinition {\n\n\t\tLEFT(\"left\"), LTRIM(\"ltrim\"), REPLACE(\"replace\"), REVERSE(\"reverse\"), RIGHT(\"right\"), RTRIM(\"rtrim\"),\n\t\tSPLIT(\"split\"), SUBSTRING(\"substring\"), TO_LOWER(\"toLower\"), TO_STRING(\"toString\"),\n\t\tTO_STRING_OR_NULL(\"toStringOrNull\"), TO_UPPER(\"toUpper\"), TRIM(\"trim\");\n\n\t\tprivate final String implementationName;\n\n\t\tStrings(String implementationName) {\n\t\t\tthis.implementationName = implementationName;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getImplementationName() {\n\t\t\treturn this.implementationName;\n\t\t}\n\n\t}\n\n\tenum Spatials implements FunctionDefinition {\n\n\t\tPOINT(\"point\"), DISTANCE(\"distance\");\n\n\t\tprivate final String implementationName;\n\n\t\tSpatials(String implementationName) {\n\t\t\tthis.implementationName = implementationName;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getImplementationName() {\n\t\t\treturn this.implementationName;\n\t\t}\n\n\t}\n\n\tenum Aggregates implements FunctionDefinition {\n\n\t\tAVG(\"avg\"), COLLECT(\"collect\"), COUNT(\"count\"), MAX(\"max\"), MIN(\"min\"), PERCENTILE_CONT(\"percentileCont\"),\n\t\tPERCENTILE_DISC(\"percentileDisc\"), ST_DEV(\"stDev\"), ST_DEV_P(\"stDevP\"), SUM(\"sum\");\n\n\t\tprivate final String implementationName;\n\n\t\tAggregates(String implementationName) {\n\t\t\tthis.implementationName = implementationName;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getImplementationName() {\n\t\t\treturn this.implementationName;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isAggregate() {\n\t\t\treturn true;\n\t\t}\n\n\t}\n\n\tenum Lists implements FunctionDefinition {\n\n\t\tKEYS(\"keys\"), LABELS(\"labels\"), NODES(\"nodes\"), RANGE(\"range\"), REDUCE(\"reduce\"),\n\t\tRELATIONSHIPS(\"relationships\");\n\n\t\tprivate final String implementationName;\n\n\t\tLists(String implementationName) {\n\t\t\tthis.implementationName = implementationName;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getImplementationName() {\n\t\t\treturn this.implementationName;\n\t\t}\n\n\t}\n\n\tenum Temporals implements FunctionDefinition {\n\n\t\tDATE(\"date\"), DATETIME(\"datetime\"), LOCALDATETIME(\"localdatetime\"), LOCALTIME(\"localtime\"), TIME(\"time\"),\n\t\tDURATION(\"duration\");\n\n\t\tprivate final String implementationName;\n\n\t\tTemporals(String implementationName) {\n\t\t\tthis.implementationName = implementationName;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getImplementationName() {\n\t\t\treturn this.implementationName;\n\t\t}\n\n\t}\n\n\tenum MathematicalFunctions implements FunctionDefinition {\n\n\t\tABS(\"abs\"), CEIL(\"ceil\"), FLOOR(\"floor\"), RAND(\"rand\", 0, 0), ROUND(\"round\", 1, 3), SIGN(\"sign\"), E(\"e\", 0, 0),\n\t\tEXP(\"exp\"), LOG(\"log\"), LOG10(\"log10\"), SQRT(\"sqrt\"), ACOS(\"acos\"), ASIN(\"asin\"), ATAN(\"atan\"),\n\t\tATAN2(\"atan2\", 2, 2), COS(\"cos\"), COT(\"cot\"), DEGREES(\"degrees\"), HAVERSIN(\"haversin\"), PI(\"pi\", 0, 0),\n\t\tRADIANS(\"radians\"), SIN(\"sin\"), TAN(\"tan\");\n\n\t\tprivate final String implementationName;\n\n\t\tprivate final int minArgs;\n\n\t\tprivate final int maxArgs;\n\n\t\tMathematicalFunctions(String implementationName) {\n\t\t\tthis(implementationName, 1, 1);\n\t\t}\n\n\t\tMathematicalFunctions(String implementationName, int minArgs, int maxArgs) {\n\t\t\tthis.implementationName = implementationName;\n\t\t\tthis.minArgs = minArgs;\n\t\t\tthis.maxArgs = maxArgs;\n\t\t}\n\n\t\tint getMinArgs() {\n\t\t\treturn this.minArgs;\n\t\t}\n\n\t\tint getMaxArgs() {\n\t\t\treturn this.maxArgs;\n\t\t}\n\n\t\t@Override\n\t\tpublic String getImplementationName() {\n\t\t\treturn this.implementationName;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Case.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\nimport org.neo4j.cypherdsl.core.ast.ProvidesAffixes;\nimport org.neo4j.cypherdsl.core.internal.CaseWhenThen;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/CaseExpression.html\">CaseExpression</a>.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface Case extends Expression, ProvidesAffixes {\n\n\t/**\n\t * Creates a new {@link Case} {@link Expression}.\n\t * @param expression starting expression for the simple case\n\t * @return the new expression\n\t */\n\tstatic Case create(Expression expression) {\n\t\treturn (expression != null) ? new AbstractCase.SimpleCaseImpl(expression) : new AbstractCase.GenericCaseImpl();\n\t}\n\n\t/**\n\t * Creates a new case/when expression with an additional {@code WHEN} block.\n\t * @param nextExpression the next expression to use.\n\t * @return an ongoing when builder.\n\t */\n\t@CheckReturnValue\n\tOngoingWhenThen when(Expression nextExpression);\n\n\t/**\n\t * Extension the {@link Case} interface to support simple case with an initial\n\t * expression / condition.\n\t */\n\t@API(status = STABLE, since = \"1.0\")\n\tinterface SimpleCase extends Case {\n\n\t}\n\n\t/**\n\t * Extension of the {@link Case} interface to support generic case.\n\t */\n\t@API(status = STABLE, since = \"1.0\")\n\tinterface GenericCase extends Case {\n\n\t}\n\n\t/**\n\t * Specification for a renderable, complete CASE statement.\n\t */\n\t@API(status = STABLE, since = \"1.0\")\n\tinterface CaseEnding extends Case {\n\n\t\t/**\n\t\t * Adds a new {@code WHEN} block.\n\t\t * @param expression a2 new when expression.\n\t\t * @return an ongoing when builder.\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingWhenThen when(Expression expression);\n\n\t\t/**\n\t\t * Ends this case expression with a default expression to evaluate.\n\t\t * @param defaultExpression the new default expression\n\t\t * @return an ongoing when builder.\n\t\t */\n\t\t@CheckReturnValue\n\t\tCase elseDefault(Expression defaultExpression);\n\n\t}\n\n\t/**\n\t * Helper class to collect `when` expressions and create {@link CaseWhenThen}\n\t * instances when the `then` is provided.\n\t */\n\t@API(status = STABLE, since = \"1.0\")\n\tinterface OngoingWhenThen {\n\n\t\t/**\n\t\t * Ends this {@code WHEN} block with an expression.\n\t\t * @param expression the expression for the ongoing {@code WHEN} block.\n\t\t * @return an ongoing when builder.\n\t\t */\n\t\t@CheckReturnValue\n\t\tCaseEnding then(Expression expression);\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Clause.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * This is a marker interface for top level clauses.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = STABLE, since = \"2021.3.0\")\npublic interface Clause extends Visitable {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Clauses.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.net.URI;\nimport java.util.Collections;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.LoadCSV;\nimport org.neo4j.cypherdsl.core.internal.ProcedureName;\nimport org.neo4j.cypherdsl.core.internal.YieldItems;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Builder / factory for various {@link Clause clauses}. It's mostly useful for building a\n * Cypher-DSL AST outside the fluent API.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = STABLE, since = \"2021.3.0\")\npublic final class Clauses {\n\n\t/**\n\t * Not to be instantiated.\n\t */\n\tprivate Clauses() {\n\t}\n\n\t/**\n\t * Builds a {@code MATCH} clause. The result can be safely cast to a {@link Match} if\n\t * needed.\n\t * @param optional should this be an optional match?\n\t * @param patternElements the pattern elements to match\n\t * @param optionalWhere an optional where sub-clause\n\t * @param optionalHints optional hints to be used\n\t * @return an immutable match clause\n\t * @since 2022.0.0\n\t */\n\tpublic static Clause match(boolean optional, List<PatternElement> patternElements, Where optionalWhere,\n\t\t\tList<Hint> optionalHints) {\n\n\t\treturn new Match(optional, Pattern.of(patternElements), optionalWhere, optionalHints);\n\t}\n\n\t/**\n\t * Builds a {@code DELETE} clause.\n\t * @param detach should this be an detach delete?\n\t * @param expressions the expressions pointing to the things to be deleted\n\t * @return an immutable delete clause\n\t */\n\tpublic static Clause delete(boolean detach, List<Expression> expressions) {\n\n\t\treturn new Delete(new ExpressionList(expressions), detach);\n\t}\n\n\t/**\n\t * Builds a {@code RETURN} clause.\n\t * @param distinct should this be a distinct return\n\t * @param expressions the expressions to be returned\n\t * @param optionalSortItems an optional list of sort items\n\t * @param optionalSkip an optional {@link NumberLiteral} of how many items to skip\n\t * @param optionalLimit an optional {@link NumberLiteral} of how many items to be\n\t * returned\n\t * @return an immutable return clause\n\t */\n\tpublic static Return returning(boolean distinct, List<Expression> expressions, List<SortItem> optionalSortItems,\n\t\t\tExpression optionalSkip, Expression optionalLimit) {\n\n\t\tDefaultStatementBuilder.OrderBuilder orderBuilder = new DefaultStatementBuilder.OrderBuilder();\n\t\torderBuilder.orderBy(optionalSortItems);\n\t\torderBuilder.skip(optionalSkip);\n\t\torderBuilder.limit(optionalLimit);\n\t\treturn Return.create(false, distinct, expressions, orderBuilder);\n\t}\n\n\t/**\n\t * Builds a {@code CREATE} clause.\n\t * @param patternElements the pattern elements to create\n\t * @return an immutable create clause\n\t */\n\tpublic static Clause create(List<PatternElement> patternElements) {\n\n\t\treturn new Create(Pattern.of(patternElements));\n\t}\n\n\t/**\n\t * Builds a {@code MERGE} clause.\n\t * @param patternElements the pattern elements to merge\n\t * @param mergeActions an optional list of {@link MergeAction merge actions}\n\t * @return an immutable merge clause\n\t */\n\tpublic static Clause merge(List<PatternElement> patternElements, List<MergeAction> mergeActions) {\n\n\t\treturn new Merge(Pattern.of(patternElements), (mergeActions != null) ? mergeActions : Collections.emptyList());\n\t}\n\n\t/**\n\t * Retrofits an existing {@link Return return clause} into an equivalent {@link With\n\t * with clause}, optionally adding a {@link Where where}.\n\t * @param returnClause the return clause that defines the fields, order and limit of\n\t * what the with clause should return\n\t * @param optionalWhere an optional {@literal WHERE }expression to define a where\n\t * clause.\n\t * @return an immutable with clause\n\t * @since 2022.0.0\n\t */\n\tpublic static Clause with(Return returnClause, Where optionalWhere) {\n\n\t\treturn new With(returnClause, optionalWhere);\n\t}\n\n\t/**\n\t * Creates a {@link Remove remove clause}, removing labels or properties.\n\t * @param expressions expressions pointing to a list of properties or labels that\n\t * shall be removed\n\t * @return an immutable remove clause\n\t */\n\tpublic static Clause remove(List<Expression> expressions) {\n\n\t\treturn new Remove(new ExpressionList(expressions));\n\t}\n\n\t/**\n\t * Creates a {@link Set remove clause}, setting labels or properties.\n\t * @param expressions expressions pointing to a list of properties or labels that\n\t * shall be set\n\t * @return an immutable set clause\n\t */\n\tpublic static Clause set(List<Expression> expressions) {\n\n\t\treturn new Set(new ExpressionList(expressions));\n\t}\n\n\t/**\n\t * Creates an {@link Unwind unwind clause}.\n\t * @param expression the expression to unwind\n\t * @param name the name on which to unwind\n\t * @return an immutable unwind clause\n\t */\n\tpublic static Clause unwind(Expression expression, SymbolicName name) {\n\n\t\treturn new Unwind(expression, name.getValue());\n\t}\n\n\t/**\n\t * Creates an {@link LoadCSV LOAD CSV clause}.\n\t * @param withHeaders set to true to render the WITH HEADERS options\n\t * @param uri the source to load from\n\t * @param alias the alias for the lines\n\t * @param fieldTerminator the field terminator\n\t * @return an immutable clause\n\t */\n\tpublic static Clause loadCSV(boolean withHeaders, StringLiteral uri, SymbolicName alias, String fieldTerminator) {\n\n\t\treturn new LoadCSV(URI.create(uri.getContent().toString()), withHeaders, alias.getValue())\n\t\t\t.withFieldTerminator(fieldTerminator);\n\t}\n\n\t/**\n\t * Creates a {@literal CALL} clause.\n\t * @param namespace an optional namespace, maybe empty\n\t * @param name the name of the stored procedure to call\n\t * @param arguments the arguments, maybe null or empty\n\t * @param resultItems the result items, maybe null or empty\n\t * @param optionalWhere an optional where\n\t * @return an immutable clause\n\t * @since 2022.0.0\n\t */\n\tpublic static Clause callClause(List<String> namespace, String name, List<Expression> arguments,\n\t\t\tList<Expression> resultItems, Where optionalWhere) {\n\n\t\treturn ProcedureCallImpl.create(ProcedureName.from(namespace, name),\n\t\t\t\tnew Arguments((arguments != null) ? arguments.toArray(new Expression[0]) : new Expression[0]),\n\t\t\t\t(resultItems != null) ? YieldItems.yieldAllOf(resultItems.toArray(new Expression[0])) : null,\n\t\t\t\toptionalWhere);\n\t}\n\n\t/**\n\t * Creates a {@literal CALL {}} sub-query clause. No checking is done whether the\n\t * statement passed in returns anything meaningful so that the resulting clause will\n\t * be runnable or not.\n\t * @param statement a statement to be used inside the sub-query.\n\t * @return an immutable sub-query clause.\n\t */\n\tpublic static Clause callClause(Statement statement) {\n\n\t\treturn Subquery.call(statement);\n\t}\n\n\t/**\n\t * Creates a literal for each clause.\n\t * @param v the name of the variable that should be available in the list of updating\n\t * clauses\n\t * @param list the list on which to iterate\n\t * @param updatingClauses the updating clauses\n\t * @return an immutable foreach clause\n\t */\n\tpublic static Clause forEach(SymbolicName v, Expression list, List<Clause> updatingClauses) {\n\n\t\tAssertions.isTrue(updatingClauses.stream().allMatch(UpdatingClause.class::isInstance),\n\t\t\t\t\"Only updating clauses SET, REMOVE, CREATE, MERGE, DELETE, and FOREACH are allowed as clauses applied inside FOREACH.\");\n\t\treturn new Foreach(v, list, updatingClauses.stream().map(UpdatingClause.class::cast).toList());\n\t}\n\n\t/**\n\t * Creates a standalone <code>ORDER BY</code> clause.\n\t * @param sortItems the items to sort by\n\t * @param skip a literal number item specifying the skipped items, may be\n\t * {@literal null}\n\t * @param limit a literal number item specifying the total limit of items, may be\n\t * {@literal null}\n\t * @return an immutable order by clause\n\t * @since 2024.7.4\n\t */\n\tpublic static Clause orderBy(List<SortItem> sortItems, Expression skip, Expression limit) {\n\n\t\treturn new OrderByClause(new Order(sortItems), (skip != null) ? Skip.create(skip) : null,\n\t\t\t\t(limit != null) ? Limit.create(limit) : null);\n\t}\n\n\tstatic final class OrderByClause extends AbstractClause {\n\n\t\tprivate final Order order;\n\n\t\tprivate final Skip skip;\n\n\t\tprivate final Limit limit;\n\n\t\tOrderByClause(Order order, Skip skip, Limit limit) {\n\t\t\tthis.order = order;\n\t\t\tthis.skip = skip;\n\t\t\tthis.limit = limit;\n\t\t}\n\n\t\t@Override\n\t\tpublic void accept(Visitor visitor) {\n\t\t\tthis.order.accept(visitor);\n\t\t\tVisitable.visitIfNotNull(this.skip, visitor);\n\t\t\tVisitable.visitIfNotNull(this.limit, visitor);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ClausesBasedStatement.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.UsingPeriodicCommit;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * This variant of a {@link Statement} takes in a plain list of clauses without any\n * further checks. During rendering they are visited in the same order as originally\n * provided.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = INTERNAL, since = \"2021.3.0\")\nclass ClausesBasedStatement extends AbstractStatement {\n\n\tprivate final UsingPeriodicCommit optionalPeriodicCommit;\n\n\tprivate final List<Clause> clauses;\n\n\tClausesBasedStatement(List<Clause> clauses, UsingPeriodicCommit optionalPeriodicCommit) {\n\t\tthis.optionalPeriodicCommit = optionalPeriodicCommit;\n\t\tthis.clauses = List.copyOf(clauses);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tVisitable.visitIfNotNull(this.optionalPeriodicCommit, visitor);\n\t\tthis.clauses.forEach(c -> c.accept(visitor));\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic boolean doesReturnOrYield() {\n\t\tif (this.clauses.isEmpty()) {\n\t\t\treturn false;\n\t\t}\n\t\tClause lastClause = this.clauses.get(this.clauses.size() - 1);\n\t\treturn lastClause instanceof Return;\n\t}\n\n\t@API(status = INTERNAL)\n\tList<Clause> getClauses() {\n\t\treturn this.clauses;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/CollectExpression.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Implements\n * <a href=\"https://neo4j.com/docs/cypher-manual/current/subqueries/collect/\">COLLECT\n * subqueries</a>.\n *\n * @author Michael J. Simons\n * @since 2023.8.0\n */\n@API(status = STABLE, since = \"2023.0.0\")\n@Neo4jVersion(minimum = \"5.6\")\npublic final class CollectExpression implements SubqueryExpression {\n\n\tprivate final ImportingWith optionalWith;\n\n\tprivate final Statement resultStatement;\n\n\tprivate CollectExpression(ImportingWith optionalWith, Statement resultStatement) {\n\n\t\tthis.optionalWith = optionalWith;\n\t\tthis.resultStatement = resultStatement;\n\t}\n\n\tstatic CollectExpression collect(Statement resultStatement) {\n\t\treturn new CollectExpression(new ImportingWith(), resultStatement);\n\t}\n\n\tstatic CollectExpression collect(With optionalWith, Statement resultStatement) {\n\t\treturn new CollectExpression(new ImportingWith(optionalWith, null), resultStatement);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.optionalWith.accept(visitor);\n\t\tthis.resultStatement.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Comparison.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.EnterResult;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A concrete condition representing a comparision between two expressions.\n *\n * @author Michael J. Simons\n * @author Gerrit Meier\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Comparison implements Condition {\n\n\tprivate final Expression left;\n\n\tprivate final Operator comparator;\n\n\tprivate final Expression right;\n\n\tprivate Comparison(Expression left, Operator operator, Expression right) {\n\n\t\tthis.left = nestedIfCondition(left);\n\t\tthis.comparator = operator;\n\t\tthis.right = nestedIfCondition(right);\n\t}\n\n\tstatic Comparison create(Operator operator, Expression expression) {\n\n\t\tAssertions.isTrue(operator.isUnary(), \"Operator must be unary.\");\n\t\tAssertions.notNull(expression, \"Expression must not be null.\");\n\n\t\treturn switch (operator.getType()) {\n\t\t\tcase PREFIX -> new Comparison(null, operator, expression);\n\t\t\tcase POSTFIX -> new Comparison(expression, operator, null);\n\t\t\tdefault -> throw new IllegalArgumentException(\"Invalid operator type \" + operator.getType());\n\t\t};\n\t}\n\n\tstatic Comparison create(Expression lhs, Operator operator, Expression rhs) {\n\n\t\tAssertions.notNull(lhs, \"Left expression must not be null.\");\n\t\tAssertions.notNull(operator, \"Operator must not be empty.\");\n\t\tAssertions.notNull(rhs, \"Right expression must not be null.\");\n\n\t\treturn new Comparison(lhs, operator, rhs);\n\t}\n\n\tprivate static Expression nestedIfCondition(Expression expression) {\n\t\treturn (expression instanceof Condition) ? new NestedExpression(expression) : expression;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tEnterResult result = visitor.enterWithResult(this);\n\t\tif (result == EnterResult.CONTINUE) {\n\t\t\tif (this.left != null) {\n\t\t\t\tExpressions.nameOrExpression(this.left).accept(visitor);\n\t\t\t}\n\t\t\tthis.comparator.accept(visitor);\n\t\t\tif (this.right != null) {\n\t\t\t\tExpressions.nameOrExpression(this.right).accept(visitor);\n\t\t\t}\n\t\t}\n\t\tvisitor.leave(this);\n\t}\n\n\t@API(status = INTERNAL, since = \"2024.6.1\")\n\tpublic Expression getLeft() {\n\t\treturn this.left;\n\t}\n\n\t@API(status = INTERNAL, since = \"2024.6.1\")\n\tpublic Operator getComparator() {\n\t\treturn this.comparator;\n\t}\n\n\t@API(status = INTERNAL, since = \"2024.6.1\")\n\tpublic Expression getRight() {\n\t\treturn this.right;\n\t}\n\n\t@Override\n\tpublic Condition not() {\n\n\t\tif (this.comparator == Operator.IS_NULL) {\n\t\t\treturn new Comparison(this.left, Operator.IS_NOT_NULL, this.right);\n\t\t}\n\t\telse if (this.comparator == Operator.IS_NOT_NULL) {\n\t\t\treturn new Comparison(this.left, Operator.IS_NULL, this.right);\n\t\t}\n\t\treturn Condition.super.not();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/CompoundCondition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.EnumSet;\nimport java.util.List;\nimport java.util.Optional;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.ProvidesAffixes;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * A condition that consists of one or two {@link Condition conditions} connected by a\n * <a href=\"https://en.wikipedia.org/wiki/Logical_connective\">Logical connective\n * (operator)</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = INTERNAL, since = \"1.0\")\nfinal class CompoundCondition implements Condition, ProvidesAffixes {\n\n\tstatic final EnumSet<Operator> VALID_OPERATORS = EnumSet.of(Operator.AND, Operator.OR, Operator.XOR);\n\n\t/**\n\t * The empty, compound condition.\n\t */\n\tprivate static final CompoundCondition EMPTY_CONDITION = new CompoundCondition(null);\n\n\tprivate final Operator operator;\n\n\tprivate final List<Condition> conditions;\n\n\tprivate CompoundCondition(Operator operator) {\n\t\tthis.operator = operator;\n\t\tthis.conditions = new ArrayList<>();\n\t}\n\n\tstatic CompoundCondition create(Condition left, Operator operator, Condition right) {\n\n\t\tAssertions.isTrue(VALID_OPERATORS.contains(operator),\n\t\t\t\t\"Operator \" + operator + \" is not a valid operator for a compound condition.\");\n\n\t\tAssertions.notNull(left, \"Left hand side condition is required.\");\n\t\tAssertions.notNull(operator, \"Operator is required.\");\n\t\tAssertions.notNull(right, \"Right hand side condition is required.\");\n\t\treturn new CompoundCondition(operator).add(operator, left).add(operator, right);\n\t}\n\n\tstatic CompoundCondition copyOf(CompoundCondition other) {\n\n\t\tCompoundCondition result = new CompoundCondition(other.operator);\n\t\tresult.conditions.addAll(other.conditions);\n\t\treturn result;\n\t}\n\n\tstatic CompoundCondition empty() {\n\n\t\treturn EMPTY_CONDITION;\n\t}\n\n\tprivate static void acceptVisitorWithOperatorForChildCondition(Visitor visitor, Operator operator,\n\t\t\tCondition condition) {\n\t\tVisitable.visitIfNotNull(operator, visitor);\n\t\tcondition.accept(visitor);\n\t}\n\n\t@Override\n\tpublic Condition and(Condition condition) {\n\t\treturn this.add(Operator.AND, condition);\n\t}\n\n\t@Override\n\tpublic Condition or(Condition condition) {\n\t\treturn this.add(Operator.OR, condition);\n\t}\n\n\t@Override\n\tpublic Condition xor(Condition condition) {\n\t\treturn this.add(Operator.XOR, condition);\n\t}\n\n\tprivate CompoundCondition add(Operator chainingOperator, Condition condition) {\n\t\tif (this == EMPTY_CONDITION) {\n\t\t\treturn new CompoundCondition(chainingOperator).add(chainingOperator, condition);\n\t\t}\n\n\t\tif (condition instanceof CompoundCondition compoundCondition && !compoundCondition.hasConditions()) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif (condition instanceof CompoundCondition compoundCondition) {\n\t\t\tCompoundCondition target;\n\t\t\tif (this.operator == chainingOperator && chainingOperator == compoundCondition.operator) {\n\t\t\t\ttarget = CompoundCondition.copyOf(this);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tCompoundCondition inner = new CompoundCondition(chainingOperator);\n\t\t\t\tif (this.hasConditions()) {\n\t\t\t\t\tinner.conditions.add(this);\n\t\t\t\t}\n\t\t\t\ttarget = inner;\n\t\t\t}\n\t\t\tif (compoundCondition.canBeFlattenedWith(chainingOperator)) {\n\t\t\t\ttarget.conditions.addAll(compoundCondition.conditions);\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttarget.conditions.add(compoundCondition);\n\t\t\t}\n\n\t\t\treturn target;\n\t\t}\n\n\t\tif (this.operator == chainingOperator) {\n\t\t\tCompoundCondition target = CompoundCondition.copyOf(this);\n\t\t\ttarget.conditions.add(condition);\n\t\t\treturn target;\n\t\t}\n\n\t\treturn CompoundCondition.create(this, chainingOperator, condition);\n\t}\n\n\tboolean hasConditions() {\n\t\treturn !(this == EMPTY_CONDITION || this.conditions.isEmpty());\n\t}\n\n\t/**\n\t * Returns true if this operation can be flattened into a single with another using\n\t * the given operator.\n\t * @param operatorBefore the operator that is to be used before this condition\n\t * @return true if all conditions in this condition are either simple or compound\n\t * annotation with the same boolean operator as {@code operatorBefore}\n\t */\n\tprivate boolean canBeFlattenedWith(Operator operatorBefore) {\n\n\t\tif (this.operator != operatorBefore) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (Condition c : this.conditions) {\n\t\t\tif (c instanceof CompoundCondition compoundCondition && compoundCondition.operator != operatorBefore) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\t// There is nothing to visit here\n\t\tif (this.conditions.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fold single condition\n\t\tboolean hasManyConditions = this.conditions.size() > 1;\n\t\tif (hasManyConditions) {\n\t\t\tvisitor.enter(this);\n\t\t}\n\n\t\t// The first nested condition does not need an operator\n\t\tacceptVisitorWithOperatorForChildCondition(visitor, null, this.conditions.get(0));\n\n\t\t// All others do\n\t\tif (hasManyConditions) {\n\t\t\tfor (Condition condition : this.conditions.subList(1, this.conditions.size())) {\n\t\t\t\tacceptVisitorWithOperatorForChildCondition(visitor, this.operator, condition);\n\t\t\t}\n\t\t\tvisitor.leave(this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Optional<String> getPrefix() {\n\t\treturn Optional.of(\"(\");\n\t}\n\n\t@Override\n\tpublic Optional<String> getSuffix() {\n\t\treturn Optional.of(\")\");\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Condition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.internal.RelationshipPatternCondition;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Shared interface for all conditions.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface Condition extends Expression {\n\n\t/**\n\t * Adds a condition to this condition with an {@literal AND}.\n\t * @param condition the new condition to add, must not be {@literal null}.\n\t * @return a new condition.\n\t */\n\tdefault Condition and(Condition condition) {\n\t\treturn CompoundCondition.create(this, Operator.AND, condition);\n\t}\n\n\t/**\n\t * Adds a condition to this condition with an {@literal OR}.\n\t * @param condition the new condition to add, must not be {@literal null}.\n\t * @return a new condition.\n\t */\n\tdefault Condition or(Condition condition) {\n\t\treturn CompoundCondition.create(this, Operator.OR, condition);\n\t}\n\n\t/**\n\t * Adds a condition to this condition with a {@literal XOR}.\n\t * @param condition the new condition to add, must not be {@literal null}.\n\t * @return a new condition.\n\t */\n\tdefault Condition xor(Condition condition) {\n\t\treturn CompoundCondition.create(this, Operator.XOR, condition);\n\t}\n\n\t/**\n\t * Adds a condition based on a path pattern to this condition with an {@literal AND}.\n\t * See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/4.0/clauses/where/#query-where-patterns\">Using\n\t * path patterns in WHERE</a>.\n\t * @param pathPattern the path pattern to add to the where clause. This path pattern\n\t * must not be {@literal null} and must not introduce new variables not available in\n\t * the match.\n\t * @return a new condition.\n\t * @since 1.0.1\n\t */\n\tdefault Condition and(RelationshipPattern pathPattern) {\n\t\treturn CompoundCondition.create(this, Operator.AND, RelationshipPatternCondition.of(pathPattern));\n\t}\n\n\t/**\n\t * Adds a condition based on a path pattern to this condition with an {@literal OR}.\n\t * See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/4.0/clauses/where/#query-where-patterns\">Using\n\t * path patterns in WHERE</a>.\n\t * @param pathPattern the path pattern to add to the where clause. This path pattern\n\t * must not be {@literal null} and must not introduce new variables not available in\n\t * the match.\n\t * @return a new condition.\n\t * @since 1.0.1\n\t */\n\tdefault Condition or(RelationshipPattern pathPattern) {\n\t\treturn CompoundCondition.create(this, Operator.OR, RelationshipPatternCondition.of(pathPattern));\n\t}\n\n\t/**\n\t * Adds a condition based on a path pattern to this condition with a {@literal XOR}.\n\t * See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/4.0/clauses/where/#query-where-patterns\">Using\n\t * path patterns in WHERE</a>.\n\t * @param pathPattern the path pattern to add to the where clause. This path pattern\n\t * must not be {@literal null} and must not introduce new variables not available in\n\t * the match.\n\t * @return a new condition.\n\t * @since 1.0.1\n\t */\n\tdefault Condition xor(RelationshipPattern pathPattern) {\n\t\treturn CompoundCondition.create(this, Operator.XOR, RelationshipPatternCondition.of(pathPattern));\n\t}\n\n\t/**\n\t * Negates this condition.\n\t * @return a new condition.\n\t */\n\tdefault Condition not() {\n\t\treturn Comparison.create(Operator.NOT, this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Conditions.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.neo4j.cypherdsl.core.internal.RelationshipPatternCondition;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\n/**\n * Builder for various conditions.\n *\n * @author Michael J. Simons\n * @author Gerrit Meier\n * @author Aakash Sorathiya\n * @since 1.0\n */\nfinal class Conditions {\n\n\t/**\n\t * Not to be instantiated.\n\t */\n\tprivate Conditions() {\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code lhs} includes all elements\n\t * present in {@code rhs}.\n\t * @param lhs argument that is tested whether it contains all values in {@code rhs} or\n\t * not\n\t * @param rhs the reference collection\n\t * @return an \"includesAll\" comparison\n\t * @since 2022.7.0\n\t */\n\tstatic Condition includesAll(Expression lhs, Expression rhs) {\n\t\tSymbolicName x = SymbolicName.of(\"x\");\n\t\treturn Predicates.all(x).in(rhs).where(x.in(lhs));\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code lhs} includes any element\n\t * present in {@code rhs}.\n\t * @param lhs argument that is tested whether it contains any values in {@code rhs} or\n\t * not\n\t * @param rhs the reference collection\n\t * @return a \"not_includes\" comparison\n\t * @since 2022.7.0\n\t */\n\tstatic Condition includesAny(Expression lhs, Expression rhs) {\n\t\tSymbolicName x = SymbolicName.of(\"x\");\n\t\treturn Predicates.any(x).in(rhs).where(x.in(lhs));\n\t}\n\n\t/**\n\t * Creates a condition that checks whether this matches a given relationship pattern.\n\t * @param relationshipPattern the pattern being evaluated in a condition\n\t * @return a new condition matching the given pattern\n\t */\n\tstatic Condition matching(RelationshipPattern relationshipPattern) {\n\t\treturn RelationshipPatternCondition.of(relationshipPattern);\n\t}\n\n\t/**\n\t * Creates a condition that matches if the right hand side is a regular expression\n\t * that matches the left hand side via {@code =~}.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a \"matches\" comparison\n\t */\n\tstatic Condition matches(Expression lhs, Expression rhs) {\n\t\treturn Comparison.create(lhs, Operator.MATCHES, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that matches if both expressions are equals according to\n\t * {@code =}.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return an \"equals\" comparison\n\t */\n\tstatic Condition isEqualTo(Expression lhs, Expression rhs) {\n\t\treturn Comparison.create(lhs, Operator.EQUALITY, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that matches if both expressions are equals according to\n\t * {@code <>}.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a \"not equals\" comparison\n\t */\n\tstatic Condition isNotEqualTo(Expression lhs, Expression rhs) {\n\t\treturn Comparison.create(lhs, Operator.INEQUALITY, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that matches if the left hand side is less than the right hand\n\t * side.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return an \"less than\" comparison\n\t */\n\tstatic Condition lt(Expression lhs, Expression rhs) {\n\t\treturn Comparison.create(lhs, Operator.LESS_THAN, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that matches if the left hand side is less than or equal the\n\t * right hand side.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a \"less than or equal\" comparison\n\t */\n\tstatic Condition lte(Expression lhs, Expression rhs) {\n\t\treturn Comparison.create(lhs, Operator.LESS_THAN_OR_EQUAL_TO, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that matches if the left hand side is greater than or equal the\n\t * right hand side.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a \"greater than or equal\" comparison\n\t */\n\tstatic Condition gte(Expression lhs, Expression rhs) {\n\t\treturn Comparison.create(lhs, Operator.GREATER_THAN_OR_EQUAL_TO, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that matches if the left hand side is greater than the right\n\t * hand side.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return an \"greater than\" comparison\n\t */\n\tstatic Condition gt(Expression lhs, Expression rhs) {\n\t\treturn Comparison.create(lhs, Operator.GREATER_THAN, rhs);\n\t}\n\n\t/**\n\t * Negates the given condition.\n\t * @param condition the condition to negate. Must not be null.\n\t * @return the negated condition.\n\t */\n\tstatic Condition not(Condition condition) {\n\n\t\tAssertions.notNull(condition, \"Condition to negate must not be null.\");\n\t\treturn condition.not();\n\t}\n\n\t/**\n\t * Negates the given pattern element: The pattern must not matched to be included in\n\t * the result.\n\t * @param pattern the pattern to negate. Must not be null.\n\t * @return a condition that evaluates to true when the pattern does not match.\n\t */\n\tstatic Condition not(RelationshipPattern pattern) {\n\n\t\treturn RelationshipPatternCondition.not(pattern);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code lhs} starts with the\n\t * {@code rhs}.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a new condition.\n\t */\n\tstatic Condition startsWith(Expression lhs, Expression rhs) {\n\t\treturn Comparison.create(lhs, Operator.STARTS_WITH, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code lhs} contains with the\n\t * {@code rhs}.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a new condition.\n\t */\n\tstatic Condition contains(Expression lhs, Expression rhs) {\n\t\treturn Comparison.create(lhs, Operator.CONTAINS, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code lhs} ends with the {@code rhs}.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a new condition.\n\t */\n\tstatic Condition endsWith(Expression lhs, Expression rhs) {\n\t\treturn Comparison.create(lhs, Operator.ENDS_WITH, rhs);\n\t}\n\n\t/**\n\t * Creates a placeholder condition which is not rendered in the final statement but is\n\t * useful while chaining conditions together.\n\t * @return a placeholder condition.\n\t */\n\tstatic Condition noCondition() {\n\n\t\treturn CompoundCondition.empty();\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code expression} is {@literal null}.\n\t * @param expression the expression to check for {@literal null}\n\t * @return a new condition.\n\t */\n\tstatic Condition isNull(Expression expression) {\n\n\t\treturn Comparison.create(Operator.IS_NULL, expression);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code expression} is not\n\t * {@literal null}.\n\t * @param expression the expression to check for {@literal null}\n\t * @return a new condition.\n\t */\n\tstatic Condition isNotNull(Expression expression) {\n\n\t\treturn Comparison.create(Operator.IS_NOT_NULL, expression);\n\t}\n\n\t/**\n\t * {@return a condition that is always true}\n\t */\n\tstatic Condition isTrue() {\n\n\t\treturn ConstantCondition.TRUE;\n\t}\n\n\t/**\n\t * {@return a condition that is always false}\n\t */\n\tstatic Condition isFalse() {\n\n\t\treturn ConstantCondition.FALSE;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ConflictingParametersException.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.io.Serial;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Exception thrown when extracting parameters from a statement leads to one parameter\n * with a given name appearing with different values.\n *\n * @author Andreas Berger\n * @author Michael J. Simons\n * @since 2021.0.0\n */\n@API(status = STABLE, since = \"2021.0.0\")\npublic final class ConflictingParametersException extends RuntimeException {\n\n\t@Serial\n\tprivate static final long serialVersionUID = -45456411835790492L;\n\n\tprivate final transient Map<String, Set<Object>> erroneousParameters;\n\n\tConflictingParametersException(Map<String, Set<Object>> erroneousParameters) {\n\t\tsuper(createMessage(erroneousParameters));\n\t\tthis.erroneousParameters = new HashMap<>(erroneousParameters.size());\n\t\terroneousParameters.forEach((k, v) -> this.erroneousParameters.put(k, new HashSet<>(v)));\n\t}\n\n\tprivate static String createMessage(Map<String, Set<Object>> errors) {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tString prefix;\n\t\tif (errors.size() > 1) {\n\t\t\tsb.append(\"There are conflicting parameter values:\");\n\t\t\tprefix = \"\\n\\t\";\n\t\t}\n\t\telse {\n\t\t\tprefix = \"\";\n\t\t}\n\t\terrors.forEach((param, values) -> {\n\t\t\tsb.append(prefix);\n\t\t\tsb.append(\"Parameter '\").append(param).append(\"' is defined multiple times with different bound values: \");\n\t\t\tsb.append(values.stream()\n\t\t\t\t.map(o -> (o != Parameter.NO_VALUE) ? Objects.toString(o) : \"(UNDEFINED VALUE)\")\n\t\t\t\t.collect(Collectors.joining(\" != \")));\n\t\t});\n\t\treturn sb.toString();\n\t}\n\n\t/**\n\t * {@return the conflicting parameters}\n\t */\n\tpublic Map<String, Set<Object>> getErroneousParameters() {\n\t\treturn Collections.unmodifiableMap(this.erroneousParameters);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ConstantCondition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A constant condition that is either always {@literal true} or {@literal false}.\n *\n * @author Michael J. Simons\n * @author Andreas Berger\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class ConstantCondition extends ExpressionCondition {\n\n\tstatic final ConstantCondition TRUE = new ConstantCondition(BooleanLiteral.TRUE);\n\tstatic final ConstantCondition FALSE = new ConstantCondition(BooleanLiteral.FALSE);\n\n\tprivate ConstantCondition(BooleanLiteral value) {\n\t\tsuper(value);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/CountExpression.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Added for supporting the Neo4j v5 parser.\n *\n * @author Michael J. Simons\n * @since 2023.0.0\n */\n@API(status = STABLE, since = \"2023.0.0\")\n@Neo4jVersion(minimum = \"5.0\")\npublic final class CountExpression implements SubqueryExpression, ExposesWhere<Expression> {\n\n\tprivate final ImportingWith importingWith;\n\n\tprivate final List<Visitable> fragments;\n\n\tprivate final Where innerWhere;\n\n\tprivate CountExpression(ImportingWith optionalWith, List<? extends Visitable> fragments, Where innerWhere) {\n\n\t\tvar patternOrUnion = (fragments.size() != 1) ? null : fragments.get(0);\n\n\t\tif (patternOrUnion instanceof Statement.UnionQuery && innerWhere != null) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot use a UNION with a WHERE clause inside a COUNT {} expression\");\n\t\t}\n\t\tthis.importingWith = optionalWith;\n\t\tvar imports = optionalWith.imports();\n\n\t\tif (imports != null && patternOrUnion instanceof Pattern pattern) {\n\t\t\tthis.fragments = List.of(new Match(false, pattern, innerWhere, null));\n\t\t\tthis.innerWhere = null;\n\t\t}\n\t\telse if (imports != null && patternOrUnion instanceof Match match) {\n\t\t\tthis.fragments = List.of(new Match(false, match.pattern, innerWhere, null));\n\t\t\tthis.innerWhere = null;\n\t\t}\n\t\telse {\n\t\t\tthis.fragments = List.copyOf(fragments);\n\t\t\tthis.innerWhere = innerWhere;\n\t\t}\n\t}\n\n\tstatic CountExpression count(Statement statement, IdentifiableElement... imports) {\n\n\t\treturn new CountExpression(ImportingWith.of(imports), List.of(statement), null);\n\t}\n\n\tstatic CountExpression count(Visitable patternOrUnion) {\n\t\treturn new CountExpression(new ImportingWith(), List.of(patternOrUnion), null);\n\t}\n\n\tstatic CountExpression count(With optionalWith, Visitable patternOrUnion) {\n\t\treturn new CountExpression(new ImportingWith(optionalWith, null), List.of(patternOrUnion), null);\n\t}\n\n\tstatic CountExpression count(List<PatternElement> patternElements, Where innerWhere) {\n\t\treturn new CountExpression(new ImportingWith(), patternElements, innerWhere);\n\t}\n\n\t/**\n\t * Creates a new {@link CountExpression count expression} with additional conditions.\n\t * @param condition the condition to apply in the count expression\n\t * @return a new {@link CountExpression}\n\t */\n\tpublic CountExpression where(Condition condition) {\n\n\t\tif (this.fragments.size() == 1 && this.fragments.get(0) instanceof Statement) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"This count expression is build upon a full statement, adding a condition to it is not supported.\");\n\t\t}\n\t\treturn new CountExpression(this.importingWith, this.fragments, new Where(condition));\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.importingWith.accept(visitor);\n\t\tthis.fragments.forEach(v -> v.accept(visitor));\n\t\tVisitable.visitIfNotNull(this.innerWhere, visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Create.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Create.html\">Create</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Create extends AbstractClause implements UpdatingClause {\n\n\tprivate final Pattern pattern;\n\n\tCreate(Pattern pattern) {\n\t\tthis.pattern = pattern;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.pattern.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Cypher.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.lang.reflect.Array;\nimport java.net.URI;\nimport java.time.Duration;\nimport java.time.Period;\nimport java.time.temporal.TemporalAccessor;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.ResourceBundle;\nimport java.util.TimeZone;\nimport java.util.function.BiConsumer;\nimport java.util.function.Consumer;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ListComprehension.OngoingDefinitionWithVariable;\nimport org.neo4j.cypherdsl.core.Literal.UnsupportedLiteralException;\nimport org.neo4j.cypherdsl.core.PatternComprehension.OngoingDefinitionWithPattern;\nimport org.neo4j.cypherdsl.core.Statement.SingleQuery;\nimport org.neo4j.cypherdsl.core.Statement.UnionQuery;\nimport org.neo4j.cypherdsl.core.Statement.UseStatement;\nimport org.neo4j.cypherdsl.core.StatementBuilder.OngoingStandaloneCallWithoutArguments;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * The main entry point into the Cypher DSL. The Cypher Builder API is intended for\n * framework usage to produce Cypher statements required for database operations.\n *\n * @author Michael J. Simons\n * @author Gerrit Meier\n * @author Andreas Berger\n * @author Ali Ince\n * @since 1.0\n */\n@SuppressWarnings(\"unused\")\n@API(status = STABLE, since = \"1.0\")\npublic final class Cypher {\n\n\tstatic final ResourceBundle MESSAGES = ResourceBundle.getBundle(\"org.neo4j.cypherdsl.core.messages\");\n\n\t/**\n\t * The foreign adapter factory. Can only be used when `com.querydsl:querydsl-core` is\n\t * on the class path. The object won't be modified after initialisation.\n\t */\n\t@SuppressWarnings(\"squid:S3077\")\n\tprivate static volatile ForeignAdapterFactory foreignAdapterFactory;\n\n\t/**\n\t * Not to be instantiated.\n\t */\n\tprivate Cypher() {\n\t}\n\n\t/**\n\t * Create a new Node representation with at least one label, the \"primary\" label. This\n\t * is required. All other labels are optional.\n\t * @param primaryLabel the primary label this node is identified by.\n\t * @param additionalLabels additional labels\n\t * @return a new node representation\n\t */\n\tpublic static Node node(String primaryLabel, String... additionalLabels) {\n\n\t\treturn new InternalNodeImpl(primaryLabel, additionalLabels);\n\t}\n\n\t/**\n\t * Create a new Node representation with at least one label, the \"primary\" label. This\n\t * is required. All other labels are optional.\n\t * @param primaryLabel the primary label this node is identified by.\n\t * @param additionalLabels additional labels\n\t * @return a new node representation\n\t */\n\tpublic static Node node(String primaryLabel, List<String> additionalLabels) {\n\n\t\treturn new InternalNodeImpl(primaryLabel, additionalLabels.toArray(new String[] {}));\n\t}\n\n\t/**\n\t * Create a new Node representation with at least one label, the \"primary\" label. This\n\t * is required. All other labels are optional. This method also takes a map of\n\t * properties. This allows the returned node object to be used in a {@code MATCH} or\n\t * {@code MERGE} statement.\n\t * @param primaryLabel the primary label this node is identified by.\n\t * @param properties the properties expected to exist on the node.\n\t * @param additionalLabels additional labels\n\t * @return a new node representation\n\t */\n\tpublic static Node node(String primaryLabel, MapExpression properties, String... additionalLabels) {\n\n\t\treturn new InternalNodeImpl(null, primaryLabel, properties, additionalLabels);\n\t}\n\n\t/**\n\t * Create a new Node representation with at least one label, the \"primary\" label. This\n\t * is required. All other labels are optional. This method also takes a map of\n\t * properties. This allows the returned node object to be used in a {@code MATCH} or\n\t * {@code MERGE} statement.\n\t * @param primaryLabel the primary label this node is identified by.\n\t * @param properties the properties expected to exist on the node.\n\t * @param additionalLabels additional labels\n\t * @return a new node representation\n\t * @since 2021.2.2\n\t */\n\tpublic static Node node(String primaryLabel, MapExpression properties, Collection<String> additionalLabels) {\n\n\t\treturn node(primaryLabel, properties, additionalLabels.toArray(new String[] {}));\n\t}\n\n\t/**\n\t * {@return a node matching any node}\n\t */\n\tpublic static Node anyNode() {\n\t\treturn new InternalNodeImpl();\n\t}\n\n\t/**\n\t * Creates an expression that matches the given {@code label} exactly. Can be used as\n\t * starting point to add conditions via {@link Labels#and(Labels)} or\n\t * {@link Labels#or(Labels)}.\n\t * @param label the label to match\n\t * @return a label expression\n\t */\n\tpublic static Labels exactlyLabel(String label) {\n\t\treturn Labels.exactly(label);\n\t}\n\n\t/**\n\t * Creates a dynamic label expression matching all labels to which {@code expression}\n\t * resolves.\n\t * @param expression the expression that must resolve to a string or a list of strings\n\t * @return a dynamic label expression\n\t * @since 2025.1.0\n\t */\n\tpublic static Labels allLabels(Expression expression) {\n\t\treturn Labels.all(expression);\n\t}\n\n\t/**\n\t * Creates a dynamic label expression matching any label to which {@code expression}\n\t * resolves.\n\t * @param expression the expression that must resolve to a string or a list of strings\n\t * @return a dynamic label expression\n\t * @since 2025.1.0\n\t */\n\tpublic static Labels anyLabel(Expression expression) {\n\t\treturn Labels.any(expression);\n\t}\n\n\t/**\n\t * Creates a new {@literal Node} object.\n\t * @param labelExpression required expression\n\t * @return a node matching a label expression\n\t * @since 2023.0.2\n\t * @deprecated use {@link #node(Labels)}\n\t */\n\t@SuppressWarnings(\"removal\")\n\t@Deprecated(forRemoval = true)\n\tpublic static Node node(LabelExpression labelExpression) {\n\t\treturn node(Labels.of(labelExpression));\n\t}\n\n\t/**\n\t * Creates a new {@literal Node} object.\n\t * @param labels required expression\n\t * @return a node matching the given labels\n\t * @since 2025.1.0\n\t */\n\tpublic static Node node(Labels labels) {\n\t\treturn new InternalNodeImpl(Objects.requireNonNull(labels), null);\n\t}\n\n\t/**\n\t * {@return the '*' wildcard literal}\n\t */\n\tpublic static Asterisk asterisk() {\n\t\treturn Asterisk.INSTANCE;\n\t}\n\n\t/**\n\t * Creates a new unlabeled {@literal Node} object.\n\t * @param symbolicName the new symbolic name\n\t * @return a node matching any node with the symbolic the given {@code symbolicName}.\n\t */\n\tpublic static Node anyNode(String symbolicName) {\n\t\treturn new InternalNodeImpl().named(symbolicName);\n\t}\n\n\t/**\n\t * Creates a new unlabeled {@literal Node} object.\n\t * @param symbolicName the new symbolic name\n\t * @return a node matching any node with the symbolic the given {@code symbolicName}.\n\t */\n\tpublic static Node anyNode(SymbolicName symbolicName) {\n\t\treturn new InternalNodeImpl().named(symbolicName);\n\t}\n\n\t/**\n\t * Dereferences a property for a symbolic name, most likely pointing to a property\n\t * container like a node or a relationship.\n\t * @param containerName the symbolic name of a property container\n\t * @param names the names of the properties to dereference. More than one name does\n\t * create a nested property like {@code containerName.name1.name2}.\n\t * @return a new property\n\t */\n\tpublic static Property property(String containerName, String... names) {\n\t\treturn property(name(containerName), names);\n\t}\n\n\t/**\n\t * Dereferences a property for a symbolic name, most likely pointing to a property\n\t * container like a node or a relationship.\n\t * @param containerName the symbolic name of a property container\n\t * @param names the names of the properties to dereference. More than one name does\n\t * create a nested property like {@code containerName.name1.name2}.\n\t * @return a new property\n\t * @since 2021.2.2\n\t */\n\tpublic static Property property(String containerName, Collection<String> names) {\n\t\treturn property(name(containerName), names.toArray(new String[] {}));\n\t}\n\n\t/**\n\t * Dereferences a property on an arbitrary expression.\n\t * @param expression the expression that describes some sort of accessible map\n\t * @param names the names of the properties to dereference. More than one name does\n\t * create a nested property like {@code expression.name1.name2}.\n\t * @return a new property.\n\t */\n\tpublic static Property property(Expression expression, String... names) {\n\t\treturn InternalPropertyImpl.create(expression, names);\n\t}\n\n\t/**\n\t * Dereferences a property on a arbitrary expression.\n\t * @param expression the expression that describes some sort of accessible map\n\t * @param names the names of the properties to dereference. More than one name does\n\t * create a nested property like {@code expression.name1.name2}.\n\t * @return a new property.\n\t * @since 2021.2.2\n\t */\n\tpublic static Property property(Expression expression, Collection<String> names) {\n\t\treturn property(expression, names.toArray(new String[] {}));\n\t}\n\n\t/**\n\t * Creates a dynamic lookup of a property for a symbolic name, most likely pointing to\n\t * a property container like a node or a relationship. A dynamic property will be\n\t * rendered as {@code p[expression]}.\n\t * @param containerName the symbolic name of a property container\n\t * @param lookup an expression to use as a dynamic lookup for properties of the\n\t * container with the given name\n\t * @return a new property\n\t * @since 2021.0.0\n\t */\n\tpublic static Property property(String containerName, Expression lookup) {\n\t\treturn property(name(containerName), lookup);\n\t}\n\n\t/**\n\t * Creates a dynamic lookup of a property on an arbitrary expression. A dynamic\n\t * property will be rendered as {@code p[expression]}.\n\t * @param expression the expression that describes some sort of accessible map\n\t * @param lookup an expression to use as a dynamic lookup for properties of the\n\t * container the expression resolved to\n\t * @return a new property.\n\t * @since 2021.0.0\n\t */\n\tpublic static Property property(Expression expression, Expression lookup) {\n\t\treturn InternalPropertyImpl.create(expression, lookup);\n\t}\n\n\t/**\n\t * Starts defining a named path by indicating a name.\n\t * @param name the name of the new path\n\t * @return an ongoing definition of a named path\n\t * @since 1.1\n\t */\n\tpublic static NamedPath.OngoingDefinitionWithName path(String name) {\n\t\treturn NamedPath.named(name);\n\t}\n\n\t/**\n\t * Starts defining a named path by indicating a name.\n\t * @param name the name of the new path\n\t * @return an ongoing definition of a named path\n\t * @since 1.1\n\t */\n\tpublic static NamedPath.OngoingDefinitionWithName path(SymbolicName name) {\n\t\treturn NamedPath.named(name);\n\t}\n\n\t/**\n\t * Returns an ongoing definition of a named path, returning the k shortest paths.\n\t * @param k the number of shortest groups to return\n\t * @return an ongoing definition of a named path, returning the k shortest paths.\n\t * @since 2024.7.0\n\t */\n\tpublic static NamedPath.OngoingShortestDefinition shortestK(int k) {\n\t\treturn NamedPath.shortest(k);\n\t}\n\n\t/**\n\t * Returns an ongoing definition of a named path, returning the k shortest groups of\n\t * points.\n\t * @param k the number of shortest groups to return\n\t * @return an ongoing definition of a named path, returning the k shortest groups of\n\t * paths.\n\t * @since 2024.7.0\n\t */\n\tpublic static NamedPath.OngoingShortestDefinition shortestKGroups(int k) {\n\t\treturn NamedPath.shortestKGroups(k);\n\t}\n\n\t/**\n\t * Returns an ongoing definition of a named path, returning any shortest path.\n\t * @return an ongoing definition of a named path, returning any shortest path\n\t * @since 2024.7.0\n\t */\n\tpublic static NamedPath.OngoingShortestDefinition anyShortest() {\n\t\treturn NamedPath.any();\n\t}\n\n\t/**\n\t * Returns an ongoing definition of a named path, returning all shortest paths.\n\t * @return an ongoing definition of a named path, returning all shortest paths\n\t * @since 2024.7.0\n\t */\n\tpublic static NamedPath.OngoingShortestDefinition allShortest() {\n\t\treturn NamedPath.allShortest();\n\t}\n\n\t/**\n\t * Creates a new symbolic name.\n\t * @param value the value of the symbolic name\n\t * @return a new symbolic name\n\t */\n\tpublic static SymbolicName name(String value) {\n\n\t\treturn SymbolicName.of(value);\n\t}\n\n\t/**\n\t * Creates a new parameter placeholder. Existing $-signs will be removed.\n\t * @param name the name of the parameter, must not be null\n\t * @return the new parameter\n\t */\n\tpublic static Parameter<Object> parameter(String name) {\n\t\treturn Parameter.create(name);\n\t}\n\n\t/**\n\t * Creates a new parameter with the given {@code name} and a value bound to it. The\n\t * value can be retrieved from the final statement build.\n\t * @param name the name of the parameter, must not be null\n\t * @param value the value of the parameter.\n\t * @param <T> type of the new parameter\n\t * @return the new parameter\n\t * @since 2021.0.0\n\t */\n\tpublic static <T> Parameter<T> parameter(String name, T value) {\n\t\treturn Parameter.create(name, value);\n\t}\n\n\t/**\n\t * Creates a new anonymous parameter with a value bound to it. The value can be\n\t * retrieved from the final statement build. The name will be available as soon as the\n\t * statement has been rendered.\n\t * @param value the value of the parameter.\n\t * @param <T> type of the new parameter\n\t * @return the new parameter\n\t * @since 2021.1.0\n\t */\n\tpublic static <T> Parameter<T> anonParameter(T value) {\n\t\treturn Parameter.anon(value);\n\t}\n\n\t/**\n\t * Prepares an optional match statement.\n\t * @param pattern the patterns to match\n\t * @return an ongoing match that is used to specify an optional where and a required\n\t * return clause\n\t */\n\tpublic static StatementBuilder.OngoingReadingWithoutWhere optionalMatch(PatternElement... pattern) {\n\n\t\treturn Statement.builder().optionalMatch(pattern);\n\t}\n\n\t/**\n\t * Prepares an optional match statement.\n\t * @param pattern the patterns to match\n\t * @return an ongoing match that is used to specify an optional where and a required\n\t * return clause\n\t * @since 2021.2.2\n\t */\n\tpublic static StatementBuilder.OngoingReadingWithoutWhere optionalMatch(\n\t\t\tCollection<? extends PatternElement> pattern) {\n\n\t\treturn optionalMatch(pattern.toArray(new PatternElement[] {}));\n\t}\n\n\t/**\n\t * Starts building a statement based on a match clause. Use\n\t * {@link Cypher#node(String, String...)} and related to retrieve a node or a\n\t * relationship, which both are pattern elements.\n\t * @param pattern the patterns to match\n\t * @return an ongoing match that is used to specify an optional where and a required\n\t * return clause\n\t */\n\tpublic static StatementBuilder.OngoingReadingWithoutWhere match(PatternElement... pattern) {\n\n\t\treturn Statement.builder().match(pattern);\n\t}\n\n\t/**\n\t * Starts building a statement based on a match clause. Use\n\t * {@link Cypher#node(String, String...)} and related to retrieve a node or a\n\t * relationship, which both are pattern elements.\n\t * @param pattern the patterns to match\n\t * @return an ongoing match that is used to specify an optional where and a required\n\t * return clause\n\t * @since 2021.2.2\n\t */\n\tpublic static StatementBuilder.OngoingReadingWithoutWhere match(Collection<? extends PatternElement> pattern) {\n\n\t\treturn match(pattern.toArray(new PatternElement[] {}));\n\t}\n\n\t/**\n\t * Starts building a statement based on a match clause. Use\n\t * {@link Cypher#node(String, String...)} and related to retrieve a node or a\n\t * relationship, which both are pattern elements.\n\t * @param optional a flag whether the {@code MATCH} clause includes the\n\t * {@code OPTIONAL} keyword.\n\t * @param pattern the patterns to match\n\t * @return an ongoing match that is used to specify an optional where and a required\n\t * return clause\n\t * @since 2020.1.3\n\t */\n\tpublic static StatementBuilder.OngoingReadingWithoutWhere match(boolean optional, PatternElement... pattern) {\n\n\t\treturn Statement.builder().match(optional, pattern);\n\t}\n\n\t/**\n\t * Starts building a statement based on a match clause. Use\n\t * {@link Cypher#node(String, String...)} and related to retrieve a node or a\n\t * relationship, which both are pattern elements.\n\t * @param optional a flag whether the {@code MATCH} clause includes the\n\t * {@code OPTIONAL} keyword.\n\t * @param pattern the patterns to match\n\t * @return an ongoing match that is used to specify an optional where and a required\n\t * return clause\n\t * @since 2021.2.2\n\t */\n\tpublic static StatementBuilder.OngoingReadingWithoutWhere match(boolean optional,\n\t\t\tCollection<? extends PatternElement> pattern) {\n\n\t\treturn match(optional, pattern.toArray(new PatternElement[] {}));\n\t}\n\n\t/**\n\t * Starts building a statement based on a {@code CREATE} clause.\n\t * @param pattern the patterns to create\n\t * @return an ongoing {@code CREATE} that can be used to specify {@code WITH} and\n\t * {@code RETURNING} etc.\n\t */\n\tpublic static StatementBuilder.OngoingUpdate create(PatternElement... pattern) {\n\n\t\treturn Statement.builder().create(pattern);\n\t}\n\n\t/**\n\t * Starts building a statement based on a {@code CREATE} clause.\n\t * @param pattern the patterns to create\n\t * @return an ongoing {@code CREATE} that can be used to specify {@code WITH} and\n\t * {@code RETURNING} etc.\n\t * @since 2021.2.2\n\t */\n\tpublic static StatementBuilder.OngoingUpdate create(Collection<? extends PatternElement> pattern) {\n\n\t\treturn create(pattern.toArray(new PatternElement[] {}));\n\t}\n\n\t/**\n\t * Starts a statement with a leading {@code WITH}. Those are useful for passing on\n\t * lists of various type that can be unwound later on etc. A leading {@code WITH}\n\t * obviously cannot be used with patterns and needs its arguments to have an alias.\n\t * @param variables one ore more variables.\n\t * @return an ongoing with clause.\n\t * @since 2020.1.2\n\t */\n\tpublic static StatementBuilder.OrderableOngoingReadingAndWithWithoutWhere with(String... variables) {\n\n\t\treturn Statement.builder().with(variables);\n\t}\n\n\t/**\n\t * Starts a statement with a leading {@code WITH}. Those are useful for passing on\n\t * lists of various type that can be unwound later on etc. A leading {@code WITH}\n\t * cannot be used with patterns obviously and needs its arguments to have an alias.\n\t * @param elements one ore more variables.\n\t * @return an ongoing with clause.\n\t * @since 2020.1.2\n\t */\n\tpublic static StatementBuilder.OrderableOngoingReadingAndWithWithoutWhere with(IdentifiableElement... elements) {\n\n\t\treturn Statement.builder().with(elements);\n\t}\n\n\t/**\n\t * Start building a new sub-query expression by importing variables into the scope\n\t * with a {@literal WITH} clause.\n\t * @param identifiableElements the identifiable elements to import\n\t * @return a builder for creating the concrete sub-query\n\t * @since 2023.9.0\n\t */\n\tpublic static SubqueryExpressionBuilder subqueryWith(String... identifiableElements) {\n\t\treturn subqueryWith(Arrays.stream(identifiableElements).map(SymbolicName::of).toArray(SymbolicName[]::new));\n\t}\n\n\t/**\n\t * Start building a new sub-query expression by importing variables into the scope\n\t * with a {@literal WITH} clause.\n\t * @param identifiableElements the identifiable elements to import\n\t * @return a builder for creating the concrete sub-query\n\t * @since 2023.9.0\n\t */\n\tpublic static SubqueryExpressionBuilder subqueryWith(IdentifiableElement... identifiableElements) {\n\t\treturn Expressions.with(identifiableElements);\n\t}\n\n\t/**\n\t * Starts a statement with a leading {@code WITH}. Those are useful for passing on\n\t * lists of various type that can be unwound later on etc. A leading {@code WITH}\n\t * cannot be used with patterns obviously and needs its arguments to have an alias.\n\t * <p>\n\t * This method takes both aliased and non-aliased expression. The later will produce\n\t * only valid Cypher when used in combination with a correlated subquery via\n\t * {@link Cypher#call(Statement)}.\n\t * @param elements one ore more expressions.\n\t * @return an ongoing with clause.\n\t * @since 2021.2.2\n\t */\n\tpublic static StatementBuilder.OrderableOngoingReadingAndWithWithoutWhere with(\n\t\t\tCollection<IdentifiableElement> elements) {\n\n\t\treturn Statement.builder().with(elements);\n\t}\n\n\t/**\n\t * Starts building a statement based on a {@code MERGE} clause.\n\t * @param pattern the patterns to merge\n\t * @return an ongoing {@code MERGE} that can be used to specify {@code WITH} and\n\t * {@code RETURNING} etc.\n\t */\n\tpublic static StatementBuilder.OngoingMerge merge(PatternElement... pattern) {\n\n\t\treturn Statement.builder().merge(pattern);\n\t}\n\n\t/**\n\t * Starts building a statement based on a {@code MERGE} clause.\n\t * @param pattern the patterns to merge\n\t * @return an ongoing {@code MERGE} that can be used to specify {@code WITH} and\n\t * {@code RETURNING} etc.\n\t * @since 2021.2.2\n\t */\n\tpublic static StatementBuilder.OngoingMerge merge(Collection<? extends PatternElement> pattern) {\n\n\t\treturn merge(pattern.toArray(new PatternElement[] {}));\n\t}\n\n\t/**\n\t * Starts building a statement starting with an {@code UNWIND} clause. The expression\n\t * needs to be an expression evaluating to a list, otherwise the query will fail.\n\t * @param expression the expression to unwind\n\t * @return an ongoing {@code UNWIND}.\n\t */\n\tpublic static StatementBuilder.OngoingUnwind unwind(Expression expression) {\n\n\t\treturn Statement.builder().unwind(expression);\n\t}\n\n\t/**\n\t * Starts building a statement starting with an {@code UNWIND} clause. The expressions\n\t * passed will be turned into a list expression\n\t * @param expressions expressions to unwind\n\t * @return a new instance of {@link StatementBuilder.OngoingUnwind}\n\t */\n\tpublic static StatementBuilder.OngoingUnwind unwind(Expression... expressions) {\n\n\t\treturn Statement.builder().unwind(Cypher.listOf(expressions));\n\t}\n\n\t/**\n\t * Starts building a statement starting with an {@code UNWIND} clause. The expressions\n\t * passed will be turned into a list expression\n\t * @param expressions expressions to unwind\n\t * @return a new instance of {@link StatementBuilder.OngoingUnwind}\n\t * @since 2021.2.2\n\t */\n\tpublic static StatementBuilder.OngoingUnwind unwind(Collection<? extends Expression> expressions) {\n\n\t\treturn unwind(expressions.toArray(new Expression[] {}));\n\t}\n\n\t/**\n\t * Creates a new {@link SortItem} to be used as part of an {@link Order}.\n\t * @param expression the expression by which things should be sorted\n\t * @return a sort item, providing means to specify ascending or descending order\n\t */\n\tpublic static SortItem sort(Expression expression) {\n\n\t\treturn SortItem.create(expression, null);\n\t}\n\n\t/**\n\t * Creates a new {@link SortItem} to be used as part of an {@link Order}.\n\t * @param expression the expression by which things should be sorted\n\t * @param direction the direction to sort by. Defaults to\n\t * {@link SortItem.Direction#UNDEFINED}.\n\t * @return a sort item\n\t * @since 2021.1.0\n\t */\n\tpublic static SortItem sort(Expression expression, SortItem.Direction direction) {\n\n\t\treturn SortItem.create(expression, direction);\n\t}\n\n\t/**\n\t * Creates a map of expression from a list of key/value pairs.\n\t * @param keysAndValues a list of key and values. Must be an even number, with\n\t * alternating {@link String} and {@link Expression}\n\t * @return a new map expression.\n\t */\n\tpublic static MapExpression mapOf(Object... keysAndValues) {\n\n\t\treturn MapExpression.create(false, keysAndValues);\n\t}\n\n\t/**\n\t * Creates an alphabetically sorted map of expression from a list of key/value pairs.\n\t * @param keysAndValues a list of key and values. Must be an even number, with\n\t * alternating {@link String} and {@link Expression}\n\t * @return a new map expression.\n\t */\n\tpublic static MapExpression sortedMapOf(Object... keysAndValues) {\n\n\t\treturn MapExpression.create(true, keysAndValues);\n\t}\n\n\t/**\n\t * Creates a map of expression from a Java Map.\n\t * @param map a map to be turned into a MapExpression\n\t * @return a new map expression.\n\t * @since 2021.1.0\n\t */\n\tpublic static MapExpression asExpression(Map<String, Object> map) {\n\n\t\treturn MapExpression.create(map);\n\t}\n\n\t/**\n\t * Creates a {@link ListExpression list-expression} from several expressions.\n\t * @param expressions expressions to get combined into a list\n\t * @return a new instance of {@link ListExpression}\n\t */\n\tpublic static ListExpression listOf(Expression... expressions) {\n\n\t\treturn ListExpression.create(expressions);\n\t}\n\n\t/**\n\t * Creates a {@link ListExpression list-expression} from several expressions.\n\t * @param expressions expressions to get combined into a list\n\t * @return a new instance of {@link ListExpression}\n\t * @since 2021.2.2\n\t */\n\tpublic static ListExpression listOf(Collection<? extends Expression> expressions) {\n\n\t\treturn Cypher.listOf(expressions.toArray(new Expression[0]));\n\t}\n\n\t/**\n\t * Creates a new {@link Literal Literal&lt;?&gt;} from the given {@code object}.\n\t * @param object the object to represent.\n\t * @param <T> the type of the literal returned\n\t * @return a new {@link Literal Literal&lt;?&gt;}.\n\t * @throws UnsupportedLiteralException when the object cannot be represented as a\n\t * literal\n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static <T> Literal<T> literalOf(Object object) {\n\n\t\tif (object == null) {\n\t\t\treturn (Literal<T>) NullLiteral.INSTANCE;\n\t\t}\n\t\tif (object instanceof Literal<?>) {\n\t\t\treturn (Literal<T>) object;\n\t\t}\n\t\tif (object instanceof CharSequence charSequence) {\n\t\t\treturn (Literal<T>) new StringLiteral(charSequence);\n\t\t}\n\t\tif (object instanceof Character) {\n\t\t\treturn (Literal<T>) new StringLiteral(String.valueOf(object));\n\t\t}\n\t\tif (object instanceof Number number) {\n\t\t\treturn (Literal<T>) new NumberLiteral(number);\n\t\t}\n\t\tif (object instanceof TemporalAccessor temporalAccessor) {\n\t\t\treturn (Literal<T>) new TemporalLiteral(temporalAccessor);\n\t\t}\n\t\tif (object instanceof Duration duration) {\n\t\t\treturn (Literal<T>) DurationLiteral.of(duration);\n\t\t}\n\t\tif (object instanceof Period period) {\n\t\t\treturn (Literal<T>) PeriodLiteral.of(period);\n\t\t}\n\t\tif (object instanceof Parameter<?> parameter) {\n\t\t\treturn (Literal<T>) ParameterLiteral.of(parameter);\n\t\t}\n\t\tif (object instanceof Iterable || object.getClass().isArray()) {\n\t\t\tList<Literal<?>> elements = new ArrayList<>();\n\t\t\tConsumer<Object> handleElement = element -> {\n\t\t\t\tif (element instanceof Literal) {\n\t\t\t\t\telements.add((Literal<?>) element);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttry {\n\t\t\t\t\t\telements.add(Cypher.literalOf(element));\n\t\t\t\t\t}\n\t\t\t\t\tcatch (UnsupportedLiteralException ex) {\n\t\t\t\t\t\tthrow new UnsupportedLiteralException(\"Unsupported literal type in iterable.\", element);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t\tif (object.getClass().isArray()) {\n\t\t\t\tfor (int i = 0; i < Array.getLength(object); i++) {\n\t\t\t\t\thandleElement.accept(Array.get(object, i));\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\t((Iterable<?>) object).forEach(handleElement);\n\t\t\t}\n\n\t\t\tListLiteral listLiteral = new ListLiteral(elements);\n\t\t\treturn (Literal<T>) listLiteral;\n\t\t}\n\t\tif (object instanceof Map) {\n\t\t\tMap<String, Literal<?>> map = new LinkedHashMap<>();\n\t\t\tBiConsumer<Object, Object> handleEntry = (key, value) -> {\n\t\t\t\tif (!(key instanceof CharSequence || key instanceof Character)) {\n\t\t\t\t\tthrow new UnsupportedLiteralException(\"Unsupported literal map key (not a string/char type).\", key);\n\t\t\t\t}\n\t\t\t\tif (value instanceof Literal) {\n\t\t\t\t\tmap.put(key.toString(), (Literal<?>) value);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tmap.put(key.toString(), Cypher.literalOf(value));\n\t\t\t\t\t}\n\t\t\t\t\tcatch (UnsupportedLiteralException ex) {\n\t\t\t\t\t\tthrow new UnsupportedLiteralException(\"Unsupported literal type in map.\", value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t\t((Map<?, ?>) object).forEach(handleEntry);\n\t\t\tMapLiteral mapLiteral = new MapLiteral(map);\n\t\t\treturn (Literal<T>) mapLiteral;\n\t\t}\n\t\tif (object instanceof Boolean b) {\n\t\t\treturn (Literal<T>) BooleanLiteral.of(b);\n\t\t}\n\t\tthrow new UnsupportedLiteralException(object);\n\t}\n\n\t/**\n\t * {@return the `TRUE` literal}\n\t */\n\tpublic static Literal<Boolean> literalTrue() {\n\t\treturn BooleanLiteral.TRUE;\n\t}\n\n\t/**\n\t * {@return the `FALSE` literal}\n\t */\n\tpublic static Literal<Boolean> literalFalse() {\n\t\treturn BooleanLiteral.FALSE;\n\t}\n\n\t/**\n\t * {@return the `NULL` literal}\n\t */\n\tpublic static Literal<Void> literalNull() {\n\t\treturn NullLiteral.INSTANCE;\n\t}\n\n\t/**\n\t * Creates a {@code UNION} statement from several other statements. No checks are\n\t * applied for matching return types.\n\t * @param statements the statements to union.\n\t * @return a union statement.\n\t */\n\tpublic static UnionQuery union(Statement... statements) {\n\t\treturn unionImpl(false, statements);\n\t}\n\n\t/**\n\t * Creates a {@code UNION} statement from several other statements. No checks are\n\t * applied for matching return types.\n\t * @param statements the statements to union.\n\t * @return a union statement.\n\t * @since 2021.2.2\n\t */\n\tpublic static UnionQuery union(Collection<Statement> statements) {\n\t\treturn union(statements.toArray(new Statement[] {}));\n\t}\n\n\t/**\n\t * Creates a {@code UNION ALL} statement from several other statements. No checks are\n\t * applied for matching return types.\n\t * @param statements the statements to union.\n\t * @return a union statement.\n\t */\n\tpublic static Statement unionAll(Statement... statements) {\n\t\treturn unionImpl(true, statements);\n\t}\n\n\t/**\n\t * Creates a {@code UNION ALL} statement from several other statements. No checks are\n\t * applied for matching return types.\n\t * @param statements the statements to union.\n\t * @return a union statement.\n\t * @since 2021.2.2\n\t */\n\tpublic static Statement unionAll(Collection<Statement> statements) {\n\t\treturn unionAll(statements.toArray(new Statement[] {}));\n\t}\n\n\t/**\n\t * A {@literal RETURN} statement without a previous match.\n\t * @param expressions the elements to return\n\t * @return a buildable statement\n\t * @since 1.0.1\n\t */\n\tpublic static StatementBuilder.OngoingReadingAndReturn returning(Expression... expressions) {\n\t\treturn Statement.builder().returning(expressions);\n\t}\n\n\t/**\n\t * A {@literal RETURN} statement without a previous match.\n\t * @param expressions the expressions to return\n\t * @return a buildable statement\n\t * @since 2021.2.2\n\t */\n\tpublic static StatementBuilder.OngoingReadingAndReturn returning(Collection<? extends Expression> expressions) {\n\t\treturn Statement.builder().returning(expressions);\n\t}\n\n\t/**\n\t * Creates a list comprehension starting with a {@link Relationship} or a\n\t * {@link RelationshipChain chain of relationships}.\n\t * @param relationshipPattern the relationship pattern on which the new list\n\t * comprehension is based on.\n\t * @return an ongoing definition.\n\t * @since 2020.0.0\n\t */\n\tpublic static OngoingDefinitionWithPattern listBasedOn(RelationshipPattern relationshipPattern) {\n\t\treturn PatternComprehension.basedOn(relationshipPattern);\n\t}\n\n\t/**\n\t * Creates a list comprehension starting with a {@link NamedPath named path}.\n\t * @param namedPath the named path on which the new list comprehension is based on.\n\t * @return an ongoing definition.\n\t * @since 2020.1.1\n\t */\n\tpublic static OngoingDefinitionWithPattern listBasedOn(NamedPath namedPath) {\n\t\treturn PatternComprehension.basedOn(namedPath);\n\t}\n\n\t/**\n\t * Starts defining a {@link ListComprehension list comprehension}.\n\t * @param variable the variable to which each element of the list is assigned.\n\t * @return an ongoing definition of a list comprehension\n\t * @since 1.0.1\n\t */\n\tpublic static OngoingDefinitionWithVariable listWith(SymbolicName variable) {\n\t\treturn ListComprehension.with(variable);\n\t}\n\n\t/**\n\t * Escapes and quotes the {@code unquotedString} for safe usage in Neo4j-Browser and\n\t * Shell.\n\t * @param unquotedString an unquoted string\n\t * @return a quoted string with special chars escaped.\n\t */\n\tpublic static String quote(String unquotedString) {\n\t\treturn literalOf(unquotedString).asString();\n\t}\n\n\t/**\n\t * {@return generic case expression start}\n\t */\n\tpublic static Case caseExpression() {\n\t\treturn Case.create(null);\n\t}\n\n\t/**\n\t * Starts building a {@literal CASE} expression.\n\t * @param expression initial expression for the simple case statement\n\t * @return simple case expression start\n\t */\n\tpublic static Case caseExpression(Expression expression) {\n\t\treturn Case.create(expression);\n\t}\n\n\t/**\n\t * Starts defining a procedure call of the procedure with the given\n\t * {@literal procedureName}. That procedure name might be fully qualified - that is,\n\t * including a namespace - or just a simple name.\n\t * @param procedureName the procedure name of the procedure to call. Might be fully\n\t * qualified.\n\t * @return an ongoing definition of a call\n\t */\n\tpublic static OngoingStandaloneCallWithoutArguments call(String procedureName) {\n\n\t\tAssertions.hasText(procedureName, \"The procedure name must not be null or empty.\");\n\t\treturn call(procedureName.split(\"\\\\.\"));\n\t}\n\n\t/**\n\t * Starts defining a procedure call of the procedure with the given qualified name.\n\t * @param namespaceAndProcedure the procedure name of the procedure to call.\n\t * @return an ongoing definition of a call\n\t */\n\tpublic static OngoingStandaloneCallWithoutArguments call(String... namespaceAndProcedure) {\n\t\treturn Statement.call(namespaceAndProcedure);\n\t}\n\n\t/**\n\t * Starts defining a procedure call of the procedure with the given qualified name.\n\t * @param namespaceAndProcedure the procedure name of the procedure to call.\n\t * @return an ongoing definition of a call\n\t * @since 2021.2.2\n\t */\n\tpublic static OngoingStandaloneCallWithoutArguments call(Collection<String> namespaceAndProcedure) {\n\t\treturn call(namespaceAndProcedure.toArray(new String[] {}));\n\t}\n\n\t/**\n\t * Starts building a statement based on one subquery.\n\t * @param subquery the statement representing the subquery\n\t * @return a new ongoing read without any further conditions or returns.\n\t * @neo4j.version 4.0.0\n\t * @since 2020.1.2\n\t * @see ExposesSubqueryCall#call(Statement)\n\t */\n\t@Neo4jVersion(minimum = \"4.0.0\")\n\tpublic static StatementBuilder.OngoingReadingWithoutWhere call(Statement subquery) {\n\t\treturn Statement.builder().call(subquery);\n\t}\n\n\t/**\n\t * Creates a closed range with given boundaries.\n\t * @param targetExpression the target expression for the range\n\t * @param start the inclusive start\n\t * @param end the exclusive end\n\t * @return a range literal.\n\t * @since 2020.1.0\n\t */\n\tpublic static Expression subList(Expression targetExpression, Integer start, Integer end) {\n\n\t\treturn ListOperator.subList(targetExpression, Cypher.literalOf(start), Cypher.literalOf(end));\n\t}\n\n\t/**\n\t * Creates a closed range with given boundaries.\n\t * @param targetExpression the target expression for the range\n\t * @param start the inclusive start\n\t * @param end the exclusive end\n\t * @return a range literal.\n\t * @since 2020.1.0\n\t */\n\tpublic static Expression subList(Expression targetExpression, Expression start, Expression end) {\n\n\t\treturn ListOperator.subList(targetExpression, start, end);\n\t}\n\n\t/**\n\t * Creates an open range starting at {@code start}.\n\t * @param targetExpression the target expression for the range\n\t * @param start the inclusive start\n\t * @return a range literal.\n\t * @since 2020.1.0\n\t */\n\tpublic static Expression subListFrom(Expression targetExpression, Integer start) {\n\n\t\treturn ListOperator.subListFrom(targetExpression, Cypher.literalOf(start));\n\t}\n\n\t/**\n\t * Creates an open range starting at {@code start}.\n\t * @param targetExpression the target expression for the range\n\t * @param start the inclusive start\n\t * @return a range literal.\n\t * @since 2020.1.0\n\t */\n\tpublic static Expression subListFrom(Expression targetExpression, Expression start) {\n\n\t\treturn ListOperator.subListFrom(targetExpression, start);\n\t}\n\n\t/**\n\t * Creates an open range starting at {@code start}.\n\t * @param targetExpression the target expression for the range\n\t * @param end the exclusive end\n\t * @return a range literal.\n\t * @since 2020.1.0\n\t */\n\tpublic static Expression subListUntil(Expression targetExpression, Integer end) {\n\n\t\treturn ListOperator.subListUntil(targetExpression, Cypher.literalOf(end));\n\t}\n\n\t/**\n\t * Creates an open range starting at {@code start}.\n\t * @param targetExpression the target expression for the range\n\t * @param end the exclusive end\n\t * @return a range literal.\n\t * @since 2020.1.0\n\t */\n\tpublic static Expression subListUntil(Expression targetExpression, Expression end) {\n\n\t\treturn ListOperator.subListUntil(targetExpression, end);\n\t}\n\n\t/**\n\t * Creates a single valued range at {@code index}.\n\t * @param targetExpression the target expression for the range\n\t * @param index the index of the range\n\t * @return a range literal.\n\t * @since 2020.1.0\n\t */\n\tpublic static ListOperator valueAt(Expression targetExpression, Integer index) {\n\n\t\treturn valueAt(targetExpression, Cypher.literalOf(index));\n\t}\n\n\t/**\n\t * Creates a single valued range at {@code index}.\n\t * @param targetExpression the target expression for the range\n\t * @param index the index of the range\n\t * @return a range literal.\n\t * @since 2020.1.0\n\t */\n\tpublic static ListOperator valueAt(Expression targetExpression, Expression index) {\n\n\t\treturn ListOperator.valueAt(targetExpression, index);\n\t}\n\n\t/**\n\t * Creates an expression from a raw string fragment. No validation is performed on it.\n\t * If it is used as expression, you must make sure to define something that works as\n\t * expression.\n\t * <p>\n\t * This method expects exactly one placeholder in the form of {@literal $E} for any\n\t * argument passed with {@code mixedArgs}.\n\t * <p>\n\t * To use exactly the term {@literal $E} escape it like this: {@literal \\$E}\n\t * @param format a raw Cypher string\n\t * @param mixedArgs args to the Cypher string\n\t * @return an expression to reuse with the builder.\n\t * @since 2021.0.2\n\t */\n\tpublic static Expression raw(String format, Object... mixedArgs) {\n\n\t\treturn RawLiteral.create(format, mixedArgs);\n\t}\n\n\t/**\n\t * Starts building a statement from a raw Cypher string that might also have arguments\n\t * as supported through {@link Cypher#raw(String, Object...)}. Use this method as your\n\t * own risk and be aware that no checks are done on the Cypher.\n\t * @param rawCypher the raw Cypher statement to call\n\t * @param args optional args that replace placeholders in the {@code rawCypher}\n\t * @return ongoing sub-query definition based on the raw Cypher statement.\n\t * @since 2024.2.0\n\t */\n\tpublic static ExposesSubqueryCall.BuildableSubquery callRawCypher(String rawCypher, Object... args) {\n\t\treturn Statement.builder().callRawCypher(rawCypher, args);\n\t}\n\n\t/**\n\t * Creates a {@code RETURN} clause from a raw Cypher expression created via\n\t * {@link Cypher#raw(String, Object...)}. The expression maybe aliased but it must\n\t * resolve to a raw element\n\t * @param rawExpression must be a plain raw or an aliased raw expression. To\n\t * eventually render as valid Cypher, it must contain the {@code RETURN} keyword.\n\t * @return a match that can be build now\n\t * @since 2021.2.1\n\t */\n\tpublic static StatementBuilder.OngoingReadingAndReturn returningRaw(Expression rawExpression) {\n\t\treturn Statement.builder().returningRaw(rawExpression);\n\t}\n\n\t/**\n\t * Provides access to the foreign DSL adapter. Please make sure you have the necessary\n\t * runtime dependencies on the class path, otherwise you will see some kind of\n\t * {@link ClassNotFoundException} along various classes related to the foreign DSL.\n\t * @param expression the expression that should be adapted\n\t * @param <FE> the type of the expression\n\t * @return a foreign adapter\n\t * @throws IllegalArgumentException in case the object cannot be adapter\n\t * @since 2021.1.0\n\t */\n\tpublic static <FE> ForeignAdapter<FE> adapt(FE expression) {\n\n\t\tForeignAdapterFactory initializedForeignAdapterFactory = foreignAdapterFactory;\n\t\tif (initializedForeignAdapterFactory == null) {\n\t\t\tsynchronized (Cypher.class) {\n\t\t\t\tinitializedForeignAdapterFactory = foreignAdapterFactory;\n\t\t\t\tif (initializedForeignAdapterFactory == null) {\n\t\t\t\t\tforeignAdapterFactory = new ForeignAdapterFactory();\n\t\t\t\t\tinitializedForeignAdapterFactory = foreignAdapterFactory;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn initializedForeignAdapterFactory.getAdapterFor(expression);\n\t}\n\n\t/**\n\t * Starts building a {@code LOAD CSV} clause by using a periodic commit. The default\n\t * rate of the database will be used.\n\t * @return an ongoing definition of a {@code LOAD CSV} clause\n\t * @since 2021.2.1\n\t */\n\tpublic static ExposesLoadCSV usingPeriodicCommit() {\n\n\t\treturn usingPeriodicCommit(null);\n\t}\n\n\t/**\n\t * Starts building a {@code LOAD CSV} clause by using a periodic commit.\n\t * @param rate the rate to be used. No checks are done on the rate, the database will\n\t * verify valid values.\n\t * @return an ongoing definition of a {@code LOAD CSV} clause\n\t * @since 2021.2.1\n\t */\n\tpublic static ExposesLoadCSV usingPeriodicCommit(Integer rate) {\n\n\t\treturn LoadCSVStatementBuilder.usingPeriodicCommit(rate);\n\t}\n\n\t/**\n\t * Starts building a {@code LOAD CSV}. No headers are assumed.\n\t * @param from the URI to load data from. Any uri that is resolvable by the database\n\t * itself is valid.\n\t * @return an ongoing definition of a {@code LOAD CSV} clause\n\t * @since 2021.2.1\n\t */\n\tpublic static LoadCSVStatementBuilder.OngoingLoadCSV loadCSV(URI from) {\n\n\t\treturn loadCSV(from, false);\n\t}\n\n\t/**\n\t * Starts building a {@code LOAD CSV}.\n\t * @param from the URI to load data from. Any uri that is resolvable by the database\n\t * itself is valid.\n\t * @param withHeaders set to {@literal true} if the csv file contains header\n\t * @return an ongoing definition of a {@code LOAD CSV} clause\n\t */\n\tpublic static LoadCSVStatementBuilder.OngoingLoadCSV loadCSV(URI from, boolean withHeaders) {\n\n\t\treturn LoadCSVStatementBuilder.loadCSV(from, withHeaders);\n\t}\n\n\tprivate static UnionQuery unionImpl(boolean unionAll, Statement... statements) {\n\n\t\tAssertions.isTrue(statements != null && statements.length >= 2, \"At least two statements are required!\");\n\n\t\tint i = 0;\n\t\tUnionQueryImpl existingUnionQuery = null;\n\t\t@SuppressWarnings(\"squid:S2259\") // Really, we asserted it 4 lines above this one.\n\t\t\t\t\t\t\t\t\t\t\t// Thank you, sonar.\n\t\tboolean isUnionQuery = statements[0] instanceof UnionQueryImpl;\n\t\tif (isUnionQuery) {\n\t\t\texistingUnionQuery = (UnionQueryImpl) statements[0];\n\t\t\tAssertions.isTrue(existingUnionQuery.isAll() == unionAll, \"Cannot mix union and union all!\");\n\t\t\ti = 1;\n\t\t}\n\n\t\tList<Statement> listOfQueries = new ArrayList<>();\n\t\tdo {\n\t\t\tAssertions.isTrue(statements[i] instanceof SingleQuery || statements[i] instanceof ClausesBasedStatement,\n\t\t\t\t\t\"Can only union single queries!\");\n\t\t\tlistOfQueries.add(statements[i]);\n\t\t}\n\t\twhile (++i < statements.length);\n\n\t\tif (existingUnionQuery == null) {\n\t\t\treturn UnionQueryImpl.create(unionAll, listOfQueries);\n\t\t}\n\t\telse {\n\t\t\treturn existingUnionQuery.addAdditionalQueries(listOfQueries);\n\t\t}\n\t}\n\n\t/**\n\t * Tries to format this expression into something human-readable. Not all expressions\n\t * are supported\n\t * @param expression an expression to format\n\t * @return a human-readable string\n\t * @throws IllegalArgumentException when the expression cannot be formatted\n\t * @since 2021.3.2\n\t */\n\tpublic static String format(Expression expression) {\n\t\treturn Expressions.format(expression);\n\t}\n\n\t/**\n\t * Decorates the given statement by prepending a static {@literal USE} clause.\n\t * @param target the target. This might be a single database or a constituent of a\n\t * composite database. This value will be escaped if necessary. If it contains a\n\t * {@literal .}, both the first and second part will be escaped individually.\n\t * @param statement the statement to decorate\n\t * @return the new buildable statement\n\t * @since 2023.0.0\n\t */\n\tpublic static UseStatement use(String target, Statement statement) {\n\t\treturn DecoratedQuery.decorate(statement, UseClauseImpl.of(target));\n\t}\n\n\t/**\n\t * Decorates the given statement by prepending a dynamic {@literal USE} clause. A\n\t * dynamic {@literal USE} clause will utilize {@code graph.byName} to resolve the\n\t * target database.\n\t * @param target a parameter that must resolve to a Cypher string.\n\t * @param statement the statement to decorate\n\t * @return the new buildable statement\n\t * @since 2023.0.0\n\t */\n\tpublic static UseStatement use(Parameter<?> target, Statement statement) {\n\t\treturn DecoratedQuery.decorate(statement, UseClauseImpl.of(target));\n\t}\n\n\t/**\n\t * Decorates the given statement by prepending a dynamic {@literal USE} clause. A\n\t * dynamic {@literal USE} clause will utilize {@code graph.byName} to resolve the\n\t * target database.\n\t * @param target a string expression\n\t * @param statement the statement to decorate\n\t * @return the new buildable statement\n\t * @since 2023.0.0\n\t */\n\tpublic static UseStatement use(StringLiteral target, Statement statement) {\n\t\treturn DecoratedQuery.decorate(statement, UseClauseImpl.of(target));\n\t}\n\n\t/**\n\t * Decorates the given statement by prepending a dynamic {@literal USE} clause. A\n\t * dynamic {@literal USE} clause will utilize {@code graph.byName} to resolve the\n\t * target database unless {@link Cypher#graphByName(Expression)} has already been\n\t * used.\n\t * @param target the name of a variable pointing to the graph or constituent\n\t * @param statement the statement to decorate\n\t * @return the new buildable statement\n\t * @since 2023.4.0\n\t */\n\tpublic static UseStatement use(Expression target, Statement statement) {\n\t\treturn DecoratedQuery.decorate(statement, UseClauseImpl.of(target));\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code lhs} includes all elements\n\t * present in {@code rhs}.\n\t * @param lhs argument that is tested whether it contains all values in {@code rhs} or\n\t * not\n\t * @param rhs the reference collection\n\t * @return an \"includesAll\" comparison\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition includesAll(Expression lhs, Expression rhs) {\n\t\treturn Conditions.includesAll(lhs, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code lhs} includes any element\n\t * present in {@code rhs}.\n\t * @param lhs argument that is tested whether it contains any values in {@code rhs} or\n\t * not\n\t * @param rhs the reference collection\n\t * @return a \"not_includes\" comparison\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition includesAny(Expression lhs, Expression rhs) {\n\t\treturn Conditions.includesAny(lhs, rhs);\n\t}\n\n\t/**\n\t * A condition testing if the given relationship pattern matches.\n\t * @param relationshipPattern the pattern being evaluated in a condition\n\t * @return a new condition matching the given pattern\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition matching(RelationshipPattern relationshipPattern) {\n\t\treturn Conditions.matching(relationshipPattern);\n\t}\n\n\t/**\n\t * Creates a condition that matches if the right hand side is a regular expression\n\t * that matches the left hand side via {@code =~}.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a \"matches\" comparison\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition matches(Expression lhs, Expression rhs) {\n\t\treturn Conditions.matches(lhs, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that matches if both expressions are equals according to\n\t * {@code =}.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return an \"equals\" comparison\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition isEqualTo(Expression lhs, Expression rhs) {\n\t\treturn Conditions.isEqualTo(lhs, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that matches if both expressions are equals according to\n\t * {@code <>}.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a \"not equals\" comparison\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition isNotEqualTo(Expression lhs, Expression rhs) {\n\t\treturn Conditions.isNotEqualTo(lhs, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that matches if the left hand side is less than the right hand\n\t * side.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a \"less than\" comparison\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition lt(Expression lhs, Expression rhs) {\n\t\treturn Conditions.lt(lhs, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that matches if the left hand side is less than or equal the\n\t * right hand side.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a \"less than or equal\" comparison\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition lte(Expression lhs, Expression rhs) {\n\t\treturn Conditions.lte(lhs, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that matches if the left hand side is greater than or equal the\n\t * right hand side.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a \"greater than or equal\" comparison\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition gte(Expression lhs, Expression rhs) {\n\t\treturn Conditions.gte(lhs, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that matches if the left hand side is greater than the right\n\t * hand side.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a \"greater than\" comparison\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition gt(Expression lhs, Expression rhs) {\n\t\treturn Conditions.gt(lhs, rhs);\n\t}\n\n\t/**\n\t * Negates the given condition.\n\t * @param condition the condition to negate. Must not be null.\n\t * @return the negated condition.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition not(Condition condition) {\n\t\treturn Conditions.not(condition);\n\t}\n\n\t/**\n\t * Negates the given pattern element: The pattern must not matche to be included in\n\t * the result.\n\t * @param pattern the pattern to negate. Must not be null.\n\t * @return a condition that evaluates to true when the pattern does not match.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition not(RelationshipPattern pattern) {\n\t\treturn Conditions.not(pattern);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code lhs} starts with the\n\t * {@code rhs}.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a new condition.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition startsWith(Expression lhs, Expression rhs) {\n\t\treturn Conditions.startsWith(lhs, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code lhs} contains with the\n\t * {@code rhs}.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a new condition.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition contains(Expression lhs, Expression rhs) {\n\t\treturn Conditions.contains(lhs, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code lhs} ends with the {@code rhs}.\n\t * @param lhs the left hand side of the comparison\n\t * @param rhs the right hand side of the comparison\n\t * @return a new condition.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition endsWith(Expression lhs, Expression rhs) {\n\t\treturn Conditions.endsWith(lhs, rhs);\n\t}\n\n\t/**\n\t * Creates a placeholder condition which is not rendered in the final statement but is\n\t * useful while chaining conditions together.\n\t * @return a placeholder condition.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition noCondition() {\n\t\treturn Conditions.noCondition();\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code expression} is {@literal null}.\n\t * @param expression the expression to check for {@literal null}\n\t * @return a new condition.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition isNull(Expression expression) {\n\t\treturn Conditions.isNull(expression);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether the {@code expression} is not\n\t * {@literal null}.\n\t * @param expression the expression to check for {@literal null}\n\t * @return a new condition.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition isNotNull(Expression expression) {\n\t\treturn Conditions.isNotNull(expression);\n\t}\n\n\t/**\n\t * Creates a new condition based on a function invocation for the {@code isEmpty()}\n\t * function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-isempty\">isEmpty</a>.\n\t * <p>\n\t * The argument {@code e} must refer to an expression that evaluates to a list for\n\t * {@code isEmpty()} to work\n\t * @param expression an expression referring to a list\n\t * @return a function call for {@code isEmpty()} for a list\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition isEmpty(Expression expression) {\n\t\treturn Predicates.isEmpty(expression);\n\t}\n\n\t/**\n\t * Creates a |{@literal true} condition.\n\t * @return a condition that is always true.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition isTrue() {\n\t\treturn Conditions.isTrue();\n\t}\n\n\t/**\n\t * Creates a |{@literal false} condition.\n\t * @return a condition that is always false.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition isFalse() {\n\t\treturn Conditions.isFalse();\n\t}\n\n\t/**\n\t * Checks if a given object has the given labels or types.\n\t * @param symbolicName reference to the entity that should be checked for labels or\n\t * types\n\t * @param labelsOrTypes the list of labels or types to check for\n\t * @return a condition that checks whether a node has a set of given labels or a\n\t * relationship a set of given types.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition hasLabelsOrType(SymbolicName symbolicName, String... labelsOrTypes) {\n\t\treturn HasLabelCondition.create(symbolicName, labelsOrTypes);\n\t}\n\n\t/**\n\t * Checks if a given object has the given labels or types.\n\t * @param symbolicName reference to the entity that should be checked for labels or\n\t * types\n\t * @param labels the expression of labels or types to check for\n\t * @return a condition that checks whether a node has a set of given labels or a\n\t * relationship a set of given types.\n\t * @since 2025.1.0\n\t */\n\tpublic static Condition hasLabelsOrType(SymbolicName symbolicName, Labels labels) {\n\t\treturn HasLabelCondition.create(symbolicName, labels);\n\t}\n\n\t/**\n\t * Creates a {@literal COUNT} sub-query expressions from at least one pattern.\n\t * @param requiredPattern one pattern is required\n\t * @param patternElement optional pattern\n\t * @return the immutable {@link CountExpression}\n\t * @since 2023.9.0\n\t */\n\tpublic static CountExpression count(PatternElement requiredPattern, PatternElement... patternElement) {\n\t\treturn Expressions.count(requiredPattern, patternElement);\n\t}\n\n\t/**\n\t * Creates a {@literal COUNT} with an inner {@literal UNION} sub-query.\n\t * @param union the union that will be the source of the {@literal COUNT} sub-query\n\t * @return the immutable {@link CountExpression}\n\t * @since 2023.9.0\n\t */\n\tpublic static CountExpression count(UnionQuery union) {\n\t\treturn Expressions.count(union);\n\t}\n\n\t/**\n\t * Creates a {@literal COUNT} from a full statement, including its filters and\n\t * conditions. The statement may or may not have a {@literal RETURN} clause. It must\n\t * however not contain any updates. While it would render syntactically correct\n\t * Cypher, Neo4j does not support updates inside counting sub-queries.\n\t * @param statement the statement to be passed to {@code count{}}\n\t * @param imports optional imports to be used in the statement (will be imported with\n\t * {@literal WITH})\n\t * @return a counting sub-query.\n\t * @since 2023.9.0\n\t */\n\tpublic static CountExpression count(Statement statement, IdentifiableElement... imports) {\n\t\treturn Expressions.count(statement, imports);\n\t}\n\n\t/**\n\t * Creates a {@literal COUNT} expression based on a list of pattern.\n\t * @param pattern the list of patterns that shall be counted\n\t * @param where an optional where-clause\n\t * @return a count expression.\n\t * @since 2023.9.0\n\t */\n\tpublic static CountExpression count(List<PatternElement> pattern, Where where) {\n\t\treturn Expressions.count(pattern, where);\n\t}\n\n\t/**\n\t * Creates a {@literal COLLECT} subquery from a statement, including its filters and\n\t * conditions. The statement must return exactly one column. It must however not\n\t * contain any updates. While it would render syntactically correct Cypher, Neo4j does\n\t * not support updates inside counting sub-queries.\n\t * @param statement the statement to be passed to {@code COLLECT{}}\n\t * @return a collecting sub-query.\n\t * @since 2023.9.0\n\t */\n\tpublic static Expression collect(Statement statement) {\n\t\treturn Expressions.collect(statement);\n\t}\n\n\t/**\n\t * Returns the name of the given expression or the expression itself if it isn't\n\t * named.\n\t * @param <T> the tyoe of the expression\n\t * @param expression possibly named with a non-empty symbolic name.\n\t * @return the name of the expression if the expression is named or the expression\n\t * itself.\n\t * @since 2023.9.0\n\t */\n\tpublic static <T extends Expression> Expression nameOrExpression(T expression) {\n\t\treturn Expressions.nameOrExpression(expression);\n\t}\n\n\tpublic static SymbolicName[] createSymbolicNames(String[] variables) {\n\t\treturn Expressions.createSymbolicNames(variables);\n\t}\n\n\tpublic static SymbolicName[] createSymbolicNames(Named[] variables) {\n\t\treturn Expressions.createSymbolicNames(variables);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code elementId{}}.\n\t * @param node the node for which the element id should be retrieved\n\t * @return a function call for {@code elementId()} on a node.\n\t * @since 2023.9.0\n\t */\n\t@Neo4jVersion(minimum = \"5.0.0\")\n\tpublic static FunctionInvocation elementId(Node node) {\n\t\treturn Functions.elementId(node);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code elementId{}}.\n\t * @param relationship the relationship for which the element id should be retrieved\n\t * @return a function call for {@code elementId()} on a relationship.\n\t * @since 2023.9.0\n\t */\n\t@Neo4jVersion(minimum = \"5.0.0\")\n\tpublic static FunctionInvocation elementId(Relationship relationship) {\n\t\treturn Functions.elementId(relationship);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code keys{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-keys\">keys</a>.\n\t * @param node the node which keys should be returned.\n\t * @return a function call for {@code keys()} on an expression.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation keys(Node node) {\n\t\treturn Functions.keys(node);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code keys{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-keys\">keys</a>.\n\t * @param relationship the relationship which keys should be returned.\n\t * @return a function call for {@code keys()} on an expression.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation keys(Relationship relationship) {\n\t\treturn Functions.keys(relationship);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code keys{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-keys\">keys</a>.\n\t * @param expression the expressions which keys should be returned. Must resolve to a\n\t * node, relationship or map.\n\t * @return a function call for {@code keys()} on an expression.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation keys(Expression expression) {\n\t\treturn Functions.keys(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code labels{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-labels\">labels</a>.\n\t * @param node the node for which the labels should be retrieved\n\t * @return a function call for {@code labels()} on a node.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation labels(Node node) {\n\t\treturn Functions.labels(node);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code labels{}}. The {@link SymbolicName\n\t * symbolic name} {@code  node} must point to a node. This can't be checked during\n\t * compile time, so please make sure of that.\n\t * <p>\n\t * See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-labels\">labels</a>.\n\t * @param node the node for which the labels should be retrieved\n\t * @return a function call for {@code labels()} on a node.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation labels(SymbolicName node) {\n\t\treturn Functions.labels(node);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code type{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-type\">type</a>.\n\t * @param relationship the relationship for which the type should be retrieved\n\t * @return a function call for {@code type()} on a relationship.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation type(Relationship relationship) {\n\t\treturn Functions.type(relationship);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code type{}}. The {@link SymbolicName symbolic\n\t * name} {@code relationship} must point to a relationship. This can't be checked\n\t * during compile time, so please make sure of that.\n\t * <p>\n\t * See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-type\">type</a>.\n\t * @param relationship the relationship for which the type should be retrieved\n\t * @return a function call for {@code type()} on a relationship.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation type(SymbolicName relationship) {\n\t\treturn Functions.type(relationship);\n\t}\n\n\t/**\n\t * Creates an instance of the {@code count} function.\n\t * @param node the named node to be counted\n\t * @return a function call for {@code count()} for one named node\n\t * @since 2023.9.0\n\t * @see #count(Expression)\n\t */\n\tpublic static FunctionInvocation count(Node node) {\n\t\treturn Functions.count(node);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code count()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-count\">count</a>.\n\t * @param expression an expression describing the things to count.\n\t * @return a function call for {@code count()} for an expression like\n\t * {@link Cypher#asterisk()} etc.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation count(Expression expression) {\n\t\treturn Functions.count(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for a {@code count()} function with {@code DISTINCT}\n\t * added.\n\t * @param node the named node to be counted\n\t * @return a function call for {@code count()} for one named node\n\t * @since 2023.9.0\n\t * @see #countDistinct(Expression)\n\t */\n\tpublic static FunctionInvocation countDistinct(Node node) {\n\t\treturn Functions.countDistinct(node);\n\t}\n\n\t/**\n\t * Creates a function invocation for a {@code count()} function with {@code DISTINCT}\n\t * added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-count\">count</a>.\n\t * @param expression an expression describing the things to count.\n\t * @return a function call for {@code count()} for an expression like\n\t * {@link Cypher#asterisk()} etc.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation countDistinct(Expression expression) {\n\t\treturn Functions.countDistinct(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code properties())} on nodes.\n\t * @param node the node who's properties should be returned.\n\t * @return a function call for {@code properties())}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation properties(Node node) {\n\t\treturn Functions.properties(node);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code properties())} on relationships.\n\t * @param relationship the relationship who's properties should be returned.\n\t * @return a function call for {@code properties())}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation properties(Relationship relationship) {\n\t\treturn Functions.properties(relationship);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code properties())} on maps.\n\t * @param map the map whose properties should be returned.\n\t * @return a function call for {@code properties())}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation properties(MapExpression map) {\n\t\treturn Functions.properties(map);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code coalesce()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-coalesce\">coalesce</a>.\n\t * @param expressions one or more expressions to be coalesced\n\t * @return a function call for {@code coalesce}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation coalesce(Expression... expressions) {\n\t\treturn Functions.coalesce(expressions);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code left()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-left\">left</a>.\n\t * @param expression an expression resolving to a string\n\t * @param length desired length\n\t * @return a function call for {@code left()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation left(Expression expression, Expression length) {\n\t\treturn Functions.left(expression, length);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code ltrim()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-ltrim\">ltrim</a>.\n\t * @param expression an expression resolving to a string\n\t * @return a function call for {@code ltrim()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation ltrim(Expression expression) {\n\t\treturn Functions.ltrim(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code replace()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-ltrim\">replace</a>.\n\t * @param original an expression that returns a string\n\t * @param search an expression that specifies the string to be replaced in\n\t * {@code original}.\n\t * @param replace an expression that specifies the replacement string.\n\t * @return a function call for {@code replace()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation replace(Expression original, Expression search, Expression replace) {\n\t\treturn Functions.replace(original, search, replace);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code reverse()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-reverse\">reverse</a>.\n\t * @param original an expression that returns a string\n\t * @return a function call for {@code reverse()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation reverse(Expression original) {\n\t\treturn Functions.reverse(original);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code right()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-left\">right</a>.\n\t * @param expression an expression resolving to a string\n\t * @param length desired length\n\t * @return a function call for {@code right()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation right(Expression expression, Expression length) {\n\t\treturn Functions.right(expression, length);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code rtrim()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-rtrim\">rtrim</a>.\n\t * @param expression an expression resolving to a string\n\t * @return a function call for {@code rtrim()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation rtrim(Expression expression) {\n\t\treturn Functions.rtrim(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code substring()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-substring\">rtrim</a>.\n\t * @param original an expression resolving to a string\n\t * @param start an expression that returns a positive integer, denoting the position\n\t * at which the substring will begin.\n\t * @param length an expression that returns a positive integer, denoting how many\n\t * characters of original will be returned.\n\t * @return a function call for {@code substring()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation substring(Expression original, Expression start, Expression length) {\n\t\treturn Functions.substring(original, start, length);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code toLower()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-toLower\">toLower</a>.\n\t * @param expression an expression resolving to a string\n\t * @return a function call for {@code toLower()} for one expression\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation toLower(Expression expression) {\n\t\treturn Functions.toLower(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code toUpper()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-toUpper\">toUpper</a>.\n\t * @param expression an expression resolving to a string\n\t * @return a function call for {@code toLower()} for one expression\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation toUpper(Expression expression) {\n\t\treturn Functions.toUpper(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code trim()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-trim\">trim</a>.\n\t * @param expression an expression resolving to a string\n\t * @return a function call for {@code trim()} for one expression\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation trim(Expression expression) {\n\t\treturn Functions.trim(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code split()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-split\">split</a>.\n\t * @param expression an expression resolving to a string that should be split\n\t * @param delimiter the delimiter on which to split\n\t * @return a function call for {@code split()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation split(Expression expression, Expression delimiter) {\n\t\treturn Functions.split(expression, delimiter);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code split()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-split\">split</a>.\n\t * @param expression an expression resolving to a string that should be split\n\t * @param delimiter the delimiter on which to split\n\t * @return a function call for {@code split()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation split(Expression expression, String delimiter) {\n\t\treturn Functions.split(expression, delimiter);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code size()} function. {@code size} can be\n\t * applied to\n\t * <ul>\n\t * <li><a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-size\">a\n\t * list</a></li>\n\t * <li><a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-size-of-string\">to\n\t * a string</a></li>\n\t * </ul>\n\t * @param expression the expression who's size is to be returned\n\t * @return a function call for {@code size()} for one expression\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation size(Expression expression) {\n\t\treturn Functions.size(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code size()} function. {@code size} can be\n\t * applied to\n\t * <ul>\n\t * <li><a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-size-of-pattern-expression\">to\n\t * a pattern expression</a></li>\n\t * </ul>\n\t * @param pattern the pattern for which {@code size()} should be invoked.\n\t * @return a function call for {@code size()} for a pattern\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation size(RelationshipPattern pattern) {\n\t\treturn Functions.size(pattern);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code exists()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-exists\">exists</a>.\n\t * @param expression the expression whose existence is to be evaluated\n\t * @return a function call for {@code exists()} for one expression\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation exists(Expression expression) {\n\t\treturn Functions.exists(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code distance()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-distance\">exists</a>.\n\t * Both points need to be in the same coordinate system.\n\t * @param point1 point 1\n\t * @param point2 point 2\n\t * @return a function call for {@code distance()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation distance(Expression point1, Expression point2) {\n\t\treturn Functions.distance(point1, point2);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code point()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point\">point</a>.\n\t * @param parameterMap the map of parameters for {@code point()}\n\t * @return a function call for {@code point()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation point(MapExpression parameterMap) {\n\t\treturn Functions.point(parameterMap);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code point()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point\">point</a>.\n\t * <p>\n\t * This generic expression variant is useful for referencing a point inside a\n\t * parameter or another map.\n\t * @param expression an expression resolving to a valid map of parameters for\n\t * {@code point()}\n\t * @return a function call for {@code point()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation point(Expression expression) {\n\t\treturn Functions.point(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code point()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point\">point</a>.\n\t * @param parameter a parameter referencing a {@code point()}\n\t * @return a function call for {@code point()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation point(Parameter<?> parameter) {\n\t\treturn Functions.point(parameter);\n\t}\n\n\t/**\n\t * Convenience method for creating a 2d cartesian point.\n\t * @param x the x coordinate\n\t * @param y the y coordinate\n\t * @return a function call for {@code point()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation cartesian(double x, double y) {\n\t\treturn Functions.cartesian(x, y);\n\t}\n\n\t/**\n\t * Convenience method for creating a 2d coordinate in the WGS 84 coordinate system.\n\t * @param longitude the longitude\n\t * @param latitude the latitude\n\t * @return a function call for {@code point()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation coordinate(double longitude, double latitude) {\n\t\treturn Functions.coordinate(longitude, latitude);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code point.withinBBox} function. See\n\t * <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-withinBBox\">point.withinBBox</a>.\n\t * @param point the point to check\n\t * @param lowerLeft the lower left point of the bounding box (south-west coordinate)\n\t * @param upperRight the upper right point of the bounding box (north-east coordinate)\n\t * @return a function call for {@code point.withinBBox}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation withinBBox(Expression point, Expression lowerLeft, Expression upperRight) {\n\t\treturn Functions.withinBBox(point, lowerLeft, upperRight);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code avg()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-avg\">avg</a>.\n\t * @param expression the things to average\n\t * @return a function call for {@code avg()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation avg(Expression expression) {\n\t\treturn Functions.avg(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code avg()} function with {@code DISTINCT}\n\t * added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-avg\">avg</a>.\n\t * @param expression the things to average\n\t * @return a function call for {@code avg()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation avgDistinct(Expression expression) {\n\t\treturn Functions.avgDistinct(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code collect()} function.\n\t * @param variable the named thing to collect\n\t * @return a function call for {@code collect()}\n\t * @since 2023.9.0\n\t * @see #collect(Expression)\n\t */\n\tpublic static FunctionInvocation collect(Named variable) {\n\t\treturn Functions.collect(variable);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code collect()} function with\n\t * {@code DISTINCT} added.\n\t * @param variable the named thing to collect\n\t * @return a function call for {@code collect()}\n\t * @since 2023.9.0\n\t * @see #collect(Expression)\n\t */\n\tpublic static FunctionInvocation collectDistinct(Named variable) {\n\t\treturn Functions.collectDistinct(variable);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code collect()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-collect\">collect</a>.\n\t * @param expression the things to collect\n\t * @return a function call for {@code collect()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation collect(Expression expression) {\n\t\treturn Functions.collect(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code collect()} function with\n\t * {@code DISTINCT} added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-collect\">collect</a>.\n\t * @param expression the things to collect\n\t * @return a function call for {@code collect()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation collectDistinct(Expression expression) {\n\t\treturn Functions.collectDistinct(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code max()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-max\">max</a>.\n\t * @param expression a list from which the maximum element value is returned\n\t * @return a function call for {@code max()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation max(Expression expression) {\n\t\treturn Functions.max(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code max()} function with {@code DISTINCT}\n\t * added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-max\">max</a>.\n\t * @param expression a list from which the maximum element value is returned\n\t * @return a function call for {@code max()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation maxDistinct(Expression expression) {\n\t\treturn Functions.maxDistinct(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code min()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-min\">min</a>.\n\t * @param expression a list from which the minimum element value is returned\n\t * @return a function call for {@code min()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation min(Expression expression) {\n\t\treturn Functions.min(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code min()} function with {@code DISTINCT}\n\t * added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-min\">min</a>.\n\t * @param expression a list from which the minimum element value is returned\n\t * @return a function call for {@code min()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation minDistinct(Expression expression) {\n\t\treturn Functions.minDistinct(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code percentileCont()} function. See\n\t * <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-percentilecont\">percentileCont</a>.\n\t * @param expression a numeric expression\n\t * @param percentile a numeric value between 0.0 and 1.0\n\t * @return a function call for {@code percentileCont()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation percentileCont(Expression expression, Number percentile) {\n\t\treturn Functions.percentileCont(expression, percentile);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code percentileCont()} function with\n\t * {@code DISTINCT} added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-percentilecont\">percentileCont</a>.\n\t * @param expression a numeric expression\n\t * @param percentile a numeric value between 0.0 and 1.0\n\t * @return a function call for {@code percentileCont()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation percentileContDistinct(Expression expression, Number percentile) {\n\t\treturn Functions.percentileContDistinct(expression, percentile);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code percentileDisc()} function. See\n\t * <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-percentiledisc\">percentileDisc</a>.\n\t * @param expression a numeric expression\n\t * @param percentile a numeric value between 0.0 and 1.0\n\t * @return a function call for {@code percentileDisc()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation percentileDisc(Expression expression, Number percentile) {\n\t\treturn Functions.percentileDisc(expression, percentile);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code percentileDisc()} function with\n\t * {@code DISTINCT} added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-percentiledisc\">percentileDisc</a>.\n\t * @param expression a numeric expression\n\t * @param percentile a numeric value between 0.0 and 1.0\n\t * @return a function call for {@code percentileDisc()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation percentileDiscDistinct(Expression expression, Number percentile) {\n\t\treturn Functions.percentileDiscDistinct(expression, percentile);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code stDev()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-stdev\">stDev</a>.\n\t * @param expression a numeric expression\n\t * @return a function call for {@code stDev()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation stDev(Expression expression) {\n\t\treturn Functions.stDev(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code stDev()} function with\n\t * {@code DISTINCT} added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-stdev\">stDev</a>.\n\t * @param expression a numeric expression\n\t * @return a function call for {@code stDev()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation stDevDistinct(Expression expression) {\n\t\treturn Functions.stDevDistinct(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code stDevP()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-stdevp\">stDevP</a>.\n\t * @param expression a numeric expression\n\t * @return a function call for {@code stDevP()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation stDevP(Expression expression) {\n\t\treturn Functions.stDevP(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code stDevP()} function with\n\t * {@code DISTINCT} added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-stdevp\">stDevP</a>.\n\t * @param expression a numeric expression\n\t * @return a function call for {@code stDevP()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation stDevPDistinct(Expression expression) {\n\t\treturn Functions.stDevPDistinct(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code sum()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-sum\">sum</a>.\n\t * @param expression an expression returning a set of numeric values\n\t * @return a function call for {@code sum()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation sum(Expression expression) {\n\t\treturn Functions.sum(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code sum()} function with {@code DISTINCT}\n\t * added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-sum\">sum</a>.\n\t * @param expression an expression returning a set of numeric values\n\t * @return a function call for {@code sum()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation sumDistinct(Expression expression) {\n\t\treturn Functions.sumDistinct(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code range()} function.\n\t * @param start the range's start\n\t * @param end the range's end\n\t * @return a function call for {@code range()}\n\t * @since 2023.9.0\n\t * @see #range(Expression, Expression)\n\t */\n\tpublic static FunctionInvocation range(Integer start, Integer end) {\n\t\treturn Functions.range(start, end);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code range()} function.\n\t * @param start the range's start\n\t * @param end the range's end\n\t * @return a function call for {@code range()}\n\t * @since 2023.9.0\n\t * @see #range(Expression, Expression, Expression)\n\t */\n\tpublic static FunctionInvocation range(Expression start, Expression end) {\n\t\treturn Functions.range(start, end);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code range()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-range\">range</a>.\n\t * @param start the range's start\n\t * @param end the range's end\n\t * @param step the range's step\n\t * @return a function call for {@code range()}\n\t * @since 2023.9.0\n\t * @see #range(Expression, Expression, Expression)\n\t */\n\tpublic static FunctionInvocation range(Integer start, Integer end, Integer step) {\n\t\treturn Functions.range(start, end, step);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code range()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-range\">range</a>.\n\t * @param start the range's start\n\t * @param end the range's end\n\t * @param step the range's step\n\t * @return a function call for {@code range()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation range(Expression start, Expression end, Expression step) {\n\t\treturn Functions.range(start, end, step);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code head()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-head\">head</a>.\n\t * @param expression a list from which the head element is returned\n\t * @return a function call for {@code head()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation head(Expression expression) {\n\t\treturn Functions.head(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code last()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-last\">last</a>.\n\t * @param expression a list from which the last element is returned\n\t * @return a function call for {@code last()}\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation last(Expression expression) {\n\t\treturn Functions.last(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code nodes{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-nodes\">nodes</a>.\n\t * @param path the path for which the number of nodes should be retrieved\n\t * @return a function call for {@code nodes()} on a path.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation nodes(NamedPath path) {\n\t\treturn Functions.nodes(path);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code nodes{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-nodes\">nodes</a>.\n\t * @param symbolicName the symbolic name of a path for which the number of nodes\n\t * should be retrieved\n\t * @return a function call for {@code nodes{}} on a path represented by a symbolic\n\t * name.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation nodes(SymbolicName symbolicName) {\n\t\treturn Functions.nodes(symbolicName);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code relationships{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-relationships\">relationships</a>.\n\t * @param path the path for which the relationships should be retrieved\n\t * @return a function call for {@code relationships()} on a path.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation relationships(NamedPath path) {\n\t\treturn Functions.relationships(path);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code relationships{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-relationships\">relationships</a>.\n\t * @param symbolicName the symbolic name of a path for which the relationships should\n\t * be retrieved\n\t * @return a function call for {@code relationships()} on a path represented by a\n\t * symbolic name.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation relationships(SymbolicName symbolicName) {\n\t\treturn Functions.relationships(symbolicName);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code startNode{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-startnode\">startNode</a>.\n\t * @param relationship the relationship for which the start node be retrieved\n\t * @return a function call for {@code startNode()} on a path.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation startNode(Relationship relationship) {\n\t\treturn Functions.startNode(relationship);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code endNode{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-endnode\">endNode</a>.\n\t * @param relationship the relationship for which the end node be retrieved\n\t * @return a function call for {@code endNode()} on a path.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation endNode(Relationship relationship) {\n\t\treturn Functions.endNode(relationship);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date()}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * This is the most simple form.\n\t * @return a function call for {@code date()}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation date() {\n\t\treturn Functions.date();\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * @param year the year\n\t * @param month the month\n\t * @param day the day\n\t * @return a function call for {@code date({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation calendarDate(Integer year, Integer month, Integer day) {\n\t\treturn Functions.calendarDate(year, month, day);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * @param year the year\n\t * @param week the optional week\n\t * @param dayOfWeek the optional day of the week\n\t * @return a function call for {@code date({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation weekDate(Integer year, Integer week, Integer dayOfWeek) {\n\t\treturn Functions.weekDate(year, week, dayOfWeek);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * @param year the year\n\t * @param quarter the optional week\n\t * @param dayOfQuarter the optional day of the week\n\t * @return a function call for {@code date({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation quarterDate(Integer year, Integer quarter, Integer dayOfQuarter) {\n\t\treturn Functions.quarterDate(year, quarter, dayOfQuarter);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * @param year the year\n\t * @param ordinalDay the ordinal day of the year.\n\t * @return a function call for {@code date({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation ordinalDate(Integer year, Integer ordinalDay) {\n\t\treturn Functions.ordinalDate(year, ordinalDay);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * This is the most generic form.\n\t * @param components the map to pass to {@code date({})}\n\t * @return a function call for {@code date({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation date(MapExpression components) {\n\t\treturn Functions.date(components);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * This creates a date from a string.\n\t * @param temporalValue a string representing a temporal value.\n\t * @return a function call for {@code date({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation date(String temporalValue) {\n\t\treturn Functions.date(temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * This creates a date from a string.\n\t * @param temporalValue an expression representing a temporal value.\n\t * @return a function call for {@code date({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation date(Expression temporalValue) {\n\t\treturn Functions.date(temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code datetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/datetime/\">datetime</a>.\n\t * @return a function call for {@code datetime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation datetime() {\n\t\treturn Functions.datetime();\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code datetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/datetime/\">datetime</a>.\n\t * @param timeZone the timezone to use when creating the temporal instance\n\t * @return a function call for {@code datetime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation datetime(TimeZone timeZone) {\n\t\treturn Functions.datetime(timeZone);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code datetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/datetime/\">datetime</a>.\n\t * This is the most generic form.\n\t * @param components the map to pass to {@code datetime({})}\n\t * @return a function call for {@code datetime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation datetime(MapExpression components) {\n\t\treturn Functions.datetime(components);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code datetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">datetime</a>.\n\t * This creates a datetime from a string.\n\t * @param temporalValue a string representing a temporal value.\n\t * @return a function call for {@code datetime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation datetime(String temporalValue) {\n\t\treturn Functions.datetime(temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code datetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">datetime</a>.\n\t * This creates a datetime from a string.\n\t * @param temporalValue an expression representing a temporal value.\n\t * @return a function call for {@code date({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation datetime(Expression temporalValue) {\n\t\treturn Functions.datetime(temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localdatetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localdatetime</a>.\n\t * @return a function call for {@code localdatetime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation localdatetime() {\n\t\treturn Functions.localdatetime();\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localdatetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localdatetime</a>.\n\t * @param timeZone the timezone to use when creating the temporal instance\n\t * @return a function call for {@code localdatetime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation localdatetime(TimeZone timeZone) {\n\t\treturn Functions.localdatetime(timeZone);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localdatetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localdatetime</a>.\n\t * This is the most generic form.\n\t * @param components the map to pass to {@code localdatetime({})}\n\t * @return a function call for {@code localdatetime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation localdatetime(MapExpression components) {\n\t\treturn Functions.localdatetime(components);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localdatetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localdatetime</a>.\n\t * This creates a localdatetime from a string.\n\t * @param temporalValue a string representing a temporal value.\n\t * @return a function call for {@code localdatetime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation localdatetime(String temporalValue) {\n\t\treturn Functions.localdatetime(temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localdatetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localdatetime</a>.\n\t * This creates a localdatetime from a string.\n\t * @param temporalValue an expression representing a temporal value.\n\t * @return a function call for {@code localdatetime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation localdatetime(Expression temporalValue) {\n\t\treturn Functions.localdatetime(temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localtime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localtime</a>.\n\t * @return a function call for {@code localtime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation localtime() {\n\t\treturn Functions.localtime();\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localtime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localtime/\">localtime</a>.\n\t * @param timeZone the timezone to use when creating the temporal instance\n\t * @return a function call for {@code localtime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation localtime(TimeZone timeZone) {\n\t\treturn Functions.localtime(timeZone);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localtime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localtime</a>.\n\t * This is the most generic form.\n\t * @param components the map to pass to {@code localtime({})}\n\t * @return a function call for {@code localtime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation localtime(MapExpression components) {\n\t\treturn Functions.localtime(components);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localtime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localtime/\">localtime</a>.\n\t * This creates a localtime from a string.\n\t * @param temporalValue a string representing a temporal value.\n\t * @return a function call for {@code localtime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation localtime(String temporalValue) {\n\t\treturn Functions.localtime(temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localtime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localtime/\">localtime</a>.\n\t * This creates a localtime from a string.\n\t * @param temporalValue an expression representing a temporal value.\n\t * @return a function call for {@code localtime({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation localtime(Expression temporalValue) {\n\t\treturn Functions.localtime(temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code time({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/time/\">time</a>.\n\t * @return a function call for {@code time({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation time() {\n\t\treturn Functions.time();\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code time({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/time/\">time</a>.\n\t * @param timeZone the timezone to use when creating the temporal instance\n\t * @return a function call for {@code time({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation time(TimeZone timeZone) {\n\t\treturn Functions.time(timeZone);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code time({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/time/\">time</a>.\n\t * This is the most generic form.\n\t * @param components the map to pass to {@code time({})}\n\t * @return a function call for {@code time({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation time(MapExpression components) {\n\t\treturn Functions.time(components);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code time({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/time/\">time</a>.\n\t * This creates a time from a string.\n\t * @param temporalValue a string representing a temporal value.\n\t * @return a function call for {@code time({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation time(String temporalValue) {\n\t\treturn Functions.time(temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code time({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/time/\">time</a>.\n\t * This creates a time from a string.\n\t * @param temporalValue an expression representing a temporal value.\n\t * @return a function call for {@code time({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation time(Expression temporalValue) {\n\t\treturn Functions.time(temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code duration({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/duration/\">duration</a>.\n\t * This is the most generic form.\n\t * @param components the map to pass to {@code duration({})}\n\t * @return a function call for {@code duration({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation duration(MapExpression components) {\n\t\treturn Functions.duration(components);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code duration({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/duration/\">duration</a>.\n\t * This creates a duration from a string.\n\t * @param temporalAmount a string representing a temporal amount.\n\t * @return a function call for {@code duration({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation duration(String temporalAmount) {\n\t\treturn Functions.duration(temporalAmount);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code duration({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/duration/\">duration</a>.\n\t * This creates a duration from a string.\n\t * @param temporalAmount an expression representing a temporal amount.\n\t * @return a function call for {@code duration({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation duration(Expression temporalAmount) {\n\t\treturn Functions.duration(temporalAmount);\n\t}\n\n\t/**\n\t * Starts building a function invocation for {@code reduce({})}.\n\t * @param variable the closure will have a variable introduced in its context. We\n\t * decide here which variable to use.\n\t * @return an ongoing definition for a function call to {@code reduce({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static Reduction.OngoingDefinitionWithVariable reduce(SymbolicName variable) {\n\t\treturn Functions.reduce(variable);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code abs({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-abs\">abs</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code abs({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation abs(Expression expression) {\n\t\treturn Functions.abs(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code ceil({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-ceil\">ceil</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code ceil({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation ceil(Expression expression) {\n\t\treturn Functions.ceil(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code floor({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-floor\">floor</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code floor({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation floor(Expression expression) {\n\t\treturn Functions.floor(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code rand({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-rand\">rand</a>.\n\t * @return a function call for {@code rand({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation rand() {\n\t\treturn Functions.rand();\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code round({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-round\">round</a>.\n\t * @param value the value to round\n\t * @param expression additional parameters, length must be 0, 1 or 2: First entry is\n\t * the precision, second is the rounding mode\n\t * @return a function call for {@code round({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation round(Expression value, Expression... expression) {\n\t\treturn Functions.round(value, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code sign({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-sign\">sign</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code sign({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation sign(Expression expression) {\n\t\treturn Functions.sign(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code e({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-e\">e</a>.\n\t * @return a function call for {@code e({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation e() {\n\t\treturn Functions.e();\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code exp({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-exp\">exp</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code exp({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation exp(Expression expression) {\n\t\treturn Functions.exp(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code log({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-log\">log</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code log({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation log(Expression expression) {\n\t\treturn Functions.log(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code log10({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-log10\">log10</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code log10({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation log10(Expression expression) {\n\t\treturn Functions.log10(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code sqrt({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-sqrt\">sqrt</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code sqrt({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation sqrt(Expression expression) {\n\t\treturn Functions.sqrt(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code acos({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-acos\">acos</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code acos({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation acos(Expression expression) {\n\t\treturn Functions.acos(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code asin({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-asin\">asin</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code asin({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation asin(Expression expression) {\n\t\treturn Functions.asin(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code atan({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-atan\">atan</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code atan({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation atan(Expression expression) {\n\t\treturn Functions.atan(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code atan2({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-atan2\">atan2</a>.\n\t * @param y the y value of a point\n\t * @param x the x value of a point\n\t * @return a function call for {@code atan2({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation atan2(Expression y, Expression x) {\n\t\treturn Functions.atan2(y, x);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code cos({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-cos\">cos</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code cos({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation cos(Expression expression) {\n\t\treturn Functions.cos(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code cot({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-cot\">cot</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code cot({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation cot(Expression expression) {\n\t\treturn Functions.cot(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code degrees({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-degrees\">degrees</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code degrees({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation degrees(Expression expression) {\n\t\treturn Functions.degrees(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code haversin({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-haversin\">haversin</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code haversin({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation haversin(Expression expression) {\n\t\treturn Functions.haversin(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code pi({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-pi\">pi</a>.\n\t * @return a function call for {@code pi({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation pi() {\n\t\treturn Functions.pi();\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code radians({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-radians\">radians</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code radians({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation radians(Expression expression) {\n\t\treturn Functions.radians(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code sin({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-sin\">sin</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code sin({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation sin(Expression expression) {\n\t\treturn Functions.sin(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code tan({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-tan\">tan</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code tan({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation tan(Expression expression) {\n\t\treturn Functions.tan(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code toInteger({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-tointeger\">toInteger</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code toInteger({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation toInteger(Expression expression) {\n\t\treturn Functions.toInteger(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code toString({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-tostring\">toString</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code toString({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation toString(Expression expression) {\n\t\treturn Functions.toString(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code toStringOrNull({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-toStringOrNull\">toStringOrNull</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code toStringOrNull({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation toStringOrNull(Expression expression) {\n\t\treturn Functions.toStringOrNull(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code toFloat({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-tofloat\">toFloat</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code toFloat({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation toFloat(Expression expression) {\n\t\treturn Functions.toFloat(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code toBoolean({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-toboolean\">toBoolean</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code toBoolean({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation toBoolean(Expression expression) {\n\t\treturn Functions.toBoolean(expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code linenumber({})}. Only applicable inside an\n\t * {@code LOAD CSV} clause.\n\t * @return a function call for {@code linenumber({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation linenumber() {\n\t\treturn Functions.linenumber();\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code file({})}. Only applicable inside an\n\t * {@code LOAD CSV} clause.\n\t * @return a function call for {@code file({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation file() {\n\t\treturn Functions.file();\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code randomUUID({})}. Only applicable inside an\n\t * {@code LOAD CSV} clause.\n\t * @return a function call for {@code randomUUID({})}.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation randomUUID() {\n\t\treturn Functions.randomUUID();\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code length()}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-length\">length</a>.\n\t * @param path the path for which the length should be retrieved\n\t * @return a function call for {@code length()} on a path.\n\t * @since 2023.9.0\n\t */\n\tpublic static FunctionInvocation length(NamedPath path) {\n\t\treturn Functions.length(path);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code graph.names()}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/graph/#functions-graph-names\">graph.names</a>.\n\t * @return a function call for {@code graph.names()}.\n\t * @since 2023.9.0\n\t */\n\t@Neo4jVersion(minimum = \"5.0.0\")\n\tpublic static FunctionInvocation graphNames() {\n\t\treturn Functions.graphNames();\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code graph.propertiesByName()}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/graph/#functions-graph-propertiesByName\">graph.propertiesByName</a>.\n\t * @param name the name of the graph\n\t * @return a function call for {@code graph.propertiesByName()}.\n\t * @since 2023.9.0\n\t */\n\t@Neo4jVersion(minimum = \"5.0.0\")\n\tpublic static FunctionInvocation graphPropertiesByName(Expression name) {\n\t\treturn Functions.graphPropertiesByName(name);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code graph.byName()}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/graph/#functions-graph-byname\">graph.byName</a>.\n\t * @param name the name of the graph\n\t * @return a function call for {@code graph.byName()}.\n\t * @since 2023.9.0\n\t */\n\t@Neo4jVersion(minimum = \"5.0.0\")\n\tpublic static FunctionInvocation graphByName(Expression name) {\n\t\treturn Functions.graphByName(name);\n\t}\n\n\t/**\n\t * Create a new map projection with the given, mixed content.\n\t * @param name the symbolic name of this project\n\t * @param content the projected content\n\t * @return a new map projection\n\t * @since 2023.9.0\n\t */\n\tpublic static MapProjection createProjection(SymbolicName name, Object... content) {\n\t\treturn MapProjection.create(name, content);\n\t}\n\n\t/**\n\t * Creates an unary minus operation.\n\t * @param e the expression to which the unary minus should be applied. We don't check\n\t * if it's a numeric expression, but in hindsight to generate semantically correct\n\t * Cypher, it's recommended that is one.\n\t * @return an unary minus operation.\n\t * @since 2023.9.0\n\t */\n\tpublic static Operation minus(Expression e) {\n\t\treturn Operations.minus(e);\n\t}\n\n\t/**\n\t * Creates an unary plus operation.\n\t * @param e the expression to which the unary plus should be applied. We don't check\n\t * if it's a numeric expression, but in hindsight to generate semantically correct\n\t * Cypher, it's recommended that is one.\n\t * @return an unary plus operation.\n\t * @since 2023.9.0\n\t */\n\tpublic static Expression plus(Expression e) {\n\t\treturn Operations.plus(e);\n\t}\n\n\tpublic static Operation concat(Expression op1, Expression op2) {\n\t\treturn Operations.concat(op1, op2);\n\t}\n\n\tpublic static Operation add(Expression op1, Expression op2) {\n\t\treturn Operations.add(op1, op2);\n\t}\n\n\tpublic static Operation subtract(Expression op1, Expression op2) {\n\t\treturn Operations.subtract(op1, op2);\n\t}\n\n\tpublic static Operation multiply(Expression op1, Expression op2) {\n\t\treturn Operations.multiply(op1, op2);\n\t}\n\n\tpublic static Operation divide(Expression op1, Expression op2) {\n\t\treturn Operations.divide(op1, op2);\n\t}\n\n\tpublic static Operation remainder(Expression op1, Expression op2) {\n\t\treturn Operations.remainder(op1, op2);\n\t}\n\n\tpublic static Operation pow(Expression op1, Expression op2) {\n\t\treturn Operations.pow(op1, op2);\n\t}\n\n\t/**\n\t * Creates a {@code =} operation. The left hand side should resolve to a property or\n\t * to something which has labels or types to modify and the right hand side should\n\t * either be new properties or labels.\n\t * @param target the target that should be modified\n\t * @param value the new value of the target\n\t * @return a new operation.\n\t * @since 2023.9.0\n\t */\n\tpublic static Operation set(Expression target, Expression value) {\n\t\treturn Operations.set(target, value);\n\t}\n\n\t/**\n\t * Creates a {@code +=} operation. The left hand side must resolve to a container\n\t * (either a node or a relationship) of properties and the right hand side must be a\n\t * map of new or updated properties\n\t * @param target the target container that should be modified\n\t * @param value the new properties\n\t * @return a new operation.\n\t * @since 2023.9.0\n\t */\n\tpublic static Operation mutate(Expression target, MapExpression value) {\n\t\treturn Operations.mutate(target, value);\n\t}\n\n\t/**\n\t * Creates a {@code +=} operation. The left hand side must resolve to a container\n\t * (either a node or a relationship) of properties and the right hand side must be a\n\t * map of new or updated properties\n\t * @param target the target container that should be modified\n\t * @param value the new properties\n\t * @return a new operation.\n\t * @since 2023.9.0\n\t */\n\tpublic static Operation mutate(Expression target, Expression value) {\n\t\treturn Operations.mutate(target, value);\n\t}\n\n\t/**\n\t * Creates an operation adding one or more labels to a given {@link Node node}.\n\t * @param target the target of the new labels\n\t * @param label the labels to be added\n\t * @return a set operation\n\t * @since 2023.9.0\n\t */\n\tpublic static Operation setLabel(Node target, String... label) {\n\t\treturn Operations.set(target, label);\n\t}\n\n\t/**\n\t * Creates an operation adding dynamic labels to a {@link Node node}.\n\t * @param target the target of the new labels\n\t * @param label the labels to be added\n\t * @return a set operation\n\t * @since 2025.1.0\n\t */\n\tpublic static Operation setLabel(Node target, Labels label) {\n\t\treturn Operations.set(target, label);\n\t}\n\n\t/**\n\t * Creates an operation removing one or more labels from a given {@link Node node}.\n\t * @param target the target of the remove operation\n\t * @param label the labels to be removed\n\t * @return a remove operation\n\t * @since 2023.9.0\n\t */\n\tpublic static Operation removeLabel(Node target, String... label) {\n\t\treturn Operations.remove(target, label);\n\t}\n\n\t/**\n\t * Creates a new condition based on a function invocation for the {@code exists()}\n\t * function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-exists\">exists</a>.\n\t * @param property the property to be passed to {@code exists()}\n\t * @return a function call for {@code exists()} for one property\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition exists(Property property) {\n\t\treturn Predicates.exists(property);\n\t}\n\n\t/**\n\t * Creates a new condition based on a function invocation for the {@code exists()}\n\t * function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-exists\">exists</a>.\n\t * @param pattern the pattern to be passed to {@code exists()}\n\t * @return a function call for {@code exists()} for one pattern\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition exists(RelationshipPattern pattern) {\n\t\treturn Predicates.exists(pattern);\n\t}\n\n\t/**\n\t * Creates a new condition via an <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/syntax/expressions/#existential-subqueries\">existential\n\t * sub-query</a>. The statement may or may not have a {@literal  RETURN} clause. It\n\t * must however not contain any updates. While it would render syntactically correct\n\t * Cypher, Neo4j does not support updates inside existential sub-queries.\n\t * @param statement the statement to be passed to {@code exists{}}\n\t * @param imports optional imports to be used in the statement (will be imported with\n\t * {@literal WITH})\n\t * @return an existential sub-query.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition exists(Statement statement, IdentifiableElement... imports) {\n\t\treturn Predicates.exists(statement, imports);\n\t}\n\n\t/**\n\t * Creates a new condition via an <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/syntax/expressions/#existential-subqueries\">existential\n\t * sub-query</a> based on the list of patterns.\n\t * @param pattern the pattern that must exists\n\t * @return an existential sub-query.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition exists(PatternElement pattern) {\n\t\treturn Predicates.exists(pattern);\n\t}\n\n\t/**\n\t * Creates a new condition via an <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/syntax/expressions/#existential-subqueries\">existential\n\t * sub-query</a> based on the list of patterns.\n\t * @param pattern the list of patterns that must exists\n\t * @return an existential sub-query.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition exists(List<PatternElement> pattern) {\n\t\treturn Predicates.exists(pattern);\n\t}\n\n\t/**\n\t * Creates a new condition via an <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/syntax/expressions/#existential-subqueries\">existential\n\t * sub-query</a> based on the list of patterns and an optional {@link Where\n\t * where-clause}.\n\t * @param pattern the list of patterns that must exists\n\t * @param where an optional where-clause\n\t * @return an existential sub-query.\n\t * @since 2023.9.0\n\t */\n\tpublic static Condition exists(List<PatternElement> pattern, Where where) {\n\t\treturn Predicates.exists(pattern, where);\n\t}\n\n\t/**\n\t * Starts building an {@literal ALL} predicate.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code all()} predicate function\n\t * @since 2023.9.0\n\t * @see #all(SymbolicName)\n\t */\n\tpublic static OngoingListBasedPredicateFunction all(String variable) {\n\t\treturn Predicates.all(variable);\n\t}\n\n\t/**\n\t * Starts building a new condition based on a function invocation for the\n\t * {@code all()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-all\">exists</a>.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code all()} predicate function\n\t * @since 2023.9.0\n\t */\n\tpublic static OngoingListBasedPredicateFunction all(SymbolicName variable) {\n\t\treturn Predicates.all(variable);\n\t}\n\n\t/**\n\t * Starts building a {@literal ANY} predicate.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code any()} predicate function\n\t * @since 2023.9.0\n\t * @see #any(SymbolicName)\n\t */\n\tpublic static OngoingListBasedPredicateFunction any(String variable) {\n\t\treturn Predicates.any(variable);\n\t}\n\n\t/**\n\t * Starts building a new condition based on a function invocation for the\n\t * {@code any()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-any\">exists</a>.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code any()} predicate function\n\t * @since 2023.9.0\n\t */\n\tpublic static OngoingListBasedPredicateFunction any(SymbolicName variable) {\n\t\treturn Predicates.any(variable);\n\t}\n\n\t/**\n\t * Starts building a {@literal NONE} predicate.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code none()} predicate function\n\t * @since 2023.9.0\n\t * @see #none(SymbolicName)\n\t */\n\tpublic static OngoingListBasedPredicateFunction none(String variable) {\n\t\treturn Predicates.none(variable);\n\t}\n\n\t/**\n\t * Starts building a new condition based on a function invocation for the\n\t * {@code none()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-none\">exists</a>.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code none()} predicate function\n\t * @since 2023.9.0\n\t */\n\tpublic static OngoingListBasedPredicateFunction none(SymbolicName variable) {\n\t\treturn Predicates.none(variable);\n\t}\n\n\t/**\n\t * Starts building a {@literal SINGLE} predicate.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code single()} predicate function\n\t * @since 2023.9.0\n\t * @see #single(SymbolicName)\n\t */\n\tpublic static OngoingListBasedPredicateFunction single(String variable) {\n\t\treturn Predicates.single(variable);\n\t}\n\n\t/**\n\t * Starts building a new condition based on a function invocation for the\n\t * {@code single()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-single\">single</a>.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code single()} predicate function\n\t * @since 2023.9.0\n\t */\n\tpublic static OngoingListBasedPredicateFunction single(SymbolicName variable) {\n\t\treturn Predicates.single(variable);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/DecoratedQuery.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Statement.UseStatement;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * A decorated statement. Used for <code>EXPLAIN</code> and <code>PROFILE</code>'d\n * queries.\n *\n * @author Michael J. Simons\n * @since 2020.1.2\n */\n@API(status = INTERNAL, since = \"2020.1.2\")\nsealed class DecoratedQuery extends AbstractStatement implements UseStatement {\n\n\tprivate final Visitable decoration;\n\n\tprivate final Statement target;\n\n\tprivate DecoratedQuery(Statement target, Visitable decoration) {\n\t\tthis.decoration = decoration;\n\t\tthis.target = target;\n\t}\n\n\tstatic DecoratedQuery explain(Statement target) {\n\n\t\treturn DecoratedQuery.decorate(target, Decoration.EXPLAIN);\n\t}\n\n\tstatic DecoratedQuery profile(Statement target) {\n\n\t\treturn DecoratedQuery.decorate(target, Decoration.PROFILE);\n\t}\n\n\tprivate static DecoratedQuery decorate(Statement target, Decoration decoration) {\n\n\t\tif (target instanceof DecoratedQuery decoratedQuery && !(decoratedQuery.decoration instanceof Use)) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot explain an already explained or profiled query.\");\n\t\t}\n\n\t\tif (target instanceof ResultStatement && Decoration.PROFILE.equals(decoration)) {\n\t\t\treturn new DecoratedQueryWithResult(target);\n\t\t}\n\n\t\treturn new DecoratedQuery(target, decoration);\n\t}\n\n\tstatic DecoratedQuery decorate(Statement target, Use use) {\n\n\t\tif (target instanceof DecoratedQuery decoratedQuery) {\n\t\t\tString message;\n\t\t\tif (decoratedQuery.decoration instanceof Decoration decoration) {\n\t\t\t\tmessage = decoration.name() + (decoration.name().endsWith(\"E\") ? \"'\" : \"'e\")\n\t\t\t\t\t\t+ \"d statements are not supported inside USE clauses\";\n\t\t\t}\n\t\t\telse { // Right now the only other decoration is the Use clause.\n\t\t\t\tmessage = \"Nested USE clauses are not supported\";\n\t\t\t}\n\t\t\tthrow new IllegalArgumentException(message);\n\t\t}\n\n\t\treturn new DecoratedQuery(target, use);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.decoration.accept(visitor);\n\t\tthis.target.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic boolean doesReturnOrYield() {\n\t\tif (this.decoration instanceof Use) {\n\t\t\treturn this.target.doesReturnOrYield();\n\t\t}\n\t\treturn super.doesReturnOrYield();\n\t}\n\n\tprivate enum Decoration implements Visitable {\n\n\t\tEXPLAIN, PROFILE;\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn RendererBridge.render(this);\n\t\t}\n\n\t}\n\n\t/**\n\t * Only profiled queries can have a result statement.\n\t */\n\tstatic final class DecoratedQueryWithResult extends DecoratedQuery implements ResultStatement {\n\n\t\tprivate DecoratedQueryWithResult(Statement target) {\n\t\t\tsuper(target, Decoration.PROFILE);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/DefaultLoadCSVStatementBuilder.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.net.URI;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.internal.LoadCSV;\nimport org.neo4j.cypherdsl.core.internal.UsingPeriodicCommit;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * A builder for the {@literal LOAD CSV} statement.\n *\n * @author Michael J. Simons\n * @since 2021.2.1\n */\n@API(status = INTERNAL, since = \"2021.2.1\")\nfinal class DefaultLoadCSVStatementBuilder extends DefaultStatementBuilder implements LoadCSVStatementBuilder {\n\n\tprivate final UsingPeriodicCommit usingPeriodicCommit;\n\n\tprivate final LoadCSV loadCSV;\n\n\tprivate DefaultLoadCSVStatementBuilder(UsingPeriodicCommit usingPeriodicCommit, LoadCSV loadCSV) {\n\t\tsuper(usingPeriodicCommit, loadCSV);\n\n\t\tthis.usingPeriodicCommit = usingPeriodicCommit;\n\t\tthis.loadCSV = loadCSV;\n\t}\n\n\tprivate DefaultLoadCSVStatementBuilder(DefaultStatementBuilder source, UsingPeriodicCommit usingPeriodicCommit,\n\t\t\tLoadCSV loadCSV) {\n\t\tsuper(source, usingPeriodicCommit, loadCSV);\n\t\tthis.usingPeriodicCommit = usingPeriodicCommit;\n\t\tthis.loadCSV = loadCSV;\n\t}\n\n\tstatic DefaultLoadCSVStatementBuilder create(PrepareLoadCSVStatementImpl config, String alias,\n\t\t\tDefaultStatementBuilder source) {\n\n\t\t// It should be reasonable safe to keep that immutable object around\n\t\tfinal LoadCSV loadCSV = new LoadCSV(config.uri, config.withHeaders, alias);\n\t\treturn (source != null) ? new DefaultLoadCSVStatementBuilder(source, config.usingPeriodicCommit, loadCSV)\n\t\t\t\t: new DefaultLoadCSVStatementBuilder(config.usingPeriodicCommit, loadCSV);\n\t}\n\n\t@Override\n\tpublic StatementBuilder withFieldTerminator(String fieldTerminator) {\n\t\treturn new DefaultStatementBuilder(this.usingPeriodicCommit, this.loadCSV.withFieldTerminator(fieldTerminator));\n\t}\n\n\tstatic final class PrepareLoadCSVStatementImpl implements ExposesLoadCSV, OngoingLoadCSV {\n\n\t\tprivate final UsingPeriodicCommit usingPeriodicCommit;\n\n\t\tprivate final DefaultStatementBuilder source;\n\n\t\tprivate URI uri;\n\n\t\tprivate boolean withHeaders;\n\n\t\tPrepareLoadCSVStatementImpl(Integer rate) {\n\n\t\t\tthis.usingPeriodicCommit = new UsingPeriodicCommit(rate);\n\t\t\tthis.source = null;\n\t\t}\n\n\t\tPrepareLoadCSVStatementImpl(URI uri, boolean withHeaders) {\n\n\t\t\tthis(uri, withHeaders, null);\n\t\t}\n\n\t\tPrepareLoadCSVStatementImpl(URI uri, boolean withHeaders, DefaultStatementBuilder source) {\n\n\t\t\tthis.usingPeriodicCommit = null;\n\n\t\t\tthis.uri = uri;\n\t\t\tthis.withHeaders = withHeaders;\n\t\t\tthis.source = source;\n\t\t}\n\n\t\t@Override\n\t\tpublic LoadCSVStatementBuilder as(String alias) {\n\n\t\t\treturn DefaultLoadCSVStatementBuilder.create(this, alias, this.source);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingLoadCSV loadCSV(URI newUri, boolean newWithHeaders) {\n\n\t\t\tthis.uri = newUri;\n\t\t\tthis.withHeaders = newWithHeaders;\n\t\t\treturn this;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/DefaultStatementBuilder.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.net.URI;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.EnumSet;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.StatementBuilder.BuildableMatchAndUpdate;\nimport org.neo4j.cypherdsl.core.StatementBuilder.BuildableOngoingMergeAction;\nimport org.neo4j.cypherdsl.core.StatementBuilder.OngoingMatchAndUpdate;\nimport org.neo4j.cypherdsl.core.StatementBuilder.OngoingMerge;\nimport org.neo4j.cypherdsl.core.StatementBuilder.OngoingReadingWithWhere;\nimport org.neo4j.cypherdsl.core.StatementBuilder.OngoingReadingWithoutWhere;\nimport org.neo4j.cypherdsl.core.StatementBuilder.OngoingUpdate;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.internal.ProcedureName;\nimport org.neo4j.cypherdsl.core.internal.YieldItems;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Default implementation of the {@link StatementBuilder} and related operations.\n *\n * @author Michael J. Simons\n * @author Gerrit Meier\n * @author Romain Rossi\n * @since 1.0\n */\n@API(status = INTERNAL, since = \"2021.2.1\")\nclass DefaultStatementBuilder implements StatementBuilder, OngoingUpdate, OngoingMerge, OngoingReadingWithWhere,\n\t\tOngoingReadingWithoutWhere, OngoingMatchAndUpdate, BuildableMatchAndUpdate, BuildableOngoingMergeAction,\n\t\tExposesSubqueryCall.BuildableSubquery, StatementBuilder.VoidCall, StatementBuilder.Terminal {\n\n\tprivate static final EnumSet<UpdateType> MERGE_OR_CREATE = EnumSet.of(UpdateType.CREATE, UpdateType.MERGE);\n\n\tprivate static final EnumSet<UpdateType> SET = EnumSet.of(UpdateType.SET, UpdateType.MUTATE);\n\n\t/**\n\t * Current list of reading or update clauses to be generated.\n\t */\n\tprivate final List<Visitable> currentSinglePartElements = new ArrayList<>();\n\n\t/**\n\t * A list of already build withs.\n\t */\n\tprivate final List<MultiPartElement> multiPartElements = new ArrayList<>();\n\n\t/**\n\t * The latest ongoing match.\n\t */\n\tprivate MatchBuilder currentOngoingMatch;\n\n\t/**\n\t * The latest ongoing update to be built.\n\t */\n\tprivate DefaultStatementWithUpdateBuilder currentOngoingUpdate;\n\n\t/**\n\t * Default constructor. Builder can be preloaded with visitables.\n\t * @param visitables a set of visitables. {@literal NULL} values will be skipped.\n\t */\n\tDefaultStatementBuilder(Visitable... visitables) {\n\n\t\taddVisitables(visitables);\n\t}\n\n\t/**\n\t * A copy constructor.\n\t * @param source the source\n\t * @param visitables a set of additional visitables. {@literal NULL} values will be\n\t * skipped.\n\t */\n\tDefaultStatementBuilder(DefaultStatementBuilder source, Visitable... visitables) {\n\n\t\tthis.currentSinglePartElements.addAll(source.currentSinglePartElements);\n\t\tthis.currentOngoingMatch = source.currentOngoingMatch;\n\t\tthis.currentOngoingUpdate = source.currentOngoingUpdate;\n\t\tthis.multiPartElements.addAll(source.multiPartElements);\n\n\t\taddVisitables(visitables);\n\t}\n\n\t/**\n\t * Creates a builder for an UPDATE clause. The vargs is list of pattern or\n\t * expressions. In case {@code updateType} is of {@link UpdateType#MERGE} or\n\t * {@link UpdateType#CREATE} they will be treated as pattern, otherwise as expression.\n\t * @param updateType the update type to create\n\t * @param patternOrExpressions a list of pattern or expression\n\t * @param <T> the type of {@code patternOrExpressions}\n\t * @return ongoing builder\n\t */\n\t@SafeVarargs\n\t@SuppressWarnings(\"varargs\") // WTH IDEA?\n\tprivate static <T extends Visitable> UpdatingClauseBuilder getUpdatingClauseBuilder(UpdateType updateType,\n\t\t\tT... patternOrExpressions) {\n\n\t\tboolean mergeOrCreate = MERGE_OR_CREATE.contains(updateType);\n\t\tString message = mergeOrCreate ? \"At least one pattern is required.\"\n\t\t\t\t: \"At least one modifying expressions is required.\";\n\t\tAssertions.notNull(patternOrExpressions, message);\n\t\tAssertions.notEmpty(patternOrExpressions, message);\n\n\t\tif (mergeOrCreate) {\n\t\t\tfinal List<PatternElement> patternElements = Arrays.stream(patternOrExpressions)\n\t\t\t\t.map(PatternElement.class::cast)\n\t\t\t\t.toList();\n\t\t\tif (updateType == UpdateType.CREATE) {\n\t\t\t\treturn new AbstractUpdatingClauseBuilder.CreateBuilder(patternElements);\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn new AbstractUpdatingClauseBuilder.MergeBuilder(patternElements);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tList<Expression> expressions = Arrays.stream(patternOrExpressions).map(Expression.class::cast).toList();\n\t\t\tExpressionList expressionList = new ExpressionList(\n\t\t\t\t\tSET.contains(updateType) ? prepareSetExpressions(updateType, expressions) : expressions);\n\t\t\treturn switch (updateType) {\n\t\t\t\tcase DETACH_DELETE -> () -> new Delete(expressionList, true);\n\t\t\t\tcase DELETE -> () -> new Delete(expressionList, false);\n\t\t\t\tcase SET, MUTATE -> () -> new Set(expressionList);\n\t\t\t\tcase REMOVE -> () -> new Remove(expressionList);\n\t\t\t\tdefault -> throw new IllegalArgumentException(\"Unsupported update type \" + updateType);\n\t\t\t};\n\t\t}\n\t}\n\n\t/**\n\t * Utility method to prepare a list of expression to work with the set clause.\n\t * @param updateType which kind of update is used while creating the {@literal SET}\n\t * operation\n\t * @param possibleSetOperations a mixed list of expressions (property and list\n\t * operations)\n\t * @return a reified list of expressions that all target properties\n\t */\n\tprivate static List<Expression> prepareSetExpressions(UpdateType updateType,\n\t\t\tList<Expression> possibleSetOperations) {\n\n\t\tList<Expression> propertyOperations = new ArrayList<>();\n\t\tList<Expression> listOfExpressions = new ArrayList<>();\n\n\t\tfor (Expression possibleSetOperation : possibleSetOperations) {\n\t\t\tif (possibleSetOperation instanceof Operation) {\n\t\t\t\tpropertyOperations.add(possibleSetOperation);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlistOfExpressions.add(possibleSetOperation);\n\t\t\t}\n\t\t}\n\n\t\tif (listOfExpressions.size() % 2 != 0) {\n\t\t\tthrow new IllegalArgumentException(\"The list of expression to set must be even.\");\n\t\t}\n\n\t\tif (updateType == UpdateType.SET) {\n\n\t\t\tfor (int i = 0; i < listOfExpressions.size(); i += 2) {\n\t\t\t\tpropertyOperations.add(Operations.set(listOfExpressions.get(i), listOfExpressions.get(i + 1)));\n\t\t\t}\n\t\t}\n\t\telse if (updateType == UpdateType.MUTATE) {\n\n\t\t\tif (!(listOfExpressions.isEmpty() || propertyOperations.isEmpty())) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"A mutating SET must be build through a single operation or through a pair of expression, not both.\");\n\t\t\t}\n\n\t\t\tif (listOfExpressions.isEmpty()) {\n\t\t\t\tfor (Expression operation : propertyOperations) {\n\t\t\t\t\tif (((Operation) operation).getOperator() != Operator.MUTATE) {\n\t\t\t\t\t\tthrow new IllegalArgumentException(\"Only property operations based on the \" + Operator.MUTATE\n\t\t\t\t\t\t\t\t+ \" are supported inside a mutating SET.\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfor (int i = 0; i < listOfExpressions.size(); i += 2) {\n\t\t\t\t\tExpression rhs = listOfExpressions.get(i + 1);\n\t\t\t\t\tif (rhs instanceof Parameter) {\n\t\t\t\t\t\tpropertyOperations.add(Operations.mutate(listOfExpressions.get(i), rhs));\n\t\t\t\t\t}\n\t\t\t\t\telse if (rhs instanceof MapExpression mapExpression) {\n\t\t\t\t\t\tpropertyOperations.add(Operations.mutate(listOfExpressions.get(i), mapExpression));\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\t\t\"A mutating SET operation can only be used with a named parameter or a map expression.\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (updateType != UpdateType.REMOVE && propertyOperations.stream()\n\t\t\t.anyMatch(e -> e instanceof Operation op && op.getOperator() == Operator.REMOVE_LABEL)) {\n\t\t\tthrow new IllegalArgumentException(\"REMOVE operations are not supported in a SET clause\");\n\t\t}\n\t\treturn propertyOperations;\n\t}\n\n\tprivate static Collection<Expression> extractIdentifiablesFromReturnList(List<Expression> returnList) {\n\t\treturn returnList.stream()\n\t\t\t.filter(IdentifiableElement.class::isInstance)\n\t\t\t.map(IdentifiableElement.class::cast)\n\t\t\t.map(IdentifiableElement::asExpression)\n\t\t\t.collect(Collectors.toSet());\n\t}\n\n\tprivate void addVisitables(Visitable[] visitables) {\n\t\tfor (Visitable visitable : visitables) {\n\t\t\tif (visitable != null) {\n\t\t\t\tthis.currentSinglePartElements.add(visitable);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic final OngoingReadingWithoutWhere match(boolean optional, PatternElement... pattern) {\n\n\t\tAssertions.notNull(pattern, \"Patterns to match are required.\");\n\t\tAssertions.notEmpty(pattern, \"At least one pattern to match is required.\");\n\n\t\tthis.closeCurrentOngoingMatch();\n\n\t\tthis.currentOngoingMatch = new MatchBuilder(optional);\n\t\tthis.currentOngoingMatch.patternList.addAll(Arrays.asList(pattern));\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic final OngoingUpdate create(PatternElement... pattern) {\n\n\t\treturn update(UpdateType.CREATE, pattern);\n\t}\n\n\t@Override\n\tpublic final OngoingUpdate create(Collection<? extends PatternElement> pattern) {\n\n\t\treturn create(pattern.toArray(new PatternElement[] {}));\n\t}\n\n\t@Override\n\tpublic final OngoingMerge merge(PatternElement... pattern) {\n\n\t\treturn update(UpdateType.MERGE, pattern);\n\t}\n\n\t@Override\n\tpublic final OngoingMergeAction onCreate() {\n\t\treturn ongoingOnAfterMerge(MergeAction.Type.ON_CREATE);\n\t}\n\n\t@Override\n\tpublic final OngoingMergeAction onMatch() {\n\t\treturn ongoingOnAfterMerge(MergeAction.Type.ON_MATCH);\n\t}\n\n\tprivate OngoingMergeAction ongoingOnAfterMerge(MergeAction.Type type) {\n\n\t\tAssertions.notNull(this.currentOngoingUpdate, \"MERGE must have been invoked before defining an event.\");\n\t\tAssertions.isTrue(this.currentOngoingUpdate.builder instanceof SupportsActionsOnTheUpdatingClause,\n\t\t\t\t\"MERGE must have been invoked before defining an event.\");\n\t\treturn new OngoingMergeAction() {\n\n\t\t\t@Override\n\t\t\tpublic BuildableOngoingMergeAction set(Node node, String... labels) {\n\n\t\t\t\treturn this.set(Operations.set(node, labels));\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic BuildableOngoingMergeAction set(Node node, Collection<String> labels) {\n\n\t\t\t\treturn this.set(Operations.set(node, labels.toArray(new String[0])));\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic BuildableOngoingMergeAction set(Node node, Labels labels) {\n\n\t\t\t\treturn this.set(Operations.set(node, labels));\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic BuildableOngoingMergeAction mutate(Expression target, Expression properties) {\n\t\t\t\t((SupportsActionsOnTheUpdatingClause) DefaultStatementBuilder.this.currentOngoingUpdate.builder)\n\t\t\t\t\t.on(type, UpdateType.MUTATE, target, properties);\n\t\t\t\treturn DefaultStatementBuilder.this;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic BuildableOngoingMergeAction set(Expression... expressions) {\n\n\t\t\t\t((SupportsActionsOnTheUpdatingClause) DefaultStatementBuilder.this.currentOngoingUpdate.builder)\n\t\t\t\t\t.on(type, UpdateType.SET, expressions);\n\t\t\t\treturn DefaultStatementBuilder.this;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic BuildableOngoingMergeAction set(Collection<? extends Expression> expressions) {\n\t\t\t\treturn set(expressions.toArray(new Expression[] {}));\n\t\t\t}\n\t\t};\n\t}\n\n\t@Override\n\tpublic final OngoingUnwind unwind(Expression expression) {\n\n\t\tcloseCurrentOngoingMatch();\n\n\t\treturn new DefaultOngoingUnwind(expression);\n\t}\n\n\tprivate DefaultStatementBuilder update(UpdateType updateType, Object[] pattern) {\n\n\t\tAssertions.notNull(pattern, \"Patterns to create are required.\");\n\t\tAssertions.notEmpty(pattern, \"At least one pattern to create is required.\");\n\n\t\tthis.closeCurrentOngoingMatch();\n\t\tthis.closeCurrentOngoingUpdate();\n\n\t\tif (pattern.getClass().getComponentType() == PatternElement.class) {\n\t\t\tthis.currentOngoingUpdate = new DefaultStatementWithUpdateBuilder(updateType, (PatternElement[]) pattern);\n\t\t}\n\t\telse if (Expression.class.isAssignableFrom(pattern.getClass().getComponentType())) {\n\t\t\tthis.currentOngoingUpdate = new DefaultStatementWithUpdateBuilder(updateType, (Expression[]) pattern);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic final OngoingReadingAndReturn returning(Collection<? extends Expression> elements) {\n\n\t\treturn returning(false, false, elements);\n\t}\n\n\t@Override\n\tpublic final OngoingReadingAndReturn returningDistinct(Collection<? extends Expression> elements) {\n\n\t\treturn returning(false, true, elements);\n\t}\n\n\t@Override\n\tpublic StatementBuilder.OngoingReadingAndReturn returningRaw(Expression rawExpression) {\n\n\t\treturn new DefaultStatementWithReturnBuilder(rawExpression);\n\t}\n\n\tprivate OngoingReadingAndReturn returning(boolean raw, boolean distinct,\n\t\t\tCollection<? extends Expression> elements) {\n\n\t\tDefaultStatementWithReturnBuilder ongoingMatchAndReturn = new DefaultStatementWithReturnBuilder(raw, distinct);\n\t\tongoingMatchAndReturn.addExpressions(elements);\n\t\treturn ongoingMatchAndReturn;\n\t}\n\n\t@Override\n\tpublic final OrderableOngoingReadingAndWithWithoutWhere with(Collection<IdentifiableElement> elements) {\n\t\treturn with(false, elements);\n\t}\n\n\t@Override\n\tpublic OrderableOngoingReadingAndWithWithoutWhere withDistinct(Collection<IdentifiableElement> elements) {\n\t\treturn with(true, elements);\n\t}\n\n\tprivate OrderableOngoingReadingAndWithWithoutWhere with(boolean distinct,\n\t\t\tCollection<IdentifiableElement> elements) {\n\n\t\tDefaultStatementWithWithBuilder ongoingMatchAndWith = new DefaultStatementWithWithBuilder(distinct);\n\t\tongoingMatchAndWith.addElements(elements);\n\t\treturn ongoingMatchAndWith;\n\t}\n\n\t@Override\n\tpublic final OngoingUpdate delete(Expression... expressions) {\n\n\t\treturn update(UpdateType.DELETE, expressions);\n\t}\n\n\t@Override\n\tpublic final OngoingUpdate delete(Collection<? extends Expression> expressions) {\n\n\t\treturn delete(expressions.toArray(new Expression[] {}));\n\t}\n\n\t@Override\n\tpublic final OngoingUpdate detachDelete(Expression... expressions) {\n\n\t\treturn update(UpdateType.DETACH_DELETE, expressions);\n\t}\n\n\t@Override\n\tpublic final OngoingUpdate detachDelete(Collection<? extends Expression> expressions) {\n\n\t\treturn detachDelete(expressions.toArray(new Expression[] {}));\n\t}\n\n\t@Override\n\tpublic final BuildableMatchAndUpdate set(Expression... expressions) {\n\n\t\tDefaultStatementWithUpdateBuilder result = new DefaultStatementWithUpdateBuilder(UpdateType.SET, expressions);\n\t\tthis.closeCurrentOngoingUpdate();\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic final BuildableMatchAndUpdate set(Collection<? extends Expression> expressions) {\n\n\t\treturn set(expressions.toArray(new Expression[] {}));\n\t}\n\n\t@Override\n\tpublic final BuildableMatchAndUpdate set(Node named, String... labels) {\n\n\t\tthis.closeCurrentOngoingUpdate();\n\t\treturn new DefaultStatementWithUpdateBuilder(UpdateType.SET, Operations.set(named, labels));\n\t}\n\n\t@Override\n\tpublic final BuildableMatchAndUpdate set(Node named, Collection<String> labels) {\n\n\t\treturn set(named, labels.toArray(new String[] {}));\n\t}\n\n\t@Override\n\tpublic BuildableMatchAndUpdate set(Node node, Labels labels) {\n\n\t\tthis.closeCurrentOngoingUpdate();\n\t\treturn new DefaultStatementWithUpdateBuilder(UpdateType.SET, Operations.set(node, labels));\n\t}\n\n\t@Override\n\tpublic final BuildableMatchAndUpdate mutate(Expression target, Expression properties) {\n\n\t\tDefaultStatementWithUpdateBuilder result = new DefaultStatementWithUpdateBuilder(UpdateType.MUTATE,\n\t\t\t\tOperations.mutate(target, properties));\n\t\tthis.closeCurrentOngoingUpdate();\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic final BuildableMatchAndUpdate remove(Property... properties) {\n\n\t\tthis.closeCurrentOngoingUpdate();\n\t\treturn new DefaultStatementWithUpdateBuilder(UpdateType.REMOVE, properties);\n\t}\n\n\t@Override\n\tpublic final BuildableMatchAndUpdate remove(Collection<Property> properties) {\n\n\t\treturn remove(properties.toArray(new Property[] {}));\n\t}\n\n\t@Override\n\tpublic final BuildableMatchAndUpdate remove(Node named, String... labels) {\n\n\t\tthis.closeCurrentOngoingUpdate();\n\t\treturn new DefaultStatementWithUpdateBuilder(UpdateType.REMOVE, Operations.remove(named, labels));\n\t}\n\n\t@Override\n\tpublic final BuildableMatchAndUpdate remove(Node named, Collection<String> labels) {\n\n\t\treturn remove(named, labels.toArray(new String[] {}));\n\t}\n\n\t@Override\n\tpublic BuildableMatchAndUpdate remove(Node node, Labels labels) {\n\n\t\tthis.closeCurrentOngoingUpdate();\n\t\treturn new DefaultStatementWithUpdateBuilder(UpdateType.REMOVE, Operations.remove(node, labels));\n\t}\n\n\t@Override\n\tpublic final OngoingReadingWithWhere where(Condition newCondition) {\n\n\t\tif (this.currentOngoingMatch == null) {\n\t\t\tif (!this.currentSinglePartElements.isEmpty() && this.currentSinglePartElements\n\t\t\t\t.get(this.currentSinglePartElements.size() - 1) instanceof Subquery) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"A CALL{} clause requires to WITH before you can add further conditions\");\n\t\t\t}\n\t\t\tthrow new IllegalArgumentException(\"Cannot adda WHERE clause at this point\");\n\t\t}\n\t\tthis.currentOngoingMatch.conditionBuilder.where(newCondition);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic final OngoingReadingWithWhere and(Condition additionalCondition) {\n\n\t\tthis.currentOngoingMatch.conditionBuilder.and(additionalCondition);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic final OngoingReadingWithWhere or(Condition additionalCondition) {\n\n\t\tthis.currentOngoingMatch.conditionBuilder.or(additionalCondition);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic Statement build() {\n\n\t\treturn buildImpl(null);\n\t}\n\n\tprotected final Statement buildImpl(Clause returnOrFinish) {\n\n\t\tSinglePartQuery singlePartQuery = SinglePartQuery.create(buildListOfVisitables(false), returnOrFinish);\n\n\t\tif (this.multiPartElements.isEmpty()) {\n\t\t\treturn singlePartQuery;\n\t\t}\n\t\telse {\n\t\t\treturn MultiPartQuery.create(this.multiPartElements, singlePartQuery);\n\t\t}\n\t}\n\n\tprotected final List<Visitable> buildListOfVisitables(boolean clearAfter) {\n\n\t\tList<Visitable> visitables = new ArrayList<>(this.currentSinglePartElements);\n\n\t\tif (this.currentOngoingMatch != null) {\n\t\t\tvisitables.add(this.currentOngoingMatch.buildMatch());\n\t\t}\n\n\t\tif (this.currentOngoingUpdate != null) {\n\t\t\tvisitables.add(this.currentOngoingUpdate.builder.build());\n\t\t}\n\n\t\tif (clearAfter) {\n\t\t\tthis.currentOngoingMatch = null;\n\t\t\tthis.currentOngoingUpdate = null;\n\t\t\tthis.currentSinglePartElements.clear();\n\t\t}\n\t\treturn visitables;\n\t}\n\n\t@SuppressWarnings(\"OptionalUsedAsFieldOrParameterType\")\n\tprotected final DefaultStatementBuilder addWith(Optional<With> optionalWith) {\n\n\t\toptionalWith\n\t\t\t.ifPresent(with -> this.multiPartElements.add(new MultiPartElement(buildListOfVisitables(true), with)));\n\t\treturn this;\n\t}\n\n\tprotected final void addUpdatingClause(UpdatingClause updatingClause) {\n\n\t\t// Close current match\n\t\tcloseCurrentOngoingMatch();\n\n\t\tthis.currentSinglePartElements.add(updatingClause);\n\t}\n\n\t@Override\n\tpublic BuildableSubquery call(Statement statement, IdentifiableElement... imports) {\n\n\t\tthis.closeCurrentOngoingMatch();\n\t\tthis.closeCurrentOngoingUpdate();\n\n\t\tthis.currentSinglePartElements.add(Subquery.call(statement, imports));\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic BuildableSubquery callRawCypher(String rawCypher, Object... args) {\n\n\t\tthis.closeCurrentOngoingMatch();\n\t\tthis.closeCurrentOngoingUpdate();\n\n\t\tthis.currentSinglePartElements.add(Subquery.raw(rawCypher, args));\n\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic BuildableSubquery callInTransactions(Statement statement, Integer rows, IdentifiableElement... imports) {\n\n\t\tthis.closeCurrentOngoingMatch();\n\t\tthis.closeCurrentOngoingUpdate();\n\n\t\tthis.currentSinglePartElements.add(Subquery.call(statement, imports).inTransactionsOf(rows));\n\n\t\treturn this;\n\t}\n\n\tprivate void closeCurrentOngoingMatch() {\n\t\tif (this.currentOngoingMatch == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.currentSinglePartElements.add(this.currentOngoingMatch.buildMatch());\n\t\tthis.currentOngoingMatch = null;\n\t}\n\n\tprivate void closeCurrentOngoingUpdate() {\n\t\tif (this.currentOngoingUpdate == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.currentSinglePartElements.add(this.currentOngoingUpdate.builder.build());\n\t\tthis.currentOngoingUpdate = null;\n\t}\n\n\t@Override\n\tpublic final Condition asCondition() {\n\n\t\tvar matches = new ArrayList<Match>();\n\t\tif (!this.currentSinglePartElements.isEmpty()) {\n\t\t\tfor (var visitable : this.currentSinglePartElements) {\n\t\t\t\tif (visitable instanceof Match match) {\n\t\t\t\t\tmatches.add(match);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.currentOngoingMatch != null) {\n\t\t\tmatches.add(this.currentOngoingMatch.buildMatch());\n\t\t}\n\n\t\tif (matches.isEmpty()) {\n\t\t\tthrow new IllegalArgumentException(\"Only MATCH statements can be used as existential subqueries.\");\n\t\t}\n\n\t\treturn ExistentialSubquery.exists(matches);\n\t}\n\n\t@Override\n\tpublic final OngoingReadingWithoutWhere usingIndex(Property... properties) {\n\n\t\tthis.currentOngoingMatch.hints.add(Hint.useIndexFor(false, properties));\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic final OngoingReadingWithoutWhere usingIndexSeek(Property... properties) {\n\n\t\tthis.currentOngoingMatch.hints.add(Hint.useIndexFor(true, properties));\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic final OngoingReadingWithoutWhere usingScan(Node node) {\n\n\t\tthis.currentOngoingMatch.hints.add(Hint.useScanFor(node));\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic final OngoingReadingWithoutWhere usingJoinOn(SymbolicName... names) {\n\n\t\tthis.currentOngoingMatch.hints.add(Hint.useJoinOn(names));\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic ForeachSourceStep foreach(SymbolicName variable) {\n\n\t\tthis.closeCurrentOngoingMatch();\n\t\tthis.closeCurrentOngoingUpdate();\n\n\t\treturn new ForeachBuilder(variable);\n\t}\n\n\t@Override\n\tpublic Terminal finish() {\n\t\treturn new DefaultStatementWithFinishBuilder();\n\t}\n\n\t@Override\n\tpublic InQueryCallBuilder call(String... namespaceAndProcedure) {\n\n\t\tAssertions.notEmpty(namespaceAndProcedure, \"The procedure namespace and name must not be null or empty.\");\n\n\t\tcloseCurrentOngoingMatch();\n\n\t\treturn new InQueryCallBuilder(ProcedureName.from(namespaceAndProcedure));\n\t}\n\n\t/**\n\t * A private enum for distinguishing updating clauses.\n\t */\n\tenum UpdateType {\n\n\t\tDELETE, DETACH_DELETE, SET, MUTATE, REMOVE, CREATE, MERGE\n\n\t}\n\n\tprivate interface UpdatingClauseBuilder {\n\n\t\tUpdatingClause build();\n\n\t}\n\n\tinterface SupportsActionsOnTheUpdatingClause {\n\n\t\tSupportsActionsOnTheUpdatingClause on(MergeAction.Type type, UpdateType updateType, Expression... expressions);\n\n\t}\n\n\tabstract static class ReturnListWrapper {\n\n\t\tprotected final List<Expression> returnList = new ArrayList<>();\n\n\t\tprotected final void addElements(Collection<IdentifiableElement> elements) {\n\n\t\t\tAssertions.notNull(elements, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSIONS_REQUIRED));\n\t\t\tvar filteredElements = elements.stream()\n\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t.map(IdentifiableElement::asExpression)\n\t\t\t\t.toList();\n\t\t\tAssertions.isTrue(!filteredElements.isEmpty(),\n\t\t\t\t\tCypher.MESSAGES.getString(MessageKeys.ASSERTIONS_AT_LEAST_ONE_EXPRESSION_REQUIRED));\n\n\t\t\tthis.returnList.addAll(filteredElements);\n\t\t}\n\n\t\tprotected final void addExpressions(Collection<? extends Expression> expressions) {\n\n\t\t\tAssertions.notNull(expressions, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSIONS_REQUIRED));\n\t\t\tAssertions.isTrue(!expressions.isEmpty() && expressions.stream().noneMatch(Objects::isNull),\n\t\t\t\t\tCypher.MESSAGES.getString(MessageKeys.ASSERTIONS_AT_LEAST_ONE_EXPRESSION_REQUIRED));\n\n\t\t\tthis.returnList.addAll(expressions);\n\t\t}\n\n\t}\n\n\t/**\n\t * Infrastructure for building {@link UpdatingClause updating clauses}.\n\t *\n\t * @param <T> the type of the updating clause\n\t */\n\tprivate abstract static class AbstractUpdatingClauseBuilder<T extends UpdatingClause>\n\t\t\timplements UpdatingClauseBuilder {\n\n\t\tprotected final List<PatternElement> patternElements;\n\n\t\tAbstractUpdatingClauseBuilder(List<PatternElement> patternElements) {\n\t\t\tthis.patternElements = patternElements;\n\t\t}\n\n\t\tabstract Function<Pattern, T> getUpdatingClauseProvider();\n\n\t\t@Override\n\t\tpublic T build() {\n\t\t\treturn getUpdatingClauseProvider().apply(Pattern.of(this.patternElements));\n\t\t}\n\n\t\tstatic class CreateBuilder extends AbstractUpdatingClauseBuilder<Create> {\n\n\t\t\tCreateBuilder(List<PatternElement> patternElements) {\n\t\t\t\tsuper(patternElements);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tFunction<Pattern, Create> getUpdatingClauseProvider() {\n\t\t\t\treturn Create::new;\n\t\t\t}\n\n\t\t}\n\n\t\tstatic class MergeBuilder extends AbstractUpdatingClauseBuilder<Merge>\n\t\t\t\timplements SupportsActionsOnTheUpdatingClause {\n\n\t\t\tprivate final List<MergeAction> mergeActions = new ArrayList<>();\n\n\t\t\tMergeBuilder(List<PatternElement> patternElements) {\n\t\t\t\tsuper(patternElements);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tFunction<Pattern, Merge> getUpdatingClauseProvider() {\n\t\t\t\treturn pattern -> new Merge(pattern, this.mergeActions);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic SupportsActionsOnTheUpdatingClause on(MergeAction.Type type, UpdateType updateType,\n\t\t\t\t\tExpression... expressions) {\n\n\t\t\t\tExpressionList expressionList = new ExpressionList(\n\t\t\t\t\t\tprepareSetExpressions(updateType, Arrays.asList(expressions)));\n\t\t\t\tthis.mergeActions.add(MergeAction.of(type, new Set(expressionList)));\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tstatic final class MatchBuilder {\n\n\t\tprivate final List<PatternElement> patternList = new ArrayList<>();\n\n\t\tprivate final List<Hint> hints = new ArrayList<>();\n\n\t\tprivate final ConditionBuilder conditionBuilder = new ConditionBuilder();\n\n\t\tprivate final boolean optional;\n\n\t\tMatchBuilder(boolean optional) {\n\t\t\tthis.optional = optional;\n\t\t}\n\n\t\tMatch buildMatch() {\n\t\t\treturn (Match) Clauses.match(this.optional, this.patternList,\n\t\t\t\t\tWhere.from(this.conditionBuilder.buildCondition().orElse(null)), this.hints);\n\t\t}\n\n\t}\n\n\tabstract static class AbstractCallBuilder {\n\n\t\tprotected final ProcedureName procedureName;\n\n\t\tprotected final DefaultStatementBuilder.ConditionBuilder conditionBuilder = new DefaultStatementBuilder.ConditionBuilder();\n\n\t\tprotected Expression[] arguments;\n\n\t\tAbstractCallBuilder(ProcedureName procedureName) {\n\t\t\tthis(procedureName, null);\n\t\t}\n\n\t\tAbstractCallBuilder(ProcedureName procedureName, Expression[] arguments) {\n\t\t\tthis.procedureName = procedureName;\n\t\t\tthis.arguments = arguments;\n\t\t}\n\n\t\tArguments createArgumentList() {\n\t\t\tArguments argumentsList = null;\n\t\t\tif (this.arguments != null && this.arguments.length > 0) {\n\t\t\t\targumentsList = new Arguments(this.arguments);\n\t\t\t}\n\t\t\treturn argumentsList;\n\t\t}\n\n\t}\n\n\tstatic final class StandaloneCallBuilder extends AbstractCallBuilder implements\n\n\t\t\tOngoingStandaloneCallWithoutArguments, OngoingStandaloneCallWithArguments {\n\n\t\tStandaloneCallBuilder(ProcedureName procedureName) {\n\t\t\tsuper(procedureName);\n\t\t}\n\n\t\t@Override\n\t\tpublic StandaloneCallBuilder withArgs(Expression... arguments) {\n\n\t\t\tsuper.arguments = arguments;\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingStandaloneCallWithReturnFields yield(Asterisk asterisk) {\n\n\t\t\treturn new YieldingStandaloneCallBuilder(this.procedureName, this.arguments, asterisk);\n\t\t}\n\n\t\t@Override\n\t\tpublic DefaultStatementBuilder.YieldingStandaloneCallBuilder yield(SymbolicName... resultFields) {\n\n\t\t\treturn new YieldingStandaloneCallBuilder(this.procedureName, this.arguments, resultFields);\n\t\t}\n\n\t\t@Override\n\t\tpublic DefaultStatementBuilder.YieldingStandaloneCallBuilder yield(AliasedExpression... aliasedResultFields) {\n\n\t\t\treturn new YieldingStandaloneCallBuilder(this.procedureName, this.arguments, aliasedResultFields);\n\t\t}\n\n\t\t@Override\n\t\tpublic Expression asFunction(boolean distinct) {\n\n\t\t\tif (super.arguments == null || super.arguments.length == 0) {\n\t\t\t\treturn FunctionInvocation.create(this.procedureName::getQualifiedName);\n\t\t\t}\n\t\t\tif (distinct) {\n\t\t\t\treturn FunctionInvocation.createDistinct(this.procedureName::getQualifiedName, super.arguments);\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn FunctionInvocation.create(this.procedureName::getQualifiedName, super.arguments);\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic VoidCall withoutResults() {\n\t\t\treturn new DefaultStatementBuilder(this.build());\n\t\t}\n\n\t\t@Override\n\t\tpublic ProcedureCall build() {\n\n\t\t\treturn ProcedureCallImpl.create(this.procedureName, createArgumentList(), null,\n\t\t\t\t\tthis.conditionBuilder.buildCondition().map(Where::new).orElse(null));\n\t\t}\n\n\t}\n\n\tstatic final class YieldingStandaloneCallBuilder extends AbstractCallBuilder\n\t\t\timplements ExposesWhere<StatementBuilder.OngoingReadingWithWhere>, ExposesReturning, ExposesFinish,\n\t\t\tOngoingStandaloneCallWithReturnFields {\n\n\t\tprivate final YieldItems yieldItems;\n\n\t\tprivate DefaultStatementBuilder delegate;\n\n\t\tYieldingStandaloneCallBuilder(ProcedureName procedureName, Expression[] arguments,\n\t\t\t\tSymbolicName... resultFields) {\n\t\t\tsuper(procedureName, arguments);\n\t\t\tthis.yieldItems = YieldItems.yieldAllOf(resultFields);\n\t\t}\n\n\t\tYieldingStandaloneCallBuilder(ProcedureName procedureName, Expression[] arguments, Asterisk asterisk) {\n\t\t\tsuper(procedureName, arguments);\n\t\t\tthis.yieldItems = YieldItems.yieldAllOf(asterisk);\n\t\t}\n\n\t\tYieldingStandaloneCallBuilder(ProcedureName procedureName, Expression[] arguments,\n\t\t\t\tAliasedExpression... aliasedResultFields) {\n\t\t\tsuper(procedureName, arguments);\n\t\t\tthis.yieldItems = YieldItems.yieldAllOf(aliasedResultFields);\n\t\t}\n\n\t\t@Override\n\t\tpublic StatementBuilder.OngoingReadingAndReturn returning(Collection<? extends Expression> expressions) {\n\n\t\t\treturn new DefaultStatementBuilder(this.buildCall()).returning(expressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic StatementBuilder.OngoingReadingAndReturn returningDistinct(\n\t\t\t\tCollection<? extends Expression> expressions) {\n\n\t\t\treturn new DefaultStatementBuilder(this.buildCall()).returningDistinct(expressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic StatementBuilder.OngoingReadingAndReturn returningRaw(Expression rawExpression) {\n\t\t\treturn new DefaultStatementBuilder(this.buildCall()).returningRaw(rawExpression);\n\t\t}\n\n\t\t@Override\n\t\tpublic StatementBuilder.OngoingReadingWithWhere where(Condition newCondition) {\n\n\t\t\tthis.conditionBuilder.where(newCondition);\n\t\t\treturn new DefaultStatementBuilder(this.buildCall());\n\t\t}\n\n\t\t@Override\n\t\tpublic StatementBuilder.OrderableOngoingReadingAndWithWithoutWhere with(\n\t\t\t\tCollection<IdentifiableElement> elements) {\n\t\t\treturn new DefaultStatementBuilder(this.buildCall()).with(elements);\n\t\t}\n\n\t\t@Override\n\t\tpublic StatementBuilder.OrderableOngoingReadingAndWithWithoutWhere withDistinct(\n\t\t\t\tCollection<IdentifiableElement> elements) {\n\t\t\treturn new DefaultStatementBuilder(this.buildCall()).withDistinct(elements);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableSubquery call(Statement statement, IdentifiableElement... imports) {\n\t\t\treturn new DefaultStatementBuilder(this.buildCall()).call(statement, imports);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableSubquery callRawCypher(String rawCypher, Object... args) {\n\t\t\treturn new DefaultStatementBuilder(this.buildCall()).callRawCypher(rawCypher, args);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableSubquery callInTransactions(Statement statement, Integer rows, IdentifiableElement... imports) {\n\t\t\treturn new DefaultStatementBuilder(this.buildCall()).callInTransactions(statement, rows, imports);\n\t\t}\n\n\t\t@Override\n\t\tpublic Statement build() {\n\n\t\t\tif (this.delegate != null) {\n\t\t\t\treturn this.delegate.build();\n\t\t\t}\n\n\t\t\treturn ProcedureCallImpl.create(this.procedureName, createArgumentList(), this.yieldItems,\n\t\t\t\t\tthis.conditionBuilder.buildCondition().map(Where::new).orElse(null));\n\t\t}\n\n\t\tStatement buildCall() {\n\t\t\treturn build();\n\t\t}\n\n\t\t@Override\n\t\tpublic StatementBuilder.OngoingReadingWithoutWhere match(boolean optional, PatternElement... pattern) {\n\t\t\treturn new DefaultStatementBuilder(this.buildCall()).match(optional, pattern);\n\t\t}\n\n\t\t@Override\n\t\tpublic ExposesAndThen<OngoingStandaloneCallWithReturnFields, Statement> andThen(Statement statement) {\n\t\t\tif (this.delegate == null) {\n\t\t\t\tthis.delegate = new DefaultStatementBuilder(this.buildCall());\n\t\t\t}\n\t\t\tthis.delegate.currentSinglePartElements.add(statement);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic StatementBuilder.Terminal finish() {\n\t\t\treturn new DefaultStatementBuilder(this.buildCall());\n\t\t}\n\n\t}\n\n\t// Static builder and support classes\n\n\tstatic final class ConditionBuilder {\n\n\t\tprivate Condition condition;\n\n\t\tvoid where(Condition newCondition) {\n\n\t\t\tAssertions.notNull(newCondition, \"The new condition must not be null.\");\n\t\t\tthis.condition = newCondition;\n\t\t}\n\n\t\tvoid and(Condition additionalCondition) {\n\n\t\t\tthis.condition = this.condition.and(additionalCondition);\n\t\t}\n\n\t\tvoid or(Condition additionalCondition) {\n\n\t\t\tthis.condition = this.condition.or(additionalCondition);\n\t\t}\n\n\t\tprivate boolean hasCondition() {\n\t\t\treturn this.condition != null && (!(this.condition instanceof CompoundCondition compoundCondition)\n\t\t\t\t\t|| compoundCondition.hasConditions());\n\t\t}\n\n\t\tOptional<Condition> buildCondition() {\n\t\t\treturn hasCondition() ? Optional.of(this.condition) : Optional.empty();\n\t\t}\n\n\t}\n\n\tstatic final class OrderBuilder {\n\n\t\tfinal List<SortItem> sortItemList = new ArrayList<>();\n\n\t\tSortItem lastSortItem;\n\n\t\tSkip skip;\n\n\t\tLimit limit;\n\n\t\tvoid reset() {\n\t\t\tthis.sortItemList.clear();\n\t\t\tthis.lastSortItem = null;\n\t\t\tthis.skip = null;\n\t\t\tthis.limit = null;\n\t\t}\n\n\t\tvoid orderBy(SortItem... sortItem) {\n\t\t\tthis.sortItemList.addAll(Arrays.asList(sortItem));\n\t\t}\n\n\t\tvoid orderBy(Collection<SortItem> sortItems) {\n\t\t\tif (sortItems != null) {\n\t\t\t\tthis.sortItemList.addAll(sortItems);\n\t\t\t}\n\t\t}\n\n\t\tvoid orderBy(Expression expression) {\n\t\t\tthis.lastSortItem = Cypher.sort(expression);\n\t\t}\n\n\t\tvoid and(Expression expression) {\n\t\t\torderBy(expression);\n\t\t}\n\n\t\tvoid descending() {\n\t\t\tthis.sortItemList.add(this.lastSortItem.descending());\n\t\t\tthis.lastSortItem = null;\n\t\t}\n\n\t\tvoid ascending() {\n\t\t\tthis.sortItemList.add(this.lastSortItem.ascending());\n\t\t\tthis.lastSortItem = null;\n\t\t}\n\n\t\tvoid skip(Expression expression) {\n\t\t\tif (expression != null) {\n\t\t\t\tthis.skip = Skip.create(expression);\n\t\t\t}\n\t\t}\n\n\t\tvoid limit(Expression expression) {\n\t\t\tif (expression != null) {\n\t\t\t\tthis.limit = Limit.create(expression);\n\t\t\t}\n\t\t}\n\n\t\tOptional<Order> buildOrder() {\n\t\t\tif (this.lastSortItem != null) {\n\t\t\t\tthis.sortItemList.add(this.lastSortItem);\n\t\t\t}\n\t\t\tOptional<Order> result = this.sortItemList.isEmpty() ? Optional.empty()\n\t\t\t\t\t: Optional.of(new Order(this.sortItemList));\n\t\t\tthis.sortItemList.clear();\n\t\t\tthis.lastSortItem = null;\n\t\t\treturn result;\n\t\t}\n\n\t\tSkip getSkip() {\n\t\t\treturn this.skip;\n\t\t}\n\n\t\tLimit getLimit() {\n\t\t\treturn this.limit;\n\t\t}\n\n\t}\n\n\tfinal class ForeachBuilder implements ForeachSourceStep, ForeachUpdateStep {\n\n\t\tprivate final SymbolicName variable;\n\n\t\tprivate Expression list;\n\n\t\tForeachBuilder(SymbolicName variable) {\n\t\t\tthis.variable = variable;\n\t\t}\n\n\t\t@Override\n\t\tpublic ForeachUpdateStep in(Expression newVariableList) {\n\n\t\t\tthis.list = Objects.requireNonNull(newVariableList);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUpdate apply(UpdatingClause... updatingClauses) {\n\t\t\tif (Arrays.stream(updatingClauses).anyMatch(Foreach.class::isInstance)) {\n\t\t\t\tthrow new IllegalArgumentException(\"FOREACH clauses may not be nested\");\n\t\t\t}\n\n\t\t\tDefaultStatementBuilder.this\n\t\t\t\t.addUpdatingClause(new Foreach(this.variable, this.list, Arrays.asList(updatingClauses)));\n\t\t\treturn DefaultStatementBuilder.this;\n\t\t}\n\n\t}\n\n\tprotected class DefaultStatementWithReturnBuilder extends ReturnListWrapper\n\t\t\timplements OngoingReadingAndReturn, TerminalOngoingOrderDefinition, OngoingMatchAndReturnWithOrder {\n\n\t\tprivate final OrderBuilder orderBuilder = new OrderBuilder();\n\n\t\tprotected boolean rawReturn;\n\n\t\tprotected boolean distinct;\n\n\t\tprotected DefaultStatementWithReturnBuilder(Expression rawReturnExpression) {\n\t\t\tthis.distinct = false;\n\t\t\tthis.rawReturn = true;\n\t\t\tthis.returnList.add(rawReturnExpression);\n\t\t}\n\n\t\tprotected DefaultStatementWithReturnBuilder(boolean rawReturn, boolean distinct) {\n\t\t\tthis.distinct = distinct;\n\t\t\tthis.rawReturn = rawReturn;\n\t\t}\n\n\t\t@Override\n\t\tpublic Collection<Expression> getIdentifiableExpressions() {\n\t\t\treturn extractIdentifiablesFromReturnList(this.returnList);\n\t\t}\n\n\t\t@Override\n\t\tpublic final OngoingMatchAndReturnWithOrder orderBy(SortItem... sortItem) {\n\t\t\tthis.orderBuilder.orderBy(sortItem);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic final OngoingMatchAndReturnWithOrder orderBy(Collection<SortItem> sortItem) {\n\t\t\treturn orderBy(sortItem.toArray(new SortItem[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic final TerminalOngoingOrderDefinition orderBy(Expression expression) {\n\t\t\tthis.orderBuilder.orderBy(expression);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic final TerminalOngoingOrderDefinition and(Expression expression) {\n\t\t\tthis.orderBuilder.and(expression);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic final DefaultStatementWithReturnBuilder descending() {\n\t\t\tthis.orderBuilder.descending();\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic final DefaultStatementWithReturnBuilder ascending() {\n\t\t\tthis.orderBuilder.ascending();\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic final OngoingReadingAndReturn skip(Number number) {\n\t\t\treturn skip((number != null) ? new NumberLiteral(number) : null);\n\t\t}\n\n\t\t@Override\n\t\tpublic final OngoingReadingAndReturn skip(Expression expression) {\n\t\t\tthis.orderBuilder.skip(expression);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic final OngoingReadingAndReturn limit(Number number) {\n\t\t\treturn limit((number != null) ? new NumberLiteral(number) : null);\n\t\t}\n\n\t\t@Override\n\t\tpublic final OngoingReadingAndReturn limit(Expression expression) {\n\t\t\tthis.orderBuilder.limit(expression);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic ResultStatement build() {\n\n\t\t\tReturn returning = Return.create(this.rawReturn, this.distinct, this.returnList, this.orderBuilder);\n\t\t\treturn (ResultStatement) DefaultStatementBuilder.this.buildImpl(returning);\n\t\t}\n\n\t}\n\n\tprotected final class DefaultStatementWithFinishBuilder implements Terminal {\n\n\t\t@Override\n\t\tpublic Statement build() {\n\t\t\treturn DefaultStatementBuilder.this.buildImpl(Finish.create());\n\t\t}\n\n\t}\n\n\t/**\n\t * Helper class aggregating a couple of interface, collecting conditions and returned\n\t * objects.\n\t */\n\tprotected final class DefaultStatementWithWithBuilder extends ReturnListWrapper implements OngoingOrderDefinition,\n\t\t\tOrderableOngoingReadingAndWithWithoutWhere, OrderableOngoingReadingAndWithWithWhere,\n\t\t\tOngoingReadingAndWithWithWhereAndOrder, OngoingReadingAndWithWithSkip {\n\n\t\tprivate final ConditionBuilder conditionBuilder = new ConditionBuilder();\n\n\t\tprivate final OrderBuilder orderBuilder = new OrderBuilder();\n\n\t\tprivate final boolean distinct;\n\n\t\tprivate DefaultStatementWithWithBuilder(boolean distinct) {\n\t\t\tthis.distinct = distinct;\n\t\t}\n\n\t\tprivate Optional<With> buildWith() {\n\n\t\t\tif (this.returnList.isEmpty()) {\n\t\t\t\treturn Optional.empty();\n\t\t\t}\n\n\t\t\tExpressionList returnItems = new ExpressionList(this.returnList);\n\n\t\t\tWhere where = this.conditionBuilder.buildCondition().map(Where::new).orElse(null);\n\n\t\t\tOptional<With> returnedWith = Optional\n\t\t\t\t.of(new With(this.distinct, returnItems, this.orderBuilder.buildOrder().orElse(null),\n\t\t\t\t\t\tthis.orderBuilder.getSkip(), this.orderBuilder.getLimit(), where));\n\t\t\tthis.returnList.clear();\n\t\t\tthis.orderBuilder.reset();\n\t\t\treturn returnedWith;\n\t\t}\n\n\t\t@Override\n\t\tpublic Collection<Expression> getIdentifiableExpressions() {\n\t\t\treturn extractIdentifiablesFromReturnList(this.returnList);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndReturn returning(Collection<? extends Expression> expressions) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).returning(expressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndReturn returningDistinct(Collection<? extends Expression> expressions) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).returningDistinct(expressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndReturn returningRaw(Expression rawExpression) {\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).returningRaw(rawExpression);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUpdate delete(Expression... expressions) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).delete(expressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUpdate delete(Collection<? extends Expression> expressions) {\n\n\t\t\treturn delete(expressions.toArray(new Expression[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUpdate detachDelete(Expression... expressions) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).detachDelete(expressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUpdate detachDelete(Collection<? extends Expression> expressions) {\n\n\t\t\treturn detachDelete(expressions.toArray(new Expression[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate set(Expression... expressions) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).set(expressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate set(Collection<? extends Expression> expressions) {\n\n\t\t\treturn set(expressions.toArray(new Expression[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate set(Node node, String... labels) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).set(node, labels);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate set(Node node, Collection<String> labels) {\n\n\t\t\treturn set(node, labels.toArray(new String[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate set(Node node, Labels labels) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).set(node, labels);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate mutate(Expression target, Expression properties) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).mutate(target, properties);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate remove(Node node, String... labels) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).remove(node, labels);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate remove(Node node, Collection<String> labels) {\n\n\t\t\treturn remove(node, labels.toArray(new String[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate remove(Node node, Labels labels) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).remove(node, labels);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate remove(Property... properties) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).remove(properties);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate remove(Collection<Property> properties) {\n\n\t\t\treturn remove(properties.toArray(new Property[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic OrderableOngoingReadingAndWithWithoutWhere with(Collection<IdentifiableElement> elements) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).with(elements);\n\t\t}\n\n\t\t@Override\n\t\tpublic OrderableOngoingReadingAndWithWithoutWhere withDistinct(Collection<IdentifiableElement> elements) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).withDistinct(elements);\n\t\t}\n\n\t\t@Override\n\t\tpublic OrderableOngoingReadingAndWithWithWhere where(Condition newCondition) {\n\n\t\t\tthis.conditionBuilder.where(newCondition);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OrderableOngoingReadingAndWithWithWhere and(Condition additionalCondition) {\n\n\t\t\tthis.conditionBuilder.and(additionalCondition);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OrderableOngoingReadingAndWithWithWhere or(Condition additionalCondition) {\n\n\t\t\tthis.conditionBuilder.or(additionalCondition);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingWithoutWhere match(boolean optional, PatternElement... pattern) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).match(optional, pattern);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUpdate create(PatternElement... pattern) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).create(pattern);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUpdate create(Collection<? extends PatternElement> pattern) {\n\n\t\t\treturn create(pattern.toArray(new PatternElement[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingMerge merge(PatternElement... pattern) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).merge(pattern);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUnwind unwind(Expression expression) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).unwind(expression);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableSubquery call(Statement statement, IdentifiableElement... imports) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).call(statement, imports);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableSubquery callRawCypher(String rawCypher, Object... args) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).callRawCypher(rawCypher, args);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableSubquery callInTransactions(Statement statement, Integer rows, IdentifiableElement... imports) {\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).callInTransactions(statement, rows, imports);\n\t\t}\n\n\t\t@Override\n\t\tpublic InQueryCallBuilder call(String... namespaceAndProcedure) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).call(namespaceAndProcedure);\n\t\t}\n\n\t\t@Override\n\t\tpublic OrderableOngoingReadingAndWithWithWhere orderBy(SortItem... sortItem) {\n\t\t\tthis.orderBuilder.orderBy(sortItem);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OrderableOngoingReadingAndWithWithWhere orderBy(Collection<SortItem> sortItem) {\n\t\t\treturn orderBy(sortItem.toArray(new SortItem[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingOrderDefinition orderBy(Expression expression) {\n\t\t\tthis.orderBuilder.orderBy(expression);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingOrderDefinition and(Expression expression) {\n\t\t\tthis.orderBuilder.and(expression);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndWithWithWhereAndOrder descending() {\n\t\t\tthis.orderBuilder.descending();\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndWithWithWhereAndOrder ascending() {\n\t\t\tthis.orderBuilder.ascending();\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndWithWithSkip skip(Number number) {\n\t\t\treturn skip((number != null) ? new NumberLiteral(number) : null);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndWithWithSkip skip(Expression expression) {\n\t\t\tthis.orderBuilder.skip(expression);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndWith limit(Number number) {\n\t\t\treturn limit((number != null) ? new NumberLiteral(number) : null);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndWith limit(Expression expression) {\n\t\t\tthis.orderBuilder.limit(expression);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic LoadCSVStatementBuilder.OngoingLoadCSV loadCSV(URI from, boolean withHeaders) {\n\n\t\t\tDefaultStatementBuilder this0 = DefaultStatementBuilder.this.addWith(buildWith());\n\t\t\treturn new DefaultLoadCSVStatementBuilder.PrepareLoadCSVStatementImpl(from, withHeaders, this0);\n\t\t}\n\n\t\t@Override\n\t\tpublic ForeachSourceStep foreach(SymbolicName variable) {\n\n\t\t\treturn DefaultStatementBuilder.this.addWith(buildWith()).foreach(variable);\n\t\t}\n\n\t\t@Override\n\t\tpublic StatementBuilder.Terminal finish() {\n\t\t\treturn DefaultStatementBuilder.this;\n\t\t}\n\n\t}\n\n\tprotected final class DefaultStatementWithUpdateBuilder implements BuildableMatchAndUpdate {\n\n\t\tfinal UpdatingClauseBuilder builder;\n\n\t\tprivate DefaultStatementWithUpdateBuilder(UpdateType updateType, PatternElement... pattern) {\n\n\t\t\tthis.builder = getUpdatingClauseBuilder(updateType, pattern);\n\t\t}\n\n\t\tprivate DefaultStatementWithUpdateBuilder(UpdateType updateType, Expression... expressions) {\n\n\t\t\tthis.builder = getUpdatingClauseBuilder(updateType, expressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndReturn returning(Collection<? extends Expression> expressions) {\n\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\n\t\t\tDefaultStatementWithReturnBuilder delegate = new DefaultStatementWithReturnBuilder(false, false);\n\t\t\tdelegate.addExpressions(expressions);\n\t\t\treturn delegate;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndReturn returningDistinct(Collection<? extends Expression> elements) {\n\n\t\t\tDefaultStatementWithReturnBuilder delegate = (DefaultStatementWithReturnBuilder) returning(elements);\n\t\t\tdelegate.distinct = true;\n\t\t\treturn delegate;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndReturn returningRaw(Expression rawExpression) {\n\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn new DefaultStatementWithReturnBuilder(rawExpression);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUpdate delete(Expression... deletedExpressions) {\n\t\t\treturn delete(false, deletedExpressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUpdate delete(Collection<? extends Expression> deletedExpressions) {\n\t\t\treturn delete(deletedExpressions.toArray(new Expression[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUpdate detachDelete(Expression... deletedExpressions) {\n\t\t\treturn delete(true, deletedExpressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUpdate detachDelete(Collection<? extends Expression> deletedExpressions) {\n\t\t\treturn detachDelete(deletedExpressions.toArray(new Expression[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingMerge merge(PatternElement... pattern) {\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn DefaultStatementBuilder.this.merge(pattern);\n\t\t}\n\n\t\tprivate OngoingUpdate delete(boolean nextDetach, Expression... deletedExpressions) {\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn DefaultStatementBuilder.this.update(nextDetach ? UpdateType.DETACH_DELETE : UpdateType.DELETE,\n\t\t\t\t\tdeletedExpressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate set(Expression... keyValuePairs) {\n\n\t\t\tDefaultStatementWithUpdateBuilder result = DefaultStatementBuilder.this.new DefaultStatementWithUpdateBuilder(\n\t\t\t\t\tUpdateType.SET, keyValuePairs);\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn result;\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate set(Collection<? extends Expression> keyValuePairs) {\n\n\t\t\treturn set(keyValuePairs.toArray(new Expression[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate set(Node node, String... labels) {\n\n\t\t\tDefaultStatementWithUpdateBuilder result = DefaultStatementBuilder.this.new DefaultStatementWithUpdateBuilder(\n\t\t\t\t\tUpdateType.SET, Operations.set(node, labels));\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn result;\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate set(Node node, Collection<String> labels) {\n\n\t\t\treturn set(node, labels.toArray(new String[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate set(Node node, Labels labels) {\n\n\t\t\tDefaultStatementWithUpdateBuilder result = DefaultStatementBuilder.this.new DefaultStatementWithUpdateBuilder(\n\t\t\t\t\tUpdateType.SET, Operations.set(node, labels));\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn result;\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate mutate(Expression target, Expression properties) {\n\n\t\t\tDefaultStatementWithUpdateBuilder result = DefaultStatementBuilder.this.new DefaultStatementWithUpdateBuilder(\n\t\t\t\t\tUpdateType.MUTATE, Operations.mutate(target, properties));\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn result;\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate remove(Node node, String... labels) {\n\n\t\t\tDefaultStatementWithUpdateBuilder result = DefaultStatementBuilder.this.new DefaultStatementWithUpdateBuilder(\n\t\t\t\t\tUpdateType.REMOVE, Operations.set(node, labels));\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn result;\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate remove(Node node, Collection<String> labels) {\n\n\t\t\treturn remove(node, labels.toArray(new String[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate remove(Node node, Labels labels) {\n\n\t\t\tDefaultStatementWithUpdateBuilder result = DefaultStatementBuilder.this.new DefaultStatementWithUpdateBuilder(\n\t\t\t\t\tUpdateType.REMOVE, Operations.remove(node, labels));\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn result;\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate remove(Property... properties) {\n\n\t\t\tDefaultStatementWithUpdateBuilder result = DefaultStatementBuilder.this.new DefaultStatementWithUpdateBuilder(\n\t\t\t\t\tUpdateType.REMOVE, properties);\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn result;\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableMatchAndUpdate remove(Collection<Property> properties) {\n\n\t\t\treturn remove(properties.toArray(new Property[] {}));\n\t\t}\n\n\t\t@Override\n\t\tpublic OrderableOngoingReadingAndWithWithoutWhere with(Collection<IdentifiableElement> returnedExpressions) {\n\t\t\treturn this.with(false, returnedExpressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic OrderableOngoingReadingAndWithWithoutWhere withDistinct(Collection<IdentifiableElement> elements) {\n\t\t\treturn this.with(true, elements);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUpdate create(PatternElement... pattern) {\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn DefaultStatementBuilder.this.create(pattern);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingUpdate create(Collection<? extends PatternElement> pattern) {\n\t\t\treturn create(pattern.toArray(new PatternElement[] {}));\n\t\t}\n\n\t\tprivate OrderableOngoingReadingAndWithWithoutWhere with(boolean distinct,\n\t\t\t\tCollection<IdentifiableElement> elements) {\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn DefaultStatementBuilder.this.with(distinct, elements);\n\t\t}\n\n\t\t@Override\n\t\tpublic Statement build() {\n\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn DefaultStatementBuilder.this.buildImpl(null);\n\t\t}\n\n\t\t@Override\n\t\tpublic ForeachSourceStep foreach(SymbolicName variable) {\n\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn DefaultStatementBuilder.this.foreach(variable);\n\t\t}\n\n\t\t@Override\n\t\tpublic StatementBuilder.Terminal finish() {\n\n\t\t\tDefaultStatementBuilder.this.addUpdatingClause(this.builder.build());\n\t\t\treturn new DefaultStatementWithFinishBuilder();\n\t\t}\n\n\t}\n\n\tfinal class DefaultOngoingUnwind implements OngoingUnwind {\n\n\t\tprivate final Expression expressionToUnwind;\n\n\t\tDefaultOngoingUnwind(Expression expressionToUnwind) {\n\t\t\tthis.expressionToUnwind = expressionToUnwind;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReading as(String variable) {\n\t\t\tDefaultStatementBuilder.this.currentSinglePartElements.add(new Unwind(this.expressionToUnwind, variable));\n\t\t\treturn DefaultStatementBuilder.this;\n\t\t}\n\n\t}\n\n\tfinal class InQueryCallBuilder extends AbstractCallBuilder implements\n\n\t\t\tOngoingInQueryCallWithoutArguments, OngoingInQueryCallWithArguments, OngoingInQueryCallWithReturnFields {\n\n\t\tprivate YieldItems yieldItems;\n\n\t\tInQueryCallBuilder(ProcedureName procedureName) {\n\t\t\tsuper(procedureName);\n\t\t}\n\n\t\tStatement buildCall() {\n\n\t\t\treturn ProcedureCallImpl.create(this.procedureName, createArgumentList(), this.yieldItems,\n\t\t\t\t\tthis.conditionBuilder.buildCondition().map(Where::new).orElse(null));\n\t\t}\n\n\t\t@Override\n\t\tpublic InQueryCallBuilder withArgs(Expression... arguments) {\n\n\t\t\tsuper.arguments = arguments;\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic InQueryCallBuilder yield(SymbolicName... resultFields) {\n\n\t\t\tthis.yieldItems = YieldItems.yieldAllOf(resultFields);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic InQueryCallBuilder yield(AliasedExpression... aliasedResultFields) {\n\n\t\t\tthis.yieldItems = YieldItems.yieldAllOf(aliasedResultFields);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingWithWhere where(Condition newCondition) {\n\n\t\t\tthis.conditionBuilder.where(newCondition);\n\t\t\tDefaultStatementBuilder.this.currentSinglePartElements.add(this.buildCall());\n\t\t\treturn DefaultStatementBuilder.this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndReturn returning(Collection<? extends Expression> expressions) {\n\n\t\t\tDefaultStatementBuilder.this.currentSinglePartElements.add(this.buildCall());\n\t\t\treturn DefaultStatementBuilder.this.returning(expressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndReturn returningDistinct(Collection<? extends Expression> expressions) {\n\n\t\t\tDefaultStatementBuilder.this.currentSinglePartElements.add(this.buildCall());\n\t\t\treturn DefaultStatementBuilder.this.returningDistinct(expressions);\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingReadingAndReturn returningRaw(Expression rawExpression) {\n\t\t\tDefaultStatementBuilder.this.currentSinglePartElements.add(this.buildCall());\n\t\t\treturn DefaultStatementBuilder.this.returningRaw(rawExpression);\n\t\t}\n\n\t\t@Override\n\t\tpublic OrderableOngoingReadingAndWithWithoutWhere with(Collection<IdentifiableElement> elements) {\n\n\t\t\tDefaultStatementBuilder.this.currentSinglePartElements.add(this.buildCall());\n\t\t\treturn DefaultStatementBuilder.this.with(elements);\n\t\t}\n\n\t\t@Override\n\t\tpublic OrderableOngoingReadingAndWithWithoutWhere withDistinct(Collection<IdentifiableElement> elements) {\n\n\t\t\tDefaultStatementBuilder.this.currentSinglePartElements.add(this.buildCall());\n\t\t\treturn DefaultStatementBuilder.this.withDistinct(elements);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableSubquery call(Statement statement, IdentifiableElement... imports) {\n\n\t\t\tDefaultStatementBuilder.this.currentSinglePartElements.add(this.buildCall());\n\t\t\treturn DefaultStatementBuilder.this.call(statement, imports);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableSubquery callRawCypher(String rawCypher, Object... args) {\n\n\t\t\tDefaultStatementBuilder.this.currentSinglePartElements.add(this.buildCall());\n\t\t\treturn DefaultStatementBuilder.this.callRawCypher(rawCypher, args);\n\t\t}\n\n\t\t@Override\n\t\tpublic BuildableSubquery callInTransactions(Statement statement, Integer rows, IdentifiableElement... imports) {\n\n\t\t\tDefaultStatementBuilder.this.currentSinglePartElements.add(this.buildCall());\n\t\t\treturn DefaultStatementBuilder.this.callInTransactions(statement, rows, imports);\n\t\t}\n\n\t\t@Override\n\t\tpublic StatementBuilder.OngoingReadingWithoutWhere match(boolean optional, PatternElement... pattern) {\n\n\t\t\tDefaultStatementBuilder.this.currentSinglePartElements.add(this.buildCall());\n\t\t\treturn DefaultStatementBuilder.this.match(optional, pattern);\n\t\t}\n\n\t\t@Override\n\t\tpublic VoidCall withoutResults() {\n\t\t\tDefaultStatementBuilder.this.currentSinglePartElements.add(this.buildCall());\n\t\t\treturn DefaultStatementBuilder.this;\n\t\t}\n\n\t\t@Override\n\t\tpublic ForeachSourceStep foreach(SymbolicName variable) {\n\t\t\tDefaultStatementBuilder.this.currentSinglePartElements.add(this.buildCall());\n\t\t\treturn DefaultStatementBuilder.this.foreach(variable);\n\t\t}\n\n\t\t@Override\n\t\tpublic StatementBuilder.Terminal finish() {\n\t\t\treturn DefaultStatementBuilder.this;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Delete.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Delete.html\">Delete</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Delete extends AbstractClause implements UpdatingClause {\n\n\tprivate final ExpressionList deleteItems;\n\n\tprivate final boolean detach;\n\n\tDelete(ExpressionList deleteItems, boolean detach) {\n\t\tthis.deleteItems = deleteItems;\n\t\tthis.detach = detach;\n\t}\n\n\t/**\n\t * Creates a {@literal DELETE} clause deleting the given items.\n\t * @param toBeDeleted the item to be deleted\n\t * @param more more items to be deleted\n\t * @return a {@link Delete} clause\n\t * @since 2023.4.0\n\t */\n\tstatic Delete delete(Expression toBeDeleted, Expression... more) {\n\t\treturn delete(false, toBeDeleted, more);\n\t}\n\n\t/**\n\t * Creates a {@literal DELETE} clause deleting the given items.\n\t * @param detach set to {@literal true} for {@literal DELETE} clause detaching all\n\t * items\n\t * @param toBeDeleted the item to be deleted\n\t * @param more more items to be deleted\n\t * @return a {@link Delete} clause\n\t * @since 2023.4.0\n\t */\n\tstatic Delete delete(boolean detach, Expression toBeDeleted, Expression... more) {\n\t\tif (more == null || more.length == 0) {\n\t\t\treturn new Delete(new ExpressionList(List.of(toBeDeleted)), detach);\n\t\t}\n\n\t\tList<Expression> finalExpressionList = new ArrayList<>();\n\t\tfinalExpressionList.add(toBeDeleted);\n\t\tCollections.addAll(finalExpressionList, more);\n\n\t\treturn new Delete(new ExpressionList(finalExpressionList), detach);\n\t}\n\n\t/**\n\t * Creates a detaching {@literal DELETE} clause deleting the given items.\n\t * @param toBeDeleted the item to be deleted\n\t * @param more more items to be deleted\n\t * @return a {@link Delete} clause\n\t * @since 2023.4.0\n\t */\n\tstatic Delete detachDelete(Expression toBeDeleted, Expression... more) {\n\t\treturn delete(true, toBeDeleted, more);\n\t}\n\n\t/**\n\t * {@return true, if the `DETACH` keyword needs to be included}\n\t */\n\t@API(status = INTERNAL)\n\tpublic boolean isDetach() {\n\t\treturn this.detach;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.deleteItems.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/DistinctExpression.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.Distinct;\n\n/**\n * AST representation of the {@literal DISTINCT} keyword.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\nfinal class DistinctExpression implements Expression {\n\n\tprivate final Expression delegate;\n\n\tDistinctExpression(Expression delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tDistinct.INSTANCE.accept(visitor);\n\t\tthis.delegate.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/DurationLiteral.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.time.Duration;\n\n/**\n * A literal representing a duration value to be formatted in a way that Neo4j's Cypher\n * understands it.\n *\n * @author Michael J. Simons\n * @since 2023.2.1\n */\nfinal class DurationLiteral extends LiteralBase<Duration> {\n\n\tprivate DurationLiteral(Duration content) {\n\t\tsuper(content);\n\t}\n\n\tstatic Literal<Duration> of(Duration duration) {\n\t\treturn new DurationLiteral(duration);\n\t}\n\n\t@Override\n\tpublic Duration getContent() {\n\t\treturn this.content;\n\t}\n\n\t@Override\n\tpublic String asString() {\n\t\tvar result = new StringBuilder();\n\t\tresult.append(\"duration('P\");\n\n\t\tvar hours = this.content.toHours();\n\t\tvar minutes = this.content.toMinutesPart();\n\t\tvar seconds = this.content.toSecondsPart();\n\t\tvar nanos = this.content.toNanosPart();\n\n\t\tif (hours != 0 || minutes != 0 || seconds != 0 || nanos != 0) {\n\t\t\tresult.append(\"T\");\n\t\t}\n\t\tif (hours != 0) {\n\t\t\tresult.append(hours).append(\"H\");\n\t\t}\n\t\tif (minutes != 0) {\n\t\t\tresult.append(minutes).append(\"M\");\n\t\t}\n\t\tif (seconds != 0 || nanos != 0) {\n\t\t\tif (nanos == 0) {\n\t\t\t\tresult.append(seconds);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tresult.append(seconds + nanos / 1_000_000_000.0);\n\t\t\t}\n\t\t\tresult.append(\"S\");\n\t\t}\n\n\t\tresult.append(\"')\");\n\t\treturn result.toString();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExistentialSubquery.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * An existential sub-query can only be used in a where clause. The sub-query must consist\n * only of a match statement which may have a {@code WHERE} clause on its own but is not\n * allowed to return anything.\n *\n * @author Michael J. Simons\n * @neo4j.version 4.0.0\n * @since 2020.1.2\n */\n@API(status = STABLE, since = \"2020.1.2\")\n@Neo4jVersion(minimum = \"4.0.0\")\npublic final class ExistentialSubquery implements SubqueryExpression, Condition {\n\n\tprivate final ImportingWith importingWith;\n\n\tprivate final List<Visitable> fragments;\n\n\tprivate final Where innerWhere;\n\n\tExistentialSubquery(List<PatternElement> fragments, Where innerWhere) {\n\t\tthis.fragments = List.of(Pattern.of(fragments));\n\t\tthis.importingWith = new ImportingWith();\n\t\tthis.innerWhere = innerWhere;\n\t}\n\n\tExistentialSubquery(List<Match> fragments) {\n\t\tthis.fragments = List.copyOf(fragments);\n\t\tthis.importingWith = new ImportingWith();\n\t\tthis.innerWhere = null;\n\t}\n\n\tExistentialSubquery(Statement statement, IdentifiableElement... imports) {\n\t\tthis.fragments = List.of(statement);\n\t\tthis.importingWith = ImportingWith.of(imports);\n\t\tthis.innerWhere = null;\n\t}\n\n\tstatic ExistentialSubquery exists(List<Match> fragments) {\n\n\t\treturn new ExistentialSubquery(fragments);\n\t}\n\n\tstatic Condition exists(Statement statement, IdentifiableElement... imports) {\n\t\treturn new ExistentialSubquery(statement, imports);\n\t}\n\n\tstatic Condition exists(List<PatternElement> patternElements, Where innerWhere) {\n\t\treturn new ExistentialSubquery(patternElements, innerWhere);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.importingWith.accept(visitor);\n\t\tthis.fragments.forEach(v -> v.accept(visitor));\n\t\tVisitable.visitIfNotNull(this.innerWhere, visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesAndThen.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\n/**\n * Allows chaining of statements to some other builders.\n *\n * @param <S> the source type of the builder that ultimately builds the statement (\"SELF\")\n * @param <R> the result type of the statement\n * @author Michael J. Simons\n */\npublic interface ExposesAndThen<S extends ExposesAndThen<S, R>, R extends Statement>\n\t\textends StatementBuilder.BuildableStatement<R> {\n\n\tExposesAndThen<S, R> andThen(Statement statement);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesCall.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Arrays;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Entrypoint for building procedure calls.\n *\n * @param <T> the type of the returned builder\n * @author Michael J. Simons\n * @since 2020.0.1\n */\n@API(status = STABLE, since = \"2020.0.1\")\npublic interface ExposesCall<T> {\n\n\t/**\n\t * Starts defining a procedure call of the procedure with the given qualified name.\n\t * @param namespaceAndProcedure the procedure name of the procedure to call.\n\t * @return an ongoing definition of a call\n\t */\n\t@CheckReturnValue\n\tT call(String... namespaceAndProcedure);\n\n\t/**\n\t * Used to provide arguments to procedure calls.\n\t *\n\t * @param <T> the type of the next step\n\t */\n\tinterface ExposesWithArgs<T> {\n\n\t\t/**\n\t\t * Adds the given arguments to the ongoing call and proceeds.\n\t\t * @param arguments the list of new arguments, might be null or empty.\n\t\t * @return an ongoing standalone call on which yielded arguments might be\n\t\t * configured.\n\t\t */\n\t\t@CheckReturnValue\n\t\tT withArgs(Expression... arguments);\n\n\t}\n\n\t/**\n\t * Interface to allow creating an expression instead of a statement from an ongoing\n\t * definition. To make this generate valid Cypher the stored procedure in question\n\t * must be a valid function.\n\t *\n\t * @since 2020.1.2\n\t */\n\tinterface AsFunction {\n\n\t\t/**\n\t\t * Returns a function invocation that can be used as an expression, for example as\n\t\t * a property or inside a condition.\n\t\t * @return a function invocation that can be used as an expression\n\t\t */\n\t\tdefault Expression asFunction() {\n\t\t\treturn asFunction(false);\n\t\t}\n\n\t\t/**\n\t\t * Returns a function invocation that can be used as an expression, for example as\n\t\t * a property or inside a condition.\n\t\t * @param distinct set to true for adding the {@code DISTINCT} for any of the\n\t\t * aggregating functions.\n\t\t * @return a distinct function invocation that can be used as an expression, for\n\t\t * example as a property or inside a condition.\n\t\t * @since 2021.2.2\n\t\t */\n\t\tExpression asFunction(boolean distinct);\n\n\t}\n\n\t/**\n\t * Used to yield procedure result fields. There are no checks involved whether the\n\t * procedure being called actually returns items with the given names.\n\t *\n\t * @param <T> the type of the next step\n\t */\n\tinterface ExposesYield<T> {\n\n\t\t/**\n\t\t * Adds the given items to the {@literal YIELD} clause of the generated call.\n\t\t * @param yieldedItems the list of items to be yielded.\n\t\t * @return the ongoing standalone call to be configured.\n\t\t */\n\t\t@CheckReturnValue\n\t\tdefault T yield(String... yieldedItems) {\n\n\t\t\tSymbolicName[] names = new SymbolicName[0];\n\t\t\tif (yieldedItems != null) {\n\t\t\t\tnames = Arrays.stream(yieldedItems).map(SymbolicName::of).toArray(SymbolicName[]::new);\n\t\t\t}\n\t\t\treturn this.yield(names);\n\t\t}\n\n\t\t/**\n\t\t * Adds the given items to the {@literal YIELD} clause of the generated call.\n\t\t * @param yieldedItems the list of named items to be yielded.\n\t\t * @return the ongoing standalone call to be configured.\n\t\t * @since 2020.1.4\n\t\t */\n\t\t@CheckReturnValue\n\t\tdefault T yield(Named... yieldedItems) {\n\n\t\t\tSymbolicName[] names = new SymbolicName[0];\n\t\t\tif (yieldedItems != null) {\n\t\t\t\tnames = Arrays.stream(yieldedItems).map(Named::getRequiredSymbolicName).toArray(SymbolicName[]::new);\n\t\t\t}\n\t\t\treturn this.yield(names);\n\t\t}\n\n\t\t/**\n\t\t * Adds the given items to the {@literal YIELD} clause of the generated call.\n\t\t * @param resultFields the list of result fields to be returned.\n\t\t * @return the ongoing standalone call to be configured.\n\t\t */\n\t\t@CheckReturnValue\n\t\tT yield(SymbolicName... resultFields);\n\n\t\t/**\n\t\t * Adds the given items to the {@literal YIELD} clause of the generated call and\n\t\t * uses new aliases in the generated call.\n\t\t * @param aliasedResultFields the list of result fields to be returned with new\n\t\t * aliases given.\n\t\t * @return the ongoing standalone call to be configured.\n\t\t */\n\t\t@CheckReturnValue\n\t\tT yield(AliasedExpression... aliasedResultFields);\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesCreate.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Collection;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A step exposing a {@link #create(PatternElement...)} method.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface ExposesCreate {\n\n\t/**\n\t * Starts building a {@code CREATE} clause.\n\t * @param pattern patterns to create\n\t * @return an ongoing merge\n\t * @see Cypher#create(PatternElement...)\n\t */\n\t@CheckReturnValue\n\tStatementBuilder.OngoingUpdate create(PatternElement... pattern);\n\n\t/**\n\t * Starts building a {@code CREATE} clause.\n\t * @param pattern patterns to create\n\t * @return an ongoing merge\n\t * @since 2021.2.2\n\t * @see Cypher#create(Collection)\n\t */\n\t@CheckReturnValue\n\tStatementBuilder.OngoingUpdate create(Collection<? extends PatternElement> pattern);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesFinish.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A step to finish the query without the need to return anything.\n *\n * @author Gerrit Meier\n */\n@API(status = STABLE, since = \"2024.4.0\")\npublic interface ExposesFinish {\n\n\t@CheckReturnValue\n\tStatementBuilder.Terminal finish();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesHints.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Arrays;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A step exposing a several {@code using} methods that are provide entry points of adding\n * advanced query hints. Read more about that topic here:\n * <a href=\"https://neo4j.com/docs/cypher-manual/current/query-tuning/using/\">Planner\n * hints and the USING keyword</a>. Note that those hints are specific to Neo4j and not\n * part of openCypher.\n *\n * @author Michael J. Simons\n * @since 2021.0.0\n */\n@API(status = STABLE, since = \"2021.0.0\")\npublic interface ExposesHints {\n\n\t/**\n\t * Applies an INDEX hint for one or more properties.\n\t * <p>\n\t * Index hints are used to specify which index, if any, the planner should use as a\n\t * starting point. This can be beneficial in cases where the index statistics are not\n\t * accurate for the specific values that the query at hand is known to use, which\n\t * would result in the planner picking a non-optimal index.\n\t * <p>\n\t * Read more about SCAN hints <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/query-tuning/using/#query-using-index-hint\">here</a>.\n\t * @param properties one or properties that makes up the index. The properties must\n\t * belong to the same node.\n\t * @return a statement using an INDEX hint.\n\t */\n\t@CheckReturnValue\n\tStatementBuilder.OngoingReadingWithoutWhere usingIndex(Property... properties);\n\n\t/**\n\t * Applies an INDEX SEEL hint for one or more properties.\n\t * <p>\n\t * Index hints are used to specify which index, if any, the planner should use as a\n\t * starting point. This can be beneficial in cases where the index statistics are not\n\t * accurate for the specific values that the query at hand is known to use, which\n\t * would result in the planner picking a non-optimal index.\n\t * <p>\n\t * Read more about SCAN hints <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/query-tuning/using/#query-using-index-hint\">here</a>.\n\t * @param properties one or properties that makes up the index. The properties must\n\t * belong to the same node.\n\t * @return a statement using an INDEX SEEK hint.\n\t */\n\t@CheckReturnValue\n\tStatementBuilder.OngoingReadingWithoutWhere usingIndexSeek(Property... properties);\n\n\t/**\n\t * Applies a SCAN hint on a node.\n\t * <p>\n\t * If your query matches large parts of an index, it might be faster to scan the label\n\t * and filter out nodes that do not match.\n\t * <p>\n\t * Read more about SCAN hints <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/query-tuning/using/#query-using-scan-hint\">here</a>.\n\t * @param node the node that should be scanned\n\t * @return a statement using a SCAN hint.\n\t */\n\t@CheckReturnValue\n\tStatementBuilder.OngoingReadingWithoutWhere usingScan(Node node);\n\n\t/**\n\t * Applies a JOIN hint on one or more nodes.\n\t * <p>\n\t * Join hints are the most advanced type of hints, and are not used to find starting\n\t * points for the query execution plan, but to enforce that joins are made at\n\t * specified points. This implies that there has to be more than one starting point\n\t * (leaf) in the plan, in order for the query to be able to join the two branches\n\t * ascending from these leaves.\n\t * <p>\n\t * Read more about JOIN hints <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/query-tuning/using/#query-using-join-hint\">here</a>.\n\t * @param nodes the nodes on which a join should be started.\n\t * @return a statement using a JOIN hint.\n\t */\n\t@CheckReturnValue\n\tdefault StatementBuilder.OngoingReadingWithoutWhere usingJoinOn(Node... nodes) {\n\n\t\tAssertions.notEmpty(nodes, \"At least one node is required to define a JOIN hint.\");\n\t\treturn this.usingJoinOn(Arrays.stream(nodes).map(Node::getRequiredSymbolicName).toArray(SymbolicName[]::new));\n\t}\n\n\t/**\n\t * Applies a JOIN hint on one or more nodes identified by their names.\n\t * <p>\n\t * Join hints are the most advanced type of hints, and are not used to find starting\n\t * points for the query execution plan, but to enforce that joins are made at\n\t * specified points. This implies that there has to be more than one starting point\n\t * (leaf) in the plan, in order for the query to be able to join the two branches\n\t * ascending from these leaves.\n\t * <p>\n\t * Read more about JOIN hints <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/query-tuning/using/#query-using-join-hint\">here</a>.\n\t * @param names the symbolic names identifying the nodes.\n\t * @return a statement using a JOIN hint.\n\t */\n\t@CheckReturnValue\n\tStatementBuilder.OngoingReadingWithoutWhere usingJoinOn(SymbolicName... names);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesLoadCSV.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.net.URI;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Exposes methods to configure a {@code LOAD CSV} clause.\n *\n * @author Michael J. Simons\n * @since 2020.2.1\n */\n@API(status = STABLE, since = \"2020.2.1\")\npublic interface ExposesLoadCSV {\n\n\t/**\n\t * Starts building a {@code LOAD CSV}.\n\t * @param from the {@link URI} to load data from. Any uri that is resolvable by the\n\t * database itself is valid.\n\t * @return an ongoing definition of a {@code LOAD CSV} clause\n\t */\n\tdefault LoadCSVStatementBuilder.OngoingLoadCSV loadCSV(URI from) {\n\t\treturn loadCSV(from, false);\n\t}\n\n\t/**\n\t * Starts building a {@code LOAD CSV}.\n\t * @param from the {@link URI} to load data from. Any uri that is resolvable by the\n\t * database itself is valid.\n\t * @param withHeaders set to {@literal true} if the csv file contains header\n\t * @return an ongoing definition of a {@code LOAD CSV} clause\n\t */\n\tLoadCSVStatementBuilder.OngoingLoadCSV loadCSV(URI from, boolean withHeaders);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesLogicalOperators.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\nimport org.neo4j.cypherdsl.core.internal.RelationshipPatternCondition;\n\n/**\n * A step exposing logical operators {@code and} and {@code or} after a {@code where}\n * clause.\n *\n * @param <T> the type being returned after the new condition has been chained\n * @author Michael J. Simons\n * @since 1.1\n */\npublic interface ExposesLogicalOperators<T> {\n\n\t/**\n\t * Adds a condition to the existing conditions, connected by an {@code AND}. Existing\n\t * conditions will be logically grouped by using {@code ()} in the statement if\n\t * previous conditions used another logical operator.\n\t * @param condition an additional condition\n\t * @return the ongoing definition of a match\n\t */\n\t@CheckReturnValue\n\tT and(Condition condition);\n\n\t/**\n\t * Adds a condition based on a path pattern to the existing conditions, connected by\n\t * an {@code AND}. Existing conditions will be logically grouped by using {@code ()}\n\t * in the statement if previous conditions used another logical operator.\n\t * @param pathPattern an additional pattern to include in the conditions\n\t * @return the ongoing definition of a match\n\t */\n\t@CheckReturnValue\n\tdefault T and(RelationshipPattern pathPattern) {\n\t\treturn this.and(RelationshipPatternCondition.of(pathPattern));\n\t}\n\n\t/**\n\t * Adds a condition to the existing conditions, connected by an {@code OR}. Existing\n\t * conditions will be logically grouped by using {@code ()} in the statement if\n\t * previous conditions used another logical operator.\n\t * @param condition an additional condition\n\t * @return the ongoing definition of a match\n\t */\n\t@CheckReturnValue\n\tT or(Condition condition);\n\n\t/**\n\t * Adds a condition based on a path pattern to the existing conditions, connected by\n\t * an {@code OR}. Existing conditions will be logically grouped by using {@code ()} in\n\t * the statement if previous conditions used another logical operator.\n\t * @param pathPattern an additional pattern to include in the conditions\n\t * @return the ongoing definition of a match\n\t */\n\t@CheckReturnValue\n\tdefault T or(RelationshipPattern pathPattern) {\n\t\treturn this.or(RelationshipPatternCondition.of(pathPattern));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesMatch.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Collection;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A step exposing a {@link #match(PatternElement...)} method. This is one of the main\n * entry points of most Cypher queries.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface ExposesMatch {\n\n\t/**\n\t * Adds (another) {@code MATCH} clause.\n\t * @param pattern the patterns to match\n\t * @return an ongoing match that is used to specify an optional where and a required\n\t * return clause\n\t */\n\t@CheckReturnValue\n\tdefault StatementBuilder.OngoingReadingWithoutWhere match(PatternElement... pattern) {\n\t\treturn this.match(false, pattern);\n\t}\n\n\t/**\n\t * Adds (another) {@code MATCH} clause.\n\t * @param pattern the patterns to match\n\t * @return an ongoing match that is used to specify an optional where and a required\n\t * return clause\n\t * @since 2021.2.2\n\t */\n\t@CheckReturnValue\n\tdefault StatementBuilder.OngoingReadingWithoutWhere match(Collection<? extends PatternElement> pattern) {\n\t\treturn this.match(pattern.toArray(new PatternElement[] {}));\n\t}\n\n\t/**\n\t * Adds (another) optional {@code MATCH} clause.\n\t * @param pattern the patterns to match\n\t * @return an ongoing match that is used to specify an optional where and a required\n\t * return clause\n\t */\n\t@CheckReturnValue\n\tdefault StatementBuilder.OngoingReadingWithoutWhere optionalMatch(PatternElement... pattern) {\n\t\treturn this.match(true, pattern);\n\t}\n\n\t/**\n\t * Adds (another) optional {@code MATCH} clause.\n\t * @param pattern the patterns to match\n\t * @return an ongoing match that is used to specify an optional where and a required\n\t * return clause\n\t * @since 2021.2.2\n\t */\n\t@CheckReturnValue\n\tdefault StatementBuilder.OngoingReadingWithoutWhere optionalMatch(Collection<? extends PatternElement> pattern) {\n\t\treturn this.optionalMatch(pattern.toArray(pattern.toArray(new PatternElement[] {})));\n\t}\n\n\t/**\n\t * Adds (another) {@code MATCH} clause.\n\t * @param optional a flag whether the {@code MATCH} clause includes the\n\t * {@code OPTIONAL} keyword.\n\t * @param pattern the patterns to match\n\t * @return an ongoing match that is used to specify an optional where and a required\n\t * return clause\n\t * @since 2020.1.3\n\t */\n\t@CheckReturnValue\n\tStatementBuilder.OngoingReadingWithoutWhere match(boolean optional, PatternElement... pattern);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesMerge.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A step exposing a {@link #merge(PatternElement...)} method.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface ExposesMerge {\n\n\t/**\n\t * Starts building a {@code MERGE} clause.\n\t * @param pattern patterns to merge\n\t * @return an ongoing merge\n\t * @see Cypher#merge(PatternElement...)\n\t */\n\t@CheckReturnValue\n\tStatementBuilder.OngoingMerge merge(PatternElement... pattern);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesPatternLengthAccessors.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * This interface is used to derive new relationship patterns from existing\n * {@link Relationship relationships} or {@link RelationshipChain chains of relationships}\n * with new lengths (min, max or unbounded) configured.\n *\n * @param <T> the type of the patterns whose lengths can be adjusted.\n * @author Michael J. Simons\n * @since 2021.2.3\n */\n@API(status = STABLE, since = \"2021.2.3\")\npublic interface ExposesPatternLengthAccessors<T extends RelationshipPattern> {\n\n\t/**\n\t * Creates a new relationship pattern with an unbound length minimum length.\n\t * @return the new relationship\n\t * @since 1.1.1\n\t */\n\tT unbounded();\n\n\t/**\n\t * Creates a new relationship pattern with a new minimum length.\n\t * @param minimum the new minimum\n\t * @return the new relationship\n\t */\n\tT min(Integer minimum);\n\n\t/**\n\t * Creates a new relationship pattern with a new maximum length.\n\t * @param maximum the new maximum\n\t * @return the new relationship\n\t */\n\tT max(Integer maximum);\n\n\t/**\n\t * Creates a new relationship pattern with a new length.\n\t * @param minimum the new minimum\n\t * @param maximum the new maximum\n\t * @return the new relationship\n\t */\n\tT length(Integer minimum, Integer maximum);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesProperties.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Map;\n\n/**\n * A container that exposes methods to add properties with values to nodes or\n * relationships.\n *\n * @param <T> type of the object holding the specified properties\n * @author Michael J. Simons\n * @since 1.1\n */\npublic interface ExposesProperties<T extends ExposesProperties<?> & PropertyContainer> {\n\n\t/**\n\t * Creates a copy of this property container with additional properties. Creates a\n\t * property container without properties when no properties are passed to this method.\n\t * @param newProperties the new properties (can be {@literal null} to remove exiting\n\t * properties).\n\t * @return the new property container.\n\t */\n\tT withProperties(MapExpression newProperties);\n\n\t/**\n\t * Creates a copy of this property container with additional properties. Creates a\n\t * property container without properties when no properties are passed to this method.\n\t * @param keysAndValues a list of key and values. Must be an even number, with\n\t * alternating {@link String} and {@link Expression}.\n\t * @return the new property container.\n\t */\n\tT withProperties(Object... keysAndValues);\n\n\t/**\n\t * Creates a copy of this property container with additional properties.\n\t * @param newProperties a map with the new properties\n\t * @return the new property container.\n\t */\n\tT withProperties(Map<String, Object> newProperties);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesRelationships.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A marker interface for things that expose methods to create new relationships to other\n * elements.\n *\n * @param <T> the type of the resulting {@link RelationshipPattern}\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface ExposesRelationships<T extends RelationshipPattern & ExposesPatternLengthAccessors<?>> {\n\n\t/**\n\t * Starts building an outgoing relationship to the {@code other} {@link Node node}.\n\t * @param other the other end of the outgoing relationship\n\t * @param types the types to match\n\t * @return an ongoing relationship definition, that can be used to specify the type\n\t */\n\tT relationshipTo(Node other, String... types);\n\n\t/**\n\t * Starts building an incoming relationship starting at the {@code other} {@link Node\n\t * node}.\n\t * @param other the source of the incoming relationship\n\t * @param types the types to match\n\t * @return an ongoing relationship definition, that can be used to specify the type\n\t */\n\tT relationshipFrom(Node other, String... types);\n\n\t/**\n\t * Starts building an undirected relationship between this {@link Node node} and the\n\t * {@code other}.\n\t * @param other the other end of the relationship\n\t * @param types the types to match\n\t * @return an ongoing relationship definition, that can be used to specify the type\n\t */\n\tT relationshipBetween(Node other, String... types);\n\n\t/**\n\t * A convenience method for creating relationships between nodes avoiding going\n\t * through the fluent API by allowing to pass in the type directly.\n\t * @param other the other end of the relationship\n\t * @param direction the direction of the relationship, seen from {@code this} node\n\t * @param types the type of the relationship to create or the types to match\n\t * @return an ongoing relationship definition, that can be used to specify details of\n\t * the relationship\n\t * @since 2023.5.0\n\t */\n\tdefault T relationshipWith(Node other, Relationship.Direction direction, String... types) {\n\t\treturn switch (direction) {\n\t\t\tcase LTR -> this.relationshipTo(other, types);\n\t\t\tcase RTL -> this.relationshipFrom(other, types);\n\t\t\tcase UNI -> this.relationshipBetween(other, types);\n\t\t};\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesReturning.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Arrays;\nimport java.util.Collection;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Return part of a statement.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface ExposesReturning {\n\n\t/**\n\t * Creates the {@code RETURN} clause. All variables passed via {@code variables} must\n\t * be valid {@link SymbolicName symbolic names}.\n\t * {@link Expression#property(String...)} must be used to return single properties.\n\t * @param variables the named things to return\n\t * @return a build step with a defined list of things to return.\n\t */\n\t@CheckReturnValue\n\tdefault StatementBuilder.OngoingReadingAndReturn returning(String... variables) {\n\t\treturn returning(Expressions.createSymbolicNames(variables));\n\t}\n\n\t/**\n\t * Creates the {@code RETURN} clause.\n\t * @param variables the named things to return\n\t * @return a build step with a defined list of things to return.\n\t */\n\t@CheckReturnValue\n\tdefault StatementBuilder.OngoingReadingAndReturn returning(Named... variables) {\n\t\treturn returning(Expressions.createSymbolicNames(variables));\n\t}\n\n\t/**\n\t * Create a match that returns one or more expressions.\n\t * @param expressions the expressions to be returned. Must not be null and be at least\n\t * one expression.\n\t * @return a match that can be build now\n\t */\n\t@CheckReturnValue\n\tdefault StatementBuilder.OngoingReadingAndReturn returning(Expression... expressions) {\n\t\treturn returning((expressions != null) ? Arrays.asList(expressions) : null);\n\t}\n\n\t/**\n\t * Create a match that returns one or more expressions.\n\t * @param expressions the expressions to be returned. Must not be null and be at least\n\t * one expression.\n\t * @return a match that can be build now\n\t */\n\t@CheckReturnValue\n\tStatementBuilder.OngoingReadingAndReturn returning(Collection<? extends Expression> expressions);\n\n\t/**\n\t * Creates a {@code RETURN} clause containing the {@code DISTINCT} keyword. All\n\t * variables passed via {@code variables} must be valid {@link SymbolicName symbolic\n\t * names}. {@link Expression#property(String...)} must be used to return single\n\t * properties.\n\t * @param variables the variables to return\n\t * @return a build step with a defined list of things to return.\n\t */\n\t@CheckReturnValue\n\tdefault StatementBuilder.OngoingReadingAndReturn returningDistinct(String... variables) {\n\t\treturn returningDistinct(Expressions.createSymbolicNames(variables));\n\t}\n\n\t/**\n\t * Creates a {@code RETURN} clause containing the {@code DISTINCT} keyword.\n\t * @param variables the named things to return\n\t * @return a build step with a defined list of things to return.\n\t */\n\t@CheckReturnValue\n\tdefault StatementBuilder.OngoingReadingAndReturn returningDistinct(Named... variables) {\n\t\treturn returningDistinct(Expressions.createSymbolicNames(variables));\n\t}\n\n\t/**\n\t * Creates a {@code RETURN} clause returning the distinct set of one or more\n\t * expressions.\n\t * @param expressions the expressions to be returned. Must not be null and be at least\n\t * one expression.\n\t * @return a match that can be build now\n\t */\n\t@CheckReturnValue\n\tdefault StatementBuilder.OngoingReadingAndReturn returningDistinct(Expression... expressions) {\n\t\treturn returningDistinct((expressions != null) ? Arrays.asList(expressions) : null);\n\t}\n\n\t/**\n\t * Creates a {@code RETURN} clause returning the distinct set of one or more\n\t * expressions.\n\t * @param expressions the expressions to be returned. Must not be null and be at least\n\t * one expression.\n\t * @return a match that can be build now\n\t */\n\t@CheckReturnValue\n\tStatementBuilder.OngoingReadingAndReturn returningDistinct(Collection<? extends Expression> expressions);\n\n\t/**\n\t * Creates a {@code RETURN} clause from a raw Cypher expression created via\n\t * {@link Cypher#raw(String, Object...)}. The expression maybe aliased, but it must\n\t * resolve to a raw element\n\t * @param rawExpression must be a plain raw or an aliased raw expression. To\n\t * eventually render as valid Cypher, it must contain the {@code RETURN} keyword.\n\t * @return a match that can be build now\n\t * @since 2021.2.1\n\t */\n\t@CheckReturnValue\n\tStatementBuilder.OngoingReadingAndReturn returningRaw(Expression rawExpression);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesSubqueryCall.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Arrays;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.StatementBuilder.BuildableStatement;\nimport org.neo4j.cypherdsl.core.StatementBuilder.OngoingReadingWithoutWhere;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * This exposes a call method taking in a statement that represents a valid, correlated\n * subquery.\n *\n * @author Michael J. Simons\n * @neo4j.version 4.0.0\n * @since 2020.1.2\n */\n@API(status = STABLE, since = \"2020.1.2\")\n@Neo4jVersion(minimum = \"4.0.0\")\npublic interface ExposesSubqueryCall {\n\n\t/**\n\t * The {@link Statement subquery} parameter must be a valid subquery.\n\t * <ul>\n\t * <li>can be a unit statement</li>\n\t * <li>cannot refer to variables from the enclosing query</li>\n\t * <li>cannot return variables with the same names as variables in the enclosing\n\t * query</li>\n\t * <li>All variables that are returned from a subquery are afterwards available in the\n\t * enclosing query</li>\n\t * </ul>\n\t * @param statement the statement representing the subquery.\n\t * @return an ongoing reading\n\t */\n\t@CheckReturnValue\n\tdefault BuildableSubquery call(Statement statement) {\n\t\tif (statement instanceof MultiPartQuery multiPartQuery) {\n\t\t\tvar parts = multiPartQuery.getParts();\n\t\t\tif (!parts.isEmpty() && parts.get(0).isImporting()) {\n\t\t\t\treturn call(multiPartQuery.stripFirst(), parts.get(0).getImports());\n\t\t\t}\n\t\t}\n\t\treturn call(statement, new IdentifiableElement[0]);\n\t}\n\n\t/**\n\t * The {@link Statement subquery} parameter must be a valid subquery.\n\t * <ul>\n\t * <li>must end with a RETURN clause</li>\n\t * <li>cannot refer to variables from the enclosing query</li>\n\t * <li>cannot return variables with the same names as variables in the enclosing\n\t * query</li>\n\t * <li>All variables that are returned from a subquery are afterwards available in the\n\t * enclosing query</li>\n\t * </ul>\n\t * @param statement the statement representing the subquery.\n\t * @param imports additional things that should be imported into the subquery.\n\t * @return an ongoing reading\n\t * @since 2021.3.0\n\t */\n\t@CheckReturnValue\n\tdefault BuildableSubquery call(Statement statement, String... imports) {\n\t\treturn call(statement, Arrays.stream(imports).map(SymbolicName::of).toArray(SymbolicName[]::new));\n\t}\n\n\t/**\n\t * The {@link Statement subquery} parameter must be a valid sub-query.\n\t * <ul>\n\t * <li>must end with a RETURN clause</li>\n\t * <li>cannot refer to variables from the enclosing query</li>\n\t * <li>cannot return variables with the same names as variables in the enclosing\n\t * query</li>\n\t * <li>All variables that are returned from a subquery are afterwards available in the\n\t * enclosing query</li>\n\t * </ul>\n\t * @param statement the statement representing the sub-query.\n\t * @param imports additional things that should be imported into the sub-query.\n\t * {@link AliasedExpression aliased expressions} will automatically be importe twice\n\t * (once as {@code WITH a}, then {code WITH a AS alias}).\n\t * @return an ongoing reading\n\t * @since 2021.3.0\n\t */\n\t@CheckReturnValue\n\tBuildableSubquery call(Statement statement, IdentifiableElement... imports);\n\n\t/**\n\t * Starts building a new sub-query from a {@code CALL ... IN TRANSACTIONS} clause\n\t * @param statement the sub-query to be called in transactions\n\t * @return ongoing sub-query definition\n\t */\n\t@CheckReturnValue\n\tdefault BuildableSubquery callInTransactions(Statement statement) {\n\t\treturn callInTransactions(statement, (Integer) null);\n\t}\n\n\t/**\n\t * Starts building a new sub-query from a raw Cypher string that might also have\n\t * arguments as supported through {@link Cypher#raw(String, Object...)}. Use this\n\t * method as your own risk and be aware that no checks are done on the Cypher.\n\t * @param rawCypher the raw Cypher statement to call\n\t * @param args optional args that replace placeholders in the {@code rawCypher}\n\t * @return ongoing sub-query definition\n\t * @since 2023.10.0\n\t */\n\t@CheckReturnValue\n\tBuildableSubquery callRawCypher(String rawCypher, Object... args);\n\n\t/**\n\t * Creates a subquery running in its own transactions. The statement won't be checked\n\t * for a {@literal RETURN} or {@literal YIELD} clause to accommodate for\n\t * {@literal CREATE} or other clauses that are void and work in a subquery if the\n\t * outer query is void, too.\n\t * @param statement the statement representing the subquery.\n\t * @param rows the number of rows per transactional batch, leave {@literal NULL} for\n\t * the default value\n\t * @return an ongoing reading, that is also buildable for outer queries that are void.\n\t * @since 2022.3.0\n\t */\n\t@CheckReturnValue\n\tdefault BuildableSubquery callInTransactions(Statement statement, Integer rows) {\n\t\tif (statement instanceof MultiPartQuery multiPartQuery) {\n\t\t\tvar parts = multiPartQuery.getParts();\n\t\t\tif (!parts.isEmpty() && parts.get(0).isImporting()) {\n\t\t\t\treturn callInTransactions(multiPartQuery.stripFirst(), rows, parts.get(0).getImports());\n\t\t\t}\n\t\t}\n\n\t\treturn callInTransactions(statement, rows, new IdentifiableElement[0]);\n\t}\n\n\t/**\n\t * Creates a subquery running in its own transactions. The statement won't be checked\n\t * for a {@literal RETURN} or {@literal YIELD} clause to accommodate for\n\t * {@literal CREATE} or other clauses that are void and work in a subquery if the\n\t * outer query is void, too.\n\t * @param statement the statement representing the subquery.\n\t * @param imports additional things that should be imported into the subquery.\n\t * @return an ongoing reading, that is also buildable for outer queries that are void.\n\t * @since 2022.3.0\n\t */\n\t@CheckReturnValue\n\tdefault BuildableSubquery callInTransactions(Statement statement, String... imports) {\n\t\treturn callInTransactions(statement, null,\n\t\t\t\tArrays.stream(imports).map(SymbolicName::of).toArray(SymbolicName[]::new));\n\t}\n\n\t/**\n\t * Creates a subquery running in its own transactions. The statement won't be checked\n\t * for a {@literal RETURN} or {@literal YIELD} clause to accommodate for\n\t * {@literal CREATE} or other clauses that are void and work in a subquery if the\n\t * outer query is void, too.\n\t * @param statement the statement representing the subquery.\n\t * @param rows the number of rows per transactional batch, leave {@literal NULL} for\n\t * the default value\n\t * @param imports additional things that should be imported into the subquery.\n\t * @return an ongoing reading, that is also buildable for outer queries that are void.\n\t * @since 2022.3.0\n\t */\n\t@CheckReturnValue\n\tdefault BuildableSubquery callInTransactions(Statement statement, Integer rows, String... imports) {\n\t\treturn callInTransactions(statement, rows,\n\t\t\t\tArrays.stream(imports).map(SymbolicName::of).toArray(SymbolicName[]::new));\n\t}\n\n\t/**\n\t * Creates a subquery running in its own transactions. The statement won't be checked\n\t * for a {@literal RETURN} or {@literal YIELD} clause to accommodate for\n\t * {@literal CREATE} or other clauses that are void and work in a subquery if the\n\t * outer query is void, too.\n\t * @param statement the statement representing the subquery.\n\t * @param imports additional things that should be imported into the subquery.\n\t * {@link AliasedExpression aliased expressions} will automatically imported twice\n\t * (once as WITH a, then WITH a AS alias).\n\t * @return an ongoing reading, that is also buildable for outer queries that are void.\n\t * @since 2022.3.0\n\t */\n\tdefault BuildableSubquery callInTransactions(Statement statement, IdentifiableElement... imports) {\n\t\treturn callInTransactions(statement, null, imports);\n\t}\n\n\t/**\n\t * Creates a subquery running in its own transactions. The statement won't be checked\n\t * for a {@literal RETURN} or {@literal YIELD} clause to accommodate for\n\t * {@literal CREATE} or other clauses that are void and work in a subquery if the\n\t * outer query is void, too.\n\t * @param statement the statement representing the subquery.\n\t * @param rows the number of rows per transactional batch, leave {@literal NULL} for\n\t * the default value\n\t * @param imports additional things that should be imported into the subquery.\n\t * {@link AliasedExpression aliased expressions} will automatically imported twice\n\t * (once as WITH a, then WITH a AS alias).\n\t * @return an ongoing reading, that is also buildable for outer queries that are void.\n\t * @since 2022.3.0\n\t */\n\t@CheckReturnValue\n\tBuildableSubquery callInTransactions(Statement statement, Integer rows, IdentifiableElement... imports);\n\n\t/**\n\t * Subqueries can be valid without any further return statement (i.e when the subquery\n\t * is a {@literal void} ({@literal unit}) one, meaning it doesn't yield or return its\n\t * results. The Cypher-DSL doesn't do any checking here, so please be careful when\n\t * using that construct.\n\t *\n\t * @since 2022.3.0\n\t */\n\tinterface BuildableSubquery extends OngoingReadingWithoutWhere, BuildableStatement<Statement> {\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesUnwind.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A step exposing a {@link #unwind(Expression...)},{@link #unwind(Expression)},\n * {@link #unwind(String)} and method.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface ExposesUnwind {\n\n\t/**\n\t * Starts building a new {@code UNWIND} clause.\n\t * @param expressions the things to unwind.\n\t * @return an ongoing definition of an unwind.\n\t */\n\t@CheckReturnValue\n\tdefault StatementBuilder.OngoingUnwind unwind(Expression... expressions) {\n\t\treturn unwind(Cypher.listOf(expressions));\n\t}\n\n\t/**\n\t * Starts building a new {@code UNWIND} clause.\n\t * @param variable the thing to unwind.\n\t * @return an ongoing definition of an unwind.\n\t */\n\t@CheckReturnValue\n\tdefault StatementBuilder.OngoingUnwind unwind(String variable) {\n\t\treturn unwind(Cypher.name(variable));\n\t}\n\n\t/**\n\t * Starts building a new {@code UNWIND} clause.\n\t * @param expression the things to unwind.\n\t * @return an ongoing definition of an unwind.\n\t */\n\tStatementBuilder.OngoingUnwind unwind(Expression expression);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesWhere.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\nimport org.neo4j.cypherdsl.core.internal.RelationshipPatternCondition;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A step exposing a several {@code where} methods that are provide entry points of adding\n * conditions.\n *\n * @param <T> the type of the owner exposing the {@literal WHERE} clause\n * @author Michael J. Simons\n * @since 2020.0.1\n */\n@API(status = STABLE, since = \"2020.0.1\")\npublic interface ExposesWhere<T> {\n\n\t/**\n\t * Adds a where clause to this fragement.\n\t * @param condition the new condition, must not be {@literal null}\n\t * @return a match or call restricted by a where clause with no return items yet.\n\t */\n\t@CheckReturnValue\n\tT where(Condition condition);\n\n\t/**\n\t * Adds a where clause based on a path pattern to this match. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/4.0/clauses/where/#query-where-patterns\">Using\n\t * path patterns in WHERE</a>.\n\t * @param pathPattern the path pattern to add to the where clause. This path pattern\n\t * must not be {@literal null} and must not introduce new variables not available in\n\t * the match.\n\t * @return a match or a call restricted by a where clause with no return items yet.\n\t * @since 1.0.1\n\t */\n\t@CheckReturnValue\n\tdefault T where(RelationshipPattern pathPattern) {\n\n\t\tAssertions.notNull(pathPattern, \"The path pattern must not be null.\");\n\t\treturn this.where(RelationshipPatternCondition.of(pathPattern));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExposesWith.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Arrays;\nimport java.util.Collection;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.StatementBuilder.OrderableOngoingReadingAndWithWithoutWhere;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A step that exposes the {@code WITH} clause. This interface used to be part of the\n * {@link StatementBuilder} and moved out of it to unify the {@literal WITH} clause taking\n * in {@link IdentifiableElement identifable elements}.\n *\n * @author Michael J. Simons\n * @since 2023.0.0\n */\n@API(status = STABLE, since = \"2023.0.0\")\npublic interface ExposesWith {\n\n\t/**\n\t * Starts a with clause by passing variables to it.\n\t * @param variables the variables to pass on to the next part\n\t * @return a match that can be build now\n\t */\n\t@CheckReturnValue\n\tdefault OrderableOngoingReadingAndWithWithoutWhere with(String... variables) {\n\t\treturn with(Expressions.createSymbolicNames(variables));\n\t}\n\n\t/**\n\t * Create a match that returns one or more identifiable elements.\n\t * @param elements the variables to pass on to the next part\n\t * @return a match that can be build now\n\t */\n\t@CheckReturnValue\n\tdefault OrderableOngoingReadingAndWithWithoutWhere with(IdentifiableElement... elements) {\n\t\treturn with(Arrays.asList(elements));\n\t}\n\n\t/**\n\t * Create a match that returns one or more identifiable elements.\n\t * @param elements the expressions to be returned. Must not be null and be at least\n\t * one expression.\n\t * @return a match that can be build now\n\t */\n\t@CheckReturnValue\n\tOrderableOngoingReadingAndWithWithoutWhere with(Collection<IdentifiableElement> elements);\n\n\t/**\n\t * Create a match that returns the distinct set of one or more identifiable elements.\n\t * @param variables the variables to pass on to the next part\n\t * @return a match that can be build now\n\t * @see #withDistinct(IdentifiableElement...)\n\t */\n\t@CheckReturnValue\n\tdefault OrderableOngoingReadingAndWithWithoutWhere withDistinct(String... variables) {\n\t\treturn withDistinct(Expressions.createSymbolicNames(variables));\n\t}\n\n\t/**\n\t * Create a match that returns the distinct set of one or more identifiable elements.\n\t * @param elements the variables to pass on to the next part\n\t * @return a match that can be build now\n\t * @see #withDistinct(IdentifiableElement...)\n\t */\n\t@CheckReturnValue\n\tdefault OrderableOngoingReadingAndWithWithoutWhere withDistinct(IdentifiableElement... elements) {\n\t\treturn withDistinct(Arrays.asList(elements));\n\t}\n\n\t/**\n\t * Create a match that returns the distinct set of one or more expressions.\n\t * @param expressions the expressions to be returned. Must not be null and be at least\n\t * one expression.\n\t * @return a match that can be build now\n\t */\n\t@CheckReturnValue\n\tOrderableOngoingReadingAndWithWithoutWhere withDistinct(Collection<IdentifiableElement> expressions);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Expression.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * An expression can be used in many places, i.e. in return statements, pattern elements\n * etc.\n *\n * @author Michael J. Simons\n * @author Aakash Sorathiya\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface Expression extends Visitable, PropertyAccessor {\n\n\t/**\n\t * Creates a condition that checks whether this {@code expression} includes all\n\t * elements of {@code rhs}.\n\t * @param rhs the other collection to compare to, must evaluate into a list during\n\t * runtime.\n\t * @return a new condition\n\t * @since 2022.7.0\n\t */\n\tdefault Condition includesAll(Expression rhs) {\n\t\treturn Conditions.includesAll(this, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether this {@code expression} includes any\n\t * element of {@code rhs}.\n\t * @param rhs the other collection to compare to, must evaluate into a list during\n\t * runtime.\n\t * @return a new condition\n\t * @since 2022.7.0\n\t */\n\tdefault Condition includesAny(Expression rhs) {\n\t\treturn Conditions.includesAny(this, rhs);\n\t}\n\n\t/**\n\t * Creates an expression with an alias. This expression does not track which or how\n\t * many aliases have been created.\n\t * @param alias the alias to use\n\t * @return an aliased expression.\n\t */\n\tdefault AliasedExpression as(String alias) {\n\n\t\tAssertions.hasText(alias, \"The alias may not be null or empty.\");\n\t\treturn new AliasedExpression(this, alias);\n\t}\n\n\t/**\n\t * This creates a {@literal size(e)} expression from this expression. The Cypher\n\t * output will semantically only be valid when this refers to a list (see <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-size\">size(list)</a>)\n\t * or when the expression is a string (see <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-size-of-string\">size()\n\t * applied to string</a>).\n\t * <p>\n\t * Any other expression will produce Cypher that is either deprecated in Neo4j &ge;\n\t * 4.4 or not supported at all.\n\t * @return the size of this expression (Either the number of items in a list or the\n\t * number of characters in a string expression).\n\t * @since 2022.1.0\n\t */\n\tdefault Expression size() {\n\n\t\treturn Functions.size(this);\n\t}\n\n\t/**\n\t * Takes the {@link #size()} expresssions and compares it for equality with the\n\t * parameter {@code expectedSize}. The same restrictions as with {@link #size()}\n\t * apply.\n\t * @param expectedSize the expected size\n\t * @return a condition\n\t * @since 2022.1.0\n\t * @see #size()\n\t */\n\tdefault Condition hasSize(Expression expectedSize) {\n\n\t\treturn Functions.size(this).isEqualTo(expectedSize);\n\t}\n\n\t/**\n\t * Reuse an existing symbolic name to alias this expression.\n\t * @param alias a symbolic name\n\t * @return an aliased expression.\n\t * @since 2021.0.2\n\t */\n\tdefault AliasedExpression as(SymbolicName alias) {\n\n\t\tAssertions.notNull(alias, \"The alias may not be null.\");\n\t\treturn as(alias.getValue());\n\t}\n\n\t/**\n\t * Transform this expression into a condition.\n\t * @return this expression as a condition. Will return the same instance if it is\n\t * already a condition.\n\t * @since 2021.2.2\n\t */\n\tdefault Condition asCondition() {\n\t\treturn (this instanceof Condition condition) ? condition : new ExpressionCondition(this);\n\t}\n\n\t/**\n\t * Creates a {@code lhs = rhs} condition.\n\t * @param rhs the right hand side of the condition\n\t * @return a new condition\n\t */\n\tdefault Condition isEqualTo(Expression rhs) {\n\t\treturn Conditions.isEqualTo(this, rhs);\n\t}\n\n\t/**\n\t * An alias for {@link #isEqualTo(Expression)}.\n\t * @param rhs the right hand side of the condition\n\t * @return a new condition\n\t */\n\tdefault Condition eq(Expression rhs) {\n\t\treturn isEqualTo(rhs);\n\t}\n\n\t/**\n\t * Creates a {@code lhs <> rhs} condition.\n\t * @param rhs the right hand side of the condition\n\t * @return a new condition\n\t */\n\tdefault Condition isNotEqualTo(Expression rhs) {\n\t\treturn Conditions.isNotEqualTo(this, rhs);\n\t}\n\n\t/**\n\t * An alias for {@link #isNotEqualTo(Expression)}.\n\t * @param rhs the right hand side of the condition\n\t * @return a new condition\n\t */\n\tdefault Condition ne(Expression rhs) {\n\t\treturn isNotEqualTo(rhs);\n\t}\n\n\t/**\n\t * Creates a {@code lhs < rhs} condition.\n\t * @param rhs the right hand side of the condition\n\t * @return a new condition\n\t */\n\tdefault Condition lt(Expression rhs) {\n\t\treturn Conditions.lt(this, rhs);\n\t}\n\n\t/**\n\t * Creates a {@code lhs <= rhs} condition.\n\t * @param rhs the right hand side of the condition\n\t * @return a new condition\n\t */\n\tdefault Condition lte(Expression rhs) {\n\t\treturn Conditions.lte(this, rhs);\n\t}\n\n\t/**\n\t * Creates a {@code lhs > rhs} condition.\n\t * @param rhs the right hand side of the condition\n\t * @return a new condition\n\t */\n\tdefault Condition gt(Expression rhs) {\n\t\treturn Conditions.gt(this, rhs);\n\t}\n\n\t/**\n\t * Creates a {@code lhs >= rhs} condition.\n\t * @param rhs the right hand side of the condition\n\t * @return a new condition\n\t */\n\tdefault Condition gte(Expression rhs) {\n\t\treturn Conditions.gte(this, rhs);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether this {@code expression} is {@literal true}.\n\t * @return a new condition\n\t */\n\tdefault Condition isTrue() {\n\t\treturn Conditions.isEqualTo(this, Cypher.literalTrue());\n\t}\n\n\t/**\n\t * Creates a condition that checks whether this {@code expression} is\n\t * {@literal false}.\n\t * @return a new condition\n\t */\n\tdefault Condition isFalse() {\n\t\treturn Conditions.isEqualTo(this, Cypher.literalFalse());\n\t}\n\n\t/**\n\t * Creates a condition that checks whether this {@code expression} matches that\n\t * {@code expression}.\n\t * @param expression the expression to match against. Must evaluate into a string\n\t * during runtime.\n\t * @return a new condition.\n\t */\n\tdefault Condition matches(Expression expression) {\n\t\treturn Conditions.matches(this, expression);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether this {@code expression} matches the given\n\t * {@code pattern}.\n\t * @param pattern the pattern to match\n\t * @return a new condition.\n\t */\n\tdefault Condition matches(String pattern) {\n\t\treturn Conditions.matches(this, Cypher.literalOf(pattern));\n\t}\n\n\t/**\n\t * Creates a condition that checks whether this {@code expression} starts with that\n\t * {@code expression}.\n\t * @param expression the expression to match against. Must evaluate into a string\n\t * during runtime.\n\t * @return a new condition.\n\t */\n\tdefault Condition startsWith(Expression expression) {\n\t\treturn Conditions.startsWith(this, expression);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether this {@code expression} contains that\n\t * {@code expression}.\n\t * @param expression the expression to match against. Must evaluate into a string\n\t * during runtime.\n\t * @return a new condition.\n\t */\n\tdefault Condition contains(Expression expression) {\n\t\treturn Conditions.contains(this, expression);\n\t}\n\n\t/**\n\t * Creates a condition that checks whether this {@code expression} ends with that\n\t * {@code expression}.\n\t * @param expression the expression to match against. Must evaluate into a string\n\t * during runtime.\n\t * @return a new condition.\n\t */\n\tdefault Condition endsWith(Expression expression) {\n\t\treturn Conditions.endsWith(this, expression);\n\t}\n\n\t/**\n\t * Creates an expression concatenating two string or list expressions.\n\t * @param expression the expression to concat to this expression.\n\t * @return a new expression.\n\t */\n\tdefault Operation concat(Expression expression) {\n\t\treturn Operations.concat(this, expression);\n\t}\n\n\t/**\n\t * Creates a {@code +} operation of this (the augend) and the {@code addend}.\n\t * @param addend the addend\n\t * @return a new operation.\n\t * @since 1.0.1\n\t */\n\tdefault Operation add(Expression addend) {\n\t\treturn Operations.add(this, addend);\n\t}\n\n\t/**\n\t * Creates a {@code -} operation of this (the minuend) and the {@code subtrahend}.\n\t * @param subtrahend the subtrahend\n\t * @return a new operation.\n\t * @since 1.0.1\n\t */\n\tdefault Operation subtract(Expression subtrahend) {\n\t\treturn Operations.subtract(this, subtrahend);\n\t}\n\n\t/**\n\t * Creates a {@code *} operation of this (the multiplier) and the\n\t * {@code multiplicand}.\n\t * @param multiplicand the multiplicand\n\t * @return a new operation.\n\t * @since 1.0.1\n\t */\n\tdefault Operation multiply(Expression multiplicand) {\n\t\treturn Operations.multiply(this, multiplicand);\n\t}\n\n\t/**\n\t * Creates a {@code /} operation of this (the divisor) and the {@code dividend}.\n\t * @param dividend the dividend\n\t * @return a new operation.\n\t * @since 1.0.1\n\t */\n\tdefault Operation divide(Expression dividend) {\n\t\treturn Operations.divide(this, dividend);\n\t}\n\n\t/**\n\t * Returns the remainder of this value and the {@code dividend}.\n\t * @param dividend the dividend\n\t * @return a new operation.\n\t */\n\tdefault Operation remainder(Expression dividend) {\n\t\treturn Operations.remainder(this, dividend);\n\t}\n\n\t/**\n\t * Returns the power of n of this value.\n\t * @param n power to raise this {@code Expression} to.\n\t * @return a new operation.\n\t */\n\tdefault Operation pow(Expression n) {\n\n\t\treturn Operations.pow(this, n);\n\t}\n\n\t/**\n\t * Creates a {@code IS NULL} operation for this {@code expression}. The expression\n\t * does not track the condition created here.\n\t * @return a condition based on this expression that evaluates to true when this\n\t * expression is null.\n\t */\n\tdefault Condition isNull() {\n\t\treturn Conditions.isNull(this);\n\t}\n\n\t/**\n\t * Creates a {@code IS NOT NULL} operation for this {@code expression}. The expression\n\t * does not track the condition created here.\n\t * @return a condition based on this expression that evaluates to true when this\n\t * expression is not null.\n\t */\n\tdefault Condition isNotNull() {\n\t\treturn Conditions.isNotNull(this);\n\t}\n\n\t/**\n\t * Creates a {@code IN} operation for this expression and that {@code expression}. The\n\t * expression does not track the condition created here.\n\t * @param haystack the expression to search for this expression\n\t * @return a new condition.\n\t */\n\tdefault Condition in(Expression haystack) {\n\t\treturn Comparison.create(this, Operator.IN, haystack);\n\t}\n\n\t/**\n\t * Creates a condition that evaluates to true if this expression is empty.\n\t * @return a new condition.\n\t */\n\tdefault Condition isEmpty() {\n\n\t\treturn Functions.size(this).isEqualTo(Cypher.literalOf(0L));\n\t}\n\n\t/**\n\t * The property does not track the sort items created here.\n\t * @return a sort item for this property in descending order\n\t */\n\tdefault SortItem descending() {\n\n\t\treturn SortItem.create(this, SortItem.Direction.DESC);\n\t}\n\n\t/**\n\t * The property does not track the sort items created here.\n\t * @return a sort item for this property in ascending order\n\t */\n\tdefault SortItem ascending() {\n\n\t\treturn SortItem.create(this, SortItem.Direction.ASC);\n\t}\n\n\t/**\n\t * Creates a new sort item with the given direction.\n\t * @param direction the direction to sort\n\t * @return a new sort item.\n\t * @since 2021.4.1\n\t */\n\tdefault SortItem sorted(SortItem.Direction direction) {\n\n\t\treturn SortItem.create(this, direction);\n\t}\n\n\t@Override\n\tdefault Property property(String... names) {\n\n\t\treturn InternalPropertyImpl.create(this, names);\n\t}\n\n\t/**\n\t * Creates a new {@link Property} associated with this property container. This\n\t * property can be used as a lookup in other expressions. It does not add a value to\n\t * the property.\n\t * <p>\n\t * The new {@link Property} object is a dynamic lookup, based on the\n\t * {@code expression} passed to this method. The expression can be example another\n\t * property, a function result or a Cypher parameter. A property defined in such a way\n\t * will render as {@code p[expression]}.\n\t * <p>\n\t * Note: The property container does not track property creation and there is no\n\t * possibility to enumerate all properties that have been created for this property\n\t * container.\n\t * @param lookup the expression that is evaluated to lookup this property.\n\t * @return a new {@link Property} associated with this named container\n\t * @since 2024.1.0\n\t */\n\t@Override\n\tdefault Property property(Expression lookup) {\n\t\treturn InternalPropertyImpl.create(this, lookup);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExpressionCondition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * A condition that uses its bound expression.\n *\n * @author Andreas Berger\n * @since 2021.0.0\n */\n@API(status = INTERNAL, since = \"2021.0.0\")\nclass ExpressionCondition implements Condition {\n\n\tprivate final Expression value;\n\n\tExpressionCondition(Expression value) {\n\t\tthis.value = value;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.value.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ExpressionList.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\n/**\n * Represents a list of expressions. When visited, the expressions are treated as named\n * expression if they have declared a symbolic name as variable or as unnamed expression\n * when nameless.\n * <p>\n * Not to be mixed up with the actual {@link ListExpression}, which itself is an\n * expression.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\nclass ExpressionList extends TypedSubtree<Expression> {\n\n\tExpressionList(List<Expression> returnItems) {\n\t\tsuper(returnItems);\n\t}\n\n\tExpressionList(Expression... children) {\n\t\tsuper(children);\n\t}\n\n\t@Override\n\tprotected Visitable prepareVisit(Expression child) {\n\t\treturn Expressions.nameOrExpression(child);\n\t}\n\n\tboolean isEmpty() {\n\t\treturn super.children.isEmpty();\n\t}\n\n\t@Override\n\tprotected List<Expression> getChildren() {\n\t\treturn super.getChildren();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Expressions.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.Statement.UnionQuery;\n\n/**\n * Utility methods for dealing with expressions.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\nfinal class Expressions {\n\n\tprivate Expressions() {\n\t}\n\n\t/**\n\t * Creates a {@literal COUNT} sub-query expressions from at least one pattern.\n\t * @param requiredPattern one pattern is required\n\t * @param patternElement optional pattern\n\t * @return the immutable {@link CountExpression}\n\t * @since 2023.0.0\n\t */\n\tstatic CountExpression count(PatternElement requiredPattern, PatternElement... patternElement) {\n\t\treturn CountExpression.count(Pattern.of(requiredPattern, patternElement));\n\t}\n\n\t/**\n\t * Creates a {@literal COUNT} with an inner {@literal UNION} sub-query.\n\t * @param union the union that will be the source of the {@literal COUNT} sub-query\n\t * @return the immutable {@link CountExpression}\n\t * @since 2023.0.0\n\t */\n\tstatic CountExpression count(UnionQuery union) {\n\t\treturn CountExpression.count(union);\n\t}\n\n\t/**\n\t * Creates a {@literal COUNT} from a full statement, including its filters and\n\t * conditions. The statement may or may not have a {@literal RETURN} clause. It must\n\t * however not contain any updates. While it would render syntactically correct\n\t * Cypher, Neo4j does not support updates inside counting sub-queries.\n\t * @param statement the statement to be passed to {@code count{}}\n\t * @param imports optional imports to be used in the statement (will be imported with\n\t * {@literal WITH})\n\t * @return a counting sub-query.\n\t * @since 2023.1.0\n\t */\n\tstatic CountExpression count(Statement statement, IdentifiableElement... imports) {\n\t\treturn CountExpression.count(statement, imports);\n\t}\n\n\t/**\n\t * Creates a {@literal COUNT} expression based on a list of pattern.\n\t * @param pattern the list of patterns that shall be counted\n\t * @param where an optional where-clause\n\t * @return a count expression.\n\t * @since 2023.9.0\n\t */\n\tstatic CountExpression count(List<PatternElement> pattern, Where where) {\n\n\t\treturn CountExpression.count(pattern, where);\n\t}\n\n\t/**\n\t * Start building a new sub-query expression by importing variables into the scope\n\t * with a {@literal WITH} clause.\n\t * @param identifiableElements the identifiable elements to import\n\t * @return a builder for creating the concrete sub-query\n\t * @since 2023.0.0\n\t */\n\tstatic SubqueryExpressionBuilder with(IdentifiableElement... identifiableElements) {\n\n\t\tvar returnItems = new ExpressionList(\n\t\t\t\tArrays.stream(identifiableElements).map(IdentifiableElement::asExpression).toList());\n\t\tvar with = new With(false, returnItems, null, null, null, null);\n\t\treturn new SubqueryExpressionBuilder() {\n\t\t\t@Override\n\t\t\tpublic CountExpression count(PatternElement requiredPattern, PatternElement... patternElement) {\n\t\t\t\treturn CountExpression.count(with, Pattern.of(requiredPattern, patternElement));\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic CountExpression count(UnionQuery union) {\n\t\t\t\treturn CountExpression.count(with, union);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic CollectExpression collect(Statement statement) {\n\t\t\t\treturn CollectExpression.collect(with, statement);\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Creates a {@literal COLLECT} subquery from a statement, including its filters and\n\t * conditions. The statement must return exactly one column. It must however not\n\t * contain any updates. While it would render syntactically correct Cypher, Neo4j does\n\t * not support updates inside counting sub-queries.\n\t * @param statement the statement to be passed to {@code COLLECT{}}\n\t * @return a collecting sub-query.\n\t * @since 2023.8.0\n\t */\n\tstatic Expression collect(Statement statement) {\n\n\t\tif (!statement.doesReturnOrYield()) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"The final RETURN clause in a subquery used with COLLECT is mandatory and the RETURN clause must return exactly one column.\");\n\t\t}\n\n\t\treturn CollectExpression.collect(statement);\n\t}\n\n\t/**\n\t * Returns the name of the expression if the expression is named or the expression\n\t * itself.\n\t * @param expression possibly named with a non-empty symbolic name.\n\t * @param <T> the type being returned\n\t * @return the name of the expression if the expression is named or the expression\n\t * itself\n\t */\n\tstatic <T extends Expression> Expression nameOrExpression(T expression) {\n\n\t\tif (expression instanceof Named named) {\n\t\t\treturn named.getSymbolicName().map(Expression.class::cast).orElse(expression);\n\t\t}\n\t\telse {\n\t\t\treturn expression;\n\t\t}\n\t}\n\n\tstatic SymbolicName[] createSymbolicNames(String[] variables) {\n\t\treturn Arrays.stream(variables).map(SymbolicName::of).toArray(SymbolicName[]::new);\n\t}\n\n\tstatic SymbolicName[] createSymbolicNames(Named[] variables) {\n\t\treturn Arrays.stream(variables).map(Named::getRequiredSymbolicName).toArray(SymbolicName[]::new);\n\t}\n\n\tstatic String format(Expression expression) {\n\n\t\tif (expression instanceof Named named) {\n\t\t\treturn named.getRequiredSymbolicName().getValue();\n\t\t}\n\t\telse if (expression instanceof AliasedExpression aliasedExpression) {\n\t\t\treturn aliasedExpression.getAlias();\n\t\t}\n\t\telse if (expression instanceof SymbolicName symbolicName) {\n\t\t\treturn symbolicName.getValue();\n\t\t}\n\t\telse if (expression instanceof Property) {\n\t\t\tStringBuilder ref = new StringBuilder();\n\t\t\texpression.accept(segment -> {\n\t\t\t\tif (segment instanceof SymbolicName symbolicName) {\n\t\t\t\t\tif (!ref.isEmpty()) {\n\t\t\t\t\t\tref.append(\".\");\n\t\t\t\t\t}\n\t\t\t\t\tref.append(symbolicName.getValue());\n\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn ref.toString();\n\t\t}\n\n\t\tthrow new IllegalArgumentException(\"Cannot format expression \" + expression.toString());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Finish.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Representation of the {@code FINISH} clause.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n */\n@API(status = STABLE, since = \"2024.4.0\")\npublic final class Finish implements Clause {\n\n\tprivate static final Expression FINISH_EXPRESSION = new RawLiteral.RawElement(\"FINISH\");\n\n\tprivate Finish() {\n\n\t}\n\n\tpublic static Finish create() {\n\t\treturn new Finish();\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tFINISH_EXPRESSION.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Foreach.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Collection;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Represents the {@literal FOREACH} clause and is currently only producible via the\n * Cypher-Parser.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = STABLE, since = \"2021.3.0\")\npublic final class Foreach extends AbstractClause implements UpdatingClause {\n\n\tprivate final SymbolicName variable;\n\n\tprivate final Expression list;\n\n\tprivate final Collection<UpdatingClause> updatingClauses;\n\n\tForeach(SymbolicName v, Expression list, Collection<UpdatingClause> updatingClauses) {\n\t\tthis.variable = v;\n\t\tthis.list = list;\n\t\tthis.updatingClauses = updatingClauses;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.variable.accept(visitor);\n\t\tOperator.IN.accept(visitor);\n\t\tthis.list.accept(visitor);\n\t\tOperator.PIPE.accept(visitor);\n\t\tthis.updatingClauses.forEach(clause -> clause.accept(visitor));\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ForeignAdapter.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Represents an adapter that allows to turn foreign expressions into Cypher-DSL\n * {@link Expression expressions}.\n *\n * @param <FE> the type of the foreign expression.\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = STABLE, since = \"2021.1.0\")\npublic interface ForeignAdapter<FE> {\n\n\t/**\n\t * Adapts a foreign expression into a Cypher-DSL {@link Condition}. The memoized\n\t * expression should be something that can be evaluated into something boolean.\n\t * @return a condition\n\t * @throws IllegalArgumentException if the expression doesn't resolve into something\n\t * boolean\n\t */\n\tCondition asCondition();\n\n\t/**\n\t * Adapts a foreign expression into a Cypher-DSL {@link Expression}.\n\t * @return a native expression\n\t */\n\tExpression asExpression();\n\n\t/**\n\t * Adapts a foreign expression into a Cypher-DSL {@link Node}, that allows to address\n\t * it further down in queries.\n\t * @return a node\n\t * @throws IllegalArgumentException if the expression doesn't describe something that\n\t * can be used to describe a node\n\t */\n\tNode asNode();\n\n\t/**\n\t * Adapts a foreign expression into a Cypher-DSL {@link Relationship}, that allows to\n\t * address it further down in queries.\n\t * @return a node\n\t * @throws IllegalArgumentException if the expression doesn't describe something that\n\t * can be used to describe a node\n\t */\n\tRelationship asRelationship();\n\n\t/**\n\t * Adapts a foreign expression into a Cypher-DSL {@link SymbolicName}. The memoized\n\t * expression should ideally be something that is named or resolves to an alias.\n\t * @return a symbolic name\n\t * @throws IllegalArgumentException if a name cannot be derived from the expression.\n\t */\n\tSymbolicName asName();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ForeignAdapterFactory.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * This factory is meant to decouple the instantiating respectively concrete usage of\n * classes on the provided path as much as possible, to avoid eager loading by some JVM\n * and in turn, a class not found exception.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\nfinal class ForeignAdapterFactory {\n\n\tprivate final Map<Class<?>, Constructor<ForeignAdapter<?>>> adapterCache = new HashMap<>();\n\n\tprivate static IllegalArgumentException newCannotAdaptException(Class<?> k, Exception cause) {\n\t\tvar msg = \"Cannot adapt expressions of type \" + k.getName() + \" to Cypher-DSL expressions.\";\n\t\treturn new IllegalArgumentException(msg, cause);\n\t}\n\n\tprivate static Set<String> getInterfaces(Class<?> type) {\n\n\t\tif (type == null || type == Object.class) {\n\t\t\treturn Set.of();\n\t\t}\n\n\t\treturn Stream\n\t\t\t.concat(getInterfaces(type.getSuperclass()).stream(),\n\t\t\t\t\tArrays.stream(type.getInterfaces())\n\t\t\t\t\t\t.flatMap(i -> Stream.concat(Stream.of(i.getName()), getInterfaces(i).stream())))\n\t\t\t.collect(Collectors.toSet());\n\t}\n\n\t@SuppressWarnings(\"unchecked\") // We do check the type of expression\n\t<FE> ForeignAdapter<FE> getAdapterFor(FE expression) {\n\n\t\tif (expression == null) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot adapt literal NULL expressions.\");\n\t\t}\n\n\t\tvar constructor = this.adapterCache.computeIfAbsent(expression.getClass(), k -> {\n\t\t\tvar interfaces = getInterfaces(k);\n\t\t\tString adapterName;\n\t\t\tif (interfaces.stream().anyMatch(\"com.querydsl.core.types.Expression\"::equals)) {\n\t\t\t\tadapterName = \"org.neo4j.cypherdsl.core.QueryDSLAdapter\";\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow newCannotAdaptException(k, null);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\treturn (Constructor<ForeignAdapter<?>>) Class.forName(adapterName).getDeclaredConstructors()[0];\n\t\t\t}\n\t\t\tcatch (ClassNotFoundException ex) {\n\t\t\t\tthrow newCannotAdaptException(k, ex);\n\t\t\t}\n\t\t});\n\n\t\ttry {\n\t\t\treturn (ForeignAdapter<FE>) constructor.newInstance(expression);\n\t\t}\n\t\tcatch (InstantiationException | IllegalAccessException | InvocationTargetException ex) {\n\t\t\tthrow newCannotAdaptException(expression.getClass(), ex);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/FunctionInvocation.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.text.MessageFormat;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.function.Predicate;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/FunctionInvocation.html\">FunctionInvocation</a>.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class FunctionInvocation implements Expression {\n\n\tprivate static final MessageFormat MESSAGE_FMT_EXP_REQUIRED = new MessageFormat(\n\t\t\tCypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_FOR_FUNCTION_REQUIRED));\n\n\tprivate static final MessageFormat MESSAGE_FMT_PATTERN_REQUIRED = new MessageFormat(\n\t\t\tCypher.MESSAGES.getString(MessageKeys.ASSERTIONS_PATTERN_FOR_FUNCTION_REQUIRED));\n\n\tprivate static final MessageFormat MESSAGE_FMT_ARG_REQUIRED = new MessageFormat(\n\t\t\tCypher.MESSAGES.getString(MessageKeys.ASSERTIONS_AT_LEAST_ONE_ARG_REQUIRED));\n\n\tprivate final String functionName;\n\n\tprivate final Visitable arguments;\n\n\tprivate FunctionInvocation(String functionName, Expression... arguments) {\n\n\t\tthis.functionName = functionName;\n\t\tthis.arguments = new ExpressionList(arguments);\n\t}\n\n\tprivate FunctionInvocation(String functionName, Visitable arguments) {\n\n\t\tthis.functionName = functionName;\n\t\tthis.arguments = arguments;\n\t}\n\n\t/**\n\t * Creates a {@link FunctionInvocation} based on a simple definition without any\n\t * arguments.\n\t * @param definition the definition of a function\n\t * @return the invocation (a valid expression)\n\t * @since 2021.2.3\n\t */\n\tpublic static FunctionInvocation create(FunctionDefinition definition) {\n\n\t\treturn new FunctionInvocation(definition.getImplementationName());\n\t}\n\n\t/**\n\t * Creates a {@link FunctionInvocation} based on a simple definition with arguments.\n\t * @param definition the definition of a function\n\t * @param expressions the arguments to the function\n\t * @return the invocation (a valid expression)\n\t * @since 2021.2.3\n\t */\n\tpublic static FunctionInvocation create(FunctionDefinition definition, Expression... expressions) {\n\n\t\tString message = MESSAGE_FMT_EXP_REQUIRED.format(new Object[] { definition.getImplementationName() });\n\n\t\tAssertions.notEmpty(expressions, message);\n\t\tAssertions.notNull(expressions[0], message);\n\n\t\treturn new FunctionInvocation(definition.getImplementationName(), expressions);\n\t}\n\n\t/**\n\t * Creates a {@link FunctionInvocation} based on a simple definition with arguments\n\t * and adds the {@code distinct} operator to it. This is only supported with\n\t * {@link FunctionDefinition#isAggregate()} returning {@literal true}.\n\t * @param definition the definition of a function\n\t * @param expressions the arguments to the function\n\t * @return the invocation (a valid expression)\n\t * @since 2021.2.3\n\t */\n\tpublic static FunctionInvocation createDistinct(FunctionDefinition definition, Expression... expressions) {\n\n\t\tAssertions.isTrue(definition.isAggregate(),\n\t\t\t\tCypher.MESSAGES.getString(MessageKeys.ASSERTIONS_CORRECT_USAGE_OF_DISTINCT));\n\n\t\tString message = MESSAGE_FMT_EXP_REQUIRED.format(new Object[] { definition.getImplementationName() });\n\n\t\tAssertions.notEmpty(expressions, message);\n\t\tAssertions.notNull(expressions[0], message);\n\n\t\tExpression[] newExpressions = new Expression[expressions.length];\n\t\tnewExpressions[0] = new DistinctExpression(expressions[0]);\n\t\tSystem.arraycopy(expressions, 1, newExpressions, 1, expressions.length - 1);\n\n\t\treturn new FunctionInvocation(definition.getImplementationName(), newExpressions);\n\t}\n\n\t/**\n\t * Creates a new function invocation for a pattern element.\n\t * @param definition the definition of the function\n\t * @param pattern the argument to the function\n\t * @return a function invocation\n\t * @since 2021.2.3\n\t */\n\tpublic static FunctionInvocation create(FunctionDefinition definition, PatternElement pattern) {\n\n\t\tString message = MESSAGE_FMT_PATTERN_REQUIRED.format(new Object[] { definition.getImplementationName() });\n\t\tAssertions.notNull(pattern, message);\n\n\t\tPredicate<FunctionDefinition> isShortestPath = d -> BuiltInFunctions.Scalars.SHORTEST_PATH\n\t\t\t.getImplementationName()\n\t\t\t.equals(d.getImplementationName()) || \"allShortestPaths\".equals(d.getImplementationName());\n\n\t\treturn new FunctionInvocation(definition.getImplementationName(),\n\t\t\t\tisShortestPath.test(definition) ? Pattern.of(List.of(pattern)) : new PatternExpressionImpl(pattern));\n\t}\n\n\tstatic FunctionInvocation create(FunctionDefinition definition, TypedSubtree<?> arguments) {\n\n\t\tAssertions.notNull(arguments,\n\t\t\t\tMESSAGE_FMT_ARG_REQUIRED.format(new Object[] { definition.getImplementationName() }));\n\n\t\treturn new FunctionInvocation(definition.getImplementationName(), arguments);\n\t}\n\n\t/**\n\t * {@return the name of this function}\n\t */\n\t@API(status = INTERNAL)\n\tpublic String getFunctionName() {\n\t\treturn this.functionName;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.arguments.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n\t/**\n\t * Defines metadata for a function.\n\t */\n\t@API(status = STABLE, since = \"2020.1.0\")\n\tpublic interface FunctionDefinition {\n\n\t\t/**\n\t\t * {@return the Cypher implementation name}\n\t\t */\n\t\tString getImplementationName();\n\n\t\t/**\n\t\t * {@return <code>true</code> if this is an aggregating function}\n\t\t */\n\t\tdefault boolean isAggregate() {\n\t\t\treturn Arrays.stream(BuiltInFunctions.Aggregates.values())\n\t\t\t\t.map(BuiltInFunctions.Aggregates::getImplementationName)\n\t\t\t\t.anyMatch(v -> v.equalsIgnoreCase(getImplementationName()));\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Functions.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.TimeZone;\n\nimport org.neo4j.cypherdsl.core.BuiltInFunctions.Aggregates;\nimport org.neo4j.cypherdsl.core.BuiltInFunctions.Lists;\nimport org.neo4j.cypherdsl.core.BuiltInFunctions.Predicates;\nimport org.neo4j.cypherdsl.core.BuiltInFunctions.Scalars;\nimport org.neo4j.cypherdsl.core.BuiltInFunctions.Spatials;\nimport org.neo4j.cypherdsl.core.BuiltInFunctions.Strings;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\n/**\n * Factory methods for creating instances of {@link FunctionInvocation functions}.\n *\n * @author Michael J. Simons\n * @author Gerrit Meier\n * @author Romain Rossi\n * @since 1.0\n */\nfinal class Functions {\n\n\tprivate Functions() {\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code id{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-id\">id</a>.\n\t * @param node the node for which the internal id should be retrieved\n\t * @return a function call for {@code id()} on a node.\n\t * @deprecated see {@link #elementId(Node)} for a replacement. Neo4j the database will\n\t * remove support for {@code id(n)} at some point.\n\t */\n\t@Deprecated(since = \"2023.3.0\")\n\t@SuppressWarnings({ \"squid:S1133\" }) // Yes, I promise, this will be removed at some\n\t\t\t\t\t\t\t\t\t\t\t// point, but not yet.\n\tstatic FunctionInvocation id(Node node) {\n\n\t\tAssertions.notNull(node, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_NODE_REQUIRED));\n\n\t\treturn FunctionInvocation.create(Scalars.ID, node.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code id{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-id\">id</a>.\n\t * @param relationship the relationship for which the internal id should be retrieved\n\t * @return a function call for {@code id()} on a relationship.\n\t * @deprecated see {@link #elementId(Relationship)} for a replacement. Neo4j the\n\t * database will remove support for {@code id(n)} at some point.\n\t */\n\t@Deprecated(since = \"2023.3.0\")\n\t@SuppressWarnings({ \"squid:S1133\" }) // Yes, I promise, this will be removed at some\n\t\t\t\t\t\t\t\t\t\t\t// point, but not yet.\n\tstatic FunctionInvocation id(Relationship relationship) {\n\n\t\tAssertions.notNull(relationship, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RELATIONSHIP_REQUIRED));\n\n\t\treturn FunctionInvocation.create(Scalars.ID, relationship.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code elementId{}}.\n\t * @param node the node for which the element id should be retrieved\n\t * @return a function call for {@code elementId()} on a node.\n\t */\n\t@Neo4jVersion(minimum = \"5.0.0\")\n\tstatic FunctionInvocation elementId(Node node) {\n\n\t\tAssertions.notNull(node, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_NODE_REQUIRED));\n\n\t\treturn FunctionInvocation.create(Scalars.ELEMENT_ID, node.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code elementId{}}.\n\t * @param relationship the relationship for which the element id should be retrieved\n\t * @return a function call for {@code elementId()} on a relationship.\n\t */\n\t@Neo4jVersion(minimum = \"5.0.0\")\n\tstatic FunctionInvocation elementId(Relationship relationship) {\n\n\t\tAssertions.notNull(relationship, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RELATIONSHIP_REQUIRED));\n\n\t\treturn FunctionInvocation.create(Scalars.ELEMENT_ID, relationship.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code keys{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-keys\">keys</a>.\n\t * @param node the node which keys should be returned.\n\t * @return a function call for {@code keys()} on an expression.\n\t * @since 2021.0.2\n\t */\n\tstatic FunctionInvocation keys(Node node) {\n\n\t\tAssertions.notNull(node, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_NODE_REQUIRED));\n\t\treturn keys(node.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code keys{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-keys\">keys</a>.\n\t * @param relationship the relationship which keys should be returned.\n\t * @return a function call for {@code keys()} on an expression.\n\t * @since 2021.0.2\n\t */\n\tstatic FunctionInvocation keys(Relationship relationship) {\n\n\t\tAssertions.notNull(relationship, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RELATIONSHIP_REQUIRED));\n\t\treturn keys(relationship.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code keys{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-keys\">keys</a>.\n\t * @param expression the expressions which keys should be returned. Must resolve to a\n\t * node, relationship or map.\n\t * @return a function call for {@code keys()} on an expression.\n\t * @since 2021.0.2\n\t */\n\tstatic FunctionInvocation keys(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\n\t\tExpression param = (expression instanceof Named named) ? named.getRequiredSymbolicName() : expression;\n\t\treturn FunctionInvocation.create(Lists.KEYS, param);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code labels{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-labels\">labels</a>.\n\t * @param node the node for which the labels should be retrieved\n\t * @return a function call for {@code labels()} on a node.\n\t */\n\tstatic FunctionInvocation labels(Node node) {\n\n\t\tAssertions.notNull(node, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_NODE_REQUIRED));\n\n\t\treturn labels(node.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code labels{}}. The {@link SymbolicName\n\t * symbolic name} {@code  node} must point to a node. This can't be checked during\n\t * compile time, so please make sure of that.\n\t * <p>\n\t * See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-labels\">labels</a>.\n\t * @param node the node for which the labels should be retrieved\n\t * @return a function call for {@code labels()} on a node.\n\t * @since 2023.2.0\n\t */\n\tstatic FunctionInvocation labels(SymbolicName node) {\n\n\t\tAssertions.notNull(node, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_NODE_REQUIRED));\n\n\t\treturn FunctionInvocation.create(Lists.LABELS, node);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code type{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-type\">type</a>.\n\t * @param relationship the relationship for which the type should be retrieved\n\t * @return a function call for {@code type()} on a relationship.\n\t */\n\tstatic FunctionInvocation type(Relationship relationship) {\n\n\t\tAssertions.notNull(relationship, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RELATIONSHIP_REQUIRED));\n\n\t\treturn type(relationship.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code type{}}. The {@link SymbolicName symbolic\n\t * name} {@code relationship} must point to a relationship. This can't be checked\n\t * during compile time, so please make sure of that.\n\t * <p>\n\t * See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-type\">type</a>.\n\t * @param relationship the relationship for which the type should be retrieved\n\t * @return a function call for {@code type()} on a relationship.\n\t * @since 2023.2.0\n\t */\n\tstatic FunctionInvocation type(SymbolicName relationship) {\n\n\t\tAssertions.notNull(relationship, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RELATIONSHIP_REQUIRED));\n\n\t\treturn FunctionInvocation.create(Scalars.TYPE, relationship);\n\t}\n\n\t/**\n\t * Returns a function call for {@code count()} for one named node.\n\t * @param node the named node to be counted\n\t * @return a function call for {@code count()} for one named node\n\t * @see #count(Expression)\n\t */\n\tstatic FunctionInvocation count(Node node) {\n\n\t\tAssertions.notNull(node, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_NODE_REQUIRED));\n\n\t\treturn FunctionInvocation.create(Aggregates.COUNT, node.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code count()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-count\">count</a>.\n\t * @param expression an expression describing the things to count.\n\t * @return a function call for {@code count()} for an expression like\n\t * {@link Cypher#asterisk()} etc.\n\t */\n\tstatic FunctionInvocation count(Expression expression) {\n\n\t\treturn FunctionInvocation.create(Aggregates.COUNT, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for a {@code count()} function with {@code DISTINCT}\n\t * added.\n\t * @param node the named node to be counted\n\t * @return a function call for {@code count()} for one named node\n\t * @see #countDistinct(Expression)\n\t */\n\tstatic FunctionInvocation countDistinct(Node node) {\n\n\t\tAssertions.notNull(node, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_NODE_REQUIRED));\n\n\t\treturn FunctionInvocation.createDistinct(Aggregates.COUNT, node.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for a {@code count()} function with {@code DISTINCT}\n\t * added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-count\">count</a>.\n\t * @param expression an expression describing the things to count.\n\t * @return a function call for {@code count()} for an expression like\n\t * {@link Cypher#asterisk()} etc.\n\t */\n\tstatic FunctionInvocation countDistinct(Expression expression) {\n\n\t\treturn FunctionInvocation.createDistinct(Aggregates.COUNT, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code properties())} on nodes.\n\t * @param node the node who's properties should be returned.\n\t * @return a function call for {@code properties())}\n\t */\n\tstatic FunctionInvocation properties(Node node) {\n\n\t\tAssertions.notNull(node, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_NODE_REQUIRED));\n\n\t\treturn FunctionInvocation.create(Scalars.PROPERTIES, node.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code properties())} on relationships.\n\t * @param relationship the relationship who's properties should be returned.\n\t * @return a function call for {@code properties())}\n\t */\n\tstatic FunctionInvocation properties(Relationship relationship) {\n\n\t\tAssertions.notNull(relationship, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RELATIONSHIP_REQUIRED));\n\n\t\treturn FunctionInvocation.create(Scalars.PROPERTIES, relationship.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code properties())} on maps.\n\t * @param map the map who's properties should be returned.\n\t * @return a function call for {@code properties())}\n\t */\n\tstatic FunctionInvocation properties(MapExpression map) {\n\n\t\treturn FunctionInvocation.create(Scalars.PROPERTIES, map);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code coalesce()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-coalesce\">coalesce</a>.\n\t * @param expressions one or more expressions to be coalesced\n\t * @return a function call for {@code coalesce}.\n\t */\n\tstatic FunctionInvocation coalesce(Expression... expressions) {\n\n\t\treturn FunctionInvocation.create(Scalars.COALESCE, expressions);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code left()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-left\">left</a>.\n\t * @param expression an expression resolving to a string\n\t * @param length desired length\n\t * @return a function call for {@code left()}\n\t * @since 2023.0.2\n\t */\n\tstatic FunctionInvocation left(Expression expression, Expression length) {\n\n\t\tif (expression != null && length == null) {\n\t\t\tthrow new IllegalArgumentException(\"length might not be null when the expression is not null\");\n\t\t}\n\t\treturn FunctionInvocation.create(Strings.LEFT, expressionOrNullLit(expression), expressionOrNullLit(length));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code ltrim()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-ltrim\">ltrim</a>.\n\t * @param expression an expression resolving to a string\n\t * @return a function call for {@code ltrim()}\n\t * @since 2023.0.2\n\t */\n\tstatic FunctionInvocation ltrim(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(Strings.LTRIM, expressionOrNullLit(expression));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code replace()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-ltrim\">replace</a>.\n\t * @param original an expression that returns a string\n\t * @param search an expression that specifies the string to be replaced in\n\t * {@code original}.\n\t * @param replace an expression that specifies the replacement string.\n\t * @return a function call for {@code replace()}\n\t * @since 2023.0.2\n\t */\n\tstatic FunctionInvocation replace(Expression original, Expression search, Expression replace) {\n\n\t\treturn FunctionInvocation.create(Strings.REPLACE, expressionOrNullLit(original), expressionOrNullLit(search),\n\t\t\t\texpressionOrNullLit(replace));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code reverse()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-reverse\">reverse</a>.\n\t * @param original an expression that returns a string\n\t * @return a function call for {@code reverse()}\n\t * @since 2023.0.2\n\t */\n\tstatic FunctionInvocation reverse(Expression original) {\n\n\t\tAssertions.notNull(original, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(Strings.REVERSE, expressionOrNullLit(original));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code right()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-left\">right</a>.\n\t * @param expression an expression resolving to a string\n\t * @param length desired length\n\t * @return a function call for {@code right()}\n\t * @since 2023.0.2\n\t */\n\tstatic FunctionInvocation right(Expression expression, Expression length) {\n\n\t\tif (expression != null && length == null) {\n\t\t\tthrow new IllegalArgumentException(\"length might not be null when the expression is not null\");\n\t\t}\n\t\treturn FunctionInvocation.create(Strings.RIGHT, expressionOrNullLit(expression), expressionOrNullLit(length));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code rtrim()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-rtrim\">rtrim</a>.\n\t * @param expression an expression resolving to a string\n\t * @return a function call for {@code rtrim()}\n\t * @since 2023.0.2\n\t */\n\tstatic FunctionInvocation rtrim(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(Strings.RTRIM, expressionOrNullLit(expression));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code substring()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-substring\">rtrim</a>.\n\t * @param original an expression resolving to a string\n\t * @param start an expression that returns a positive integer, denoting the position\n\t * at which the substring will begin.\n\t * @param length an expression that returns a positive integer, denoting how many\n\t * characters of original will be returned.\n\t * @return a function call for {@code substring()}\n\t * @since 2023.0.2\n\t */\n\tstatic FunctionInvocation substring(Expression original, Expression start, Expression length) {\n\n\t\tAssertions.notNull(start, \"start is required\");\n\t\tif (length != null) {\n\t\t\treturn FunctionInvocation.create(Strings.SUBSTRING, expressionOrNullLit(original), start, length);\n\t\t}\n\t\treturn FunctionInvocation.create(Strings.SUBSTRING, expressionOrNullLit(original), start);\n\t}\n\n\tprivate static Expression expressionOrNullLit(Expression expression) {\n\t\treturn (expression != null) ? expression : Cypher.literalNull();\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code toLower()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-toLower\">toLower</a>.\n\t * @param expression an expression resolving to a string\n\t * @return a function call for {@code toLower()} for one expression\n\t */\n\tstatic FunctionInvocation toLower(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(Strings.TO_LOWER, expressionOrNullLit(expression));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code toUpper()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-toUpper\">toUpper</a>.\n\t * @param expression an expression resolving to a string\n\t * @return a function call for {@code toLower()} for one expression\n\t * @since 2023.0.2\n\t */\n\tstatic FunctionInvocation toUpper(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(Strings.TO_UPPER, expressionOrNullLit(expression));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code trim()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-trim\">trim</a>.\n\t * @param expression an expression resolving to a string\n\t * @return a function call for {@code trim()} for one expression\n\t * @since 2021.2.1\n\t */\n\tstatic FunctionInvocation trim(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(Strings.TRIM, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code split()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-split\">split</a>.\n\t * @param expression an expression resolving to a string that should be split\n\t * @param delimiter the delimiter on which to split\n\t * @return a function call for {@code split()}\n\t * @since 2021.2.1\n\t */\n\tstatic FunctionInvocation split(Expression expression, Expression delimiter) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\tAssertions.notNull(delimiter, \"The delimiter is required.\");\n\t\treturn FunctionInvocation.create(Strings.SPLIT, expression, delimiter);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code split()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-split\">split</a>.\n\t * @param expression an expression resolving to a string that should be split\n\t * @param delimiter the delimiter on which to split\n\t * @return a function call for {@code split()}\n\t * @since 2021.2.1\n\t */\n\tstatic FunctionInvocation split(Expression expression, String delimiter) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\tAssertions.notNull(delimiter, \"The delimiter is required.\");\n\t\treturn split(expression, Cypher.literalOf(delimiter));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code size()} function. {@code size} can be\n\t * applied to\n\t * <ul>\n\t * <li><a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-size\">a\n\t * list</a></li>\n\t * <li><a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-size-of-string\">to\n\t * a string</a></li>\n\t * </ul>\n\t * @param expression the expression who's size is to be returned\n\t * @return a function call for {@code size()} for one expression\n\t */\n\tstatic FunctionInvocation size(Expression expression) {\n\n\t\treturn FunctionInvocation.create(Scalars.SIZE, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code size()} function. {@code size} can be\n\t * applied to\n\t * <ul>\n\t * <li><a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-size-of-pattern-expression\">to\n\t * a pattern expression</a></li>\n\t * </ul>\n\t * @param pattern the pattern for which {@code size()} should be invoked.\n\t * @return a function call for {@code size()} for a pattern\n\t */\n\tstatic FunctionInvocation size(RelationshipPattern pattern) {\n\n\t\treturn FunctionInvocation.create(Scalars.SIZE, pattern);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code exists()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-exists\">exists</a>.\n\t * @param expression the expression who's existence is to be evaluated\n\t * @return a function call for {@code exists()} for one expression\n\t */\n\tstatic FunctionInvocation exists(Expression expression) {\n\n\t\treturn FunctionInvocation.create(Predicates.EXISTS, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code distance()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-distance\">exists</a>.\n\t * Both points need to be in the same coordinate system.\n\t * @param point1 point 1\n\t * @param point2 point 2\n\t * @return a function call for {@code distance()}\n\t */\n\tstatic FunctionInvocation distance(Expression point1, Expression point2) {\n\n\t\tAssertions.notNull(point1, \"The distance function requires two points.\");\n\t\tAssertions.notNull(point2, \"The distance function requires two points.\");\n\n\t\treturn FunctionInvocation.create(Spatials.DISTANCE, point1, point2);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code point()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point\">point</a>.\n\t * @param parameterMap the map of parameters for {@code point()}\n\t * @return a function call for {@code point()}\n\t */\n\tstatic FunctionInvocation point(MapExpression parameterMap) {\n\n\t\treturn point((Expression) parameterMap);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code point()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point\">point</a>.\n\t * <p>\n\t * This generic expression variant is useful for referencing a point inside a\n\t * parameter or another map.\n\t * @param expression an expression resolving to a valid map of parameters for\n\t * {@code point()}\n\t * @return a function call for {@code point()}\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation point(Expression expression) {\n\n\t\treturn FunctionInvocation.create(Spatials.POINT, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code point()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point\">point</a>.\n\t * @param parameter a parameter referencing a {@code point()}\n\t * @return a function call for {@code point()}\n\t * @since 2022.7.3\n\t */\n\tstatic FunctionInvocation point(Parameter<?> parameter) {\n\n\t\treturn FunctionInvocation.create(Spatials.POINT, parameter);\n\t}\n\n\t/**\n\t * Convenience method for creating a 2d cartesian point.\n\t * @param x the x coordinate\n\t * @param y the y coordinate\n\t * @return a function call for {@code point()}\n\t * @since 2022.7.3\n\t */\n\tstatic FunctionInvocation cartesian(double x, double y) {\n\n\t\treturn point(Cypher.mapOf(\"x\", Cypher.literalOf(x), \"y\", Cypher.literalOf(y)));\n\t}\n\n\t/**\n\t * Convenience method for creating a 2d coordinate in the WGS 84 coordinate system.\n\t * @param longitude the longitude\n\t * @param latitude the latitude\n\t * @return a function call for {@code point()}\n\t * @since 2022.7.3\n\t */\n\tstatic FunctionInvocation coordinate(double longitude, double latitude) {\n\n\t\treturn point(Cypher.mapOf(\"longitude\", Cypher.literalOf(longitude), \"latitude\", Cypher.literalOf(latitude)));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code point.withinBBox} function. See\n\t * <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-withinBBox\">point.withinBBox</a>.\n\t * @param point the point to check\n\t * @param lowerLeft the lower left point of the bounding box (south-west coordinate)\n\t * @param upperRight the upper right point of the bounding box (north-east coordinate)\n\t * @return a function call for {@code point.withinBBox}\n\t * @since 2022.7.3\n\t */\n\tstatic FunctionInvocation withinBBox(Expression point, Expression lowerLeft, Expression upperRight) {\n\n\t\treturn FunctionInvocation.create(() -> \"point.withinBBox\", point, lowerLeft, upperRight);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code avg()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-avg\">avg</a>.\n\t * @param expression the things to average\n\t * @return a function call for {@code avg()}\n\t */\n\tstatic FunctionInvocation avg(Expression expression) {\n\n\t\treturn FunctionInvocation.create(Aggregates.AVG, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code avg()} function with {@code DISTINCT}\n\t * added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-avg\">avg</a>.\n\t * @param expression the things to average\n\t * @return a function call for {@code avg()}\n\t */\n\tstatic FunctionInvocation avgDistinct(Expression expression) {\n\n\t\treturn FunctionInvocation.createDistinct(Aggregates.AVG, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code collect()} function.\n\t * @param variable the named thing to collect\n\t * @return a function call for {@code collect()}\n\t * @see #collect(Expression)\n\t */\n\tstatic FunctionInvocation collect(Named variable) {\n\n\t\tAssertions.notNull(variable, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_VARIABLE_REQUIRED));\n\n\t\treturn FunctionInvocation.create(Aggregates.COLLECT, variable.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code collect()} function with\n\t * {@code DISTINCT} added.\n\t * @param variable the named thing to collect\n\t * @return a function call for {@code collect()}\n\t * @see #collect(Expression)\n\t */\n\tstatic FunctionInvocation collectDistinct(Named variable) {\n\n\t\tAssertions.notNull(variable, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_VARIABLE_REQUIRED));\n\n\t\treturn FunctionInvocation.createDistinct(Aggregates.COLLECT, variable.getRequiredSymbolicName());\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code collect()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-collect\">collect</a>.\n\t * @param expression the things to collect\n\t * @return a function call for {@code collect()}\n\t */\n\tstatic FunctionInvocation collect(Expression expression) {\n\n\t\treturn FunctionInvocation.create(Aggregates.COLLECT, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code collect()} function with\n\t * {@code DISTINCT} added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-collect\">collect</a>.\n\t * @param expression the things to collect\n\t * @return a function call for {@code collect()}\n\t */\n\tstatic FunctionInvocation collectDistinct(Expression expression) {\n\n\t\treturn FunctionInvocation.createDistinct(Aggregates.COLLECT, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code max()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-max\">max</a>.\n\t * @param expression a list from which the maximum element value is returned\n\t * @return a function call for {@code max()}\n\t */\n\tstatic FunctionInvocation max(Expression expression) {\n\n\t\treturn FunctionInvocation.create(Aggregates.MAX, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code max()} function with {@code DISTINCT}\n\t * added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-max\">max</a>.\n\t * @param expression a list from which the maximum element value is returned\n\t * @return a function call for {@code max()}\n\t */\n\tstatic FunctionInvocation maxDistinct(Expression expression) {\n\n\t\treturn FunctionInvocation.createDistinct(Aggregates.MAX, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code min()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-min\">min</a>.\n\t * @param expression a list from which the minimum element value is returned\n\t * @return a function call for {@code min()}\n\t */\n\tstatic FunctionInvocation min(Expression expression) {\n\n\t\treturn FunctionInvocation.create(Aggregates.MIN, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code min()} function with {@code DISTINCT}\n\t * added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-min\">min</a>.\n\t * @param expression a list from which the minimum element value is returned\n\t * @return a function call for {@code min()}\n\t */\n\tstatic FunctionInvocation minDistinct(Expression expression) {\n\n\t\treturn FunctionInvocation.createDistinct(Aggregates.MIN, expression);\n\t}\n\n\tprivate static void assertPercentileArguments(Aggregates builtIn, Expression expression, Number percentile) {\n\t\tAssertions.notNull(expression,\n\t\t\t\t\"The numeric expression for \" + builtIn.getImplementationName() + \" is required.\");\n\t\tAssertions.notNull(percentile, \"The percentile for \" + builtIn.getImplementationName() + \" is required.\");\n\t\tfinal double p = percentile.doubleValue();\n\t\tAssertions.isTrue(p >= 0D && p <= 1D,\n\t\t\t\t\"The percentile for \" + builtIn.getImplementationName() + \" must be between 0.0 and 1.0.\");\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code percentileCont()} function. See\n\t * <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-percentilecont\">percentileCont</a>.\n\t * @param expression a numeric expression\n\t * @param percentile a numeric value between 0.0 and 1.0\n\t * @return a function call for {@code percentileCont()}\n\t */\n\tstatic FunctionInvocation percentileCont(Expression expression, Number percentile) {\n\n\t\tassertPercentileArguments(Aggregates.PERCENTILE_CONT, expression, percentile);\n\n\t\treturn FunctionInvocation.create(Aggregates.PERCENTILE_CONT, expression, new NumberLiteral(percentile));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code percentileCont()} function with\n\t * {@code DISTINCT} added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-percentilecont\">percentileCont</a>.\n\t * @param expression a numeric expression\n\t * @param percentile a numeric value between 0.0 and 1.0\n\t * @return a function call for {@code percentileCont()}\n\t */\n\tstatic FunctionInvocation percentileContDistinct(Expression expression, Number percentile) {\n\n\t\tassertPercentileArguments(Aggregates.PERCENTILE_CONT, expression, percentile);\n\n\t\treturn FunctionInvocation.createDistinct(Aggregates.PERCENTILE_CONT, expression, new NumberLiteral(percentile));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code percentileDisc()} function. See\n\t * <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-percentiledisc\">percentileDisc</a>.\n\t * @param expression a numeric expression\n\t * @param percentile a numeric value between 0.0 and 1.0\n\t * @return a function call for {@code percentileDisc()}\n\t */\n\tstatic FunctionInvocation percentileDisc(Expression expression, Number percentile) {\n\n\t\tassertPercentileArguments(Aggregates.PERCENTILE_DISC, expression, percentile);\n\n\t\treturn FunctionInvocation.create(Aggregates.PERCENTILE_DISC, expression, new NumberLiteral(percentile));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code percentileDisc()} function with\n\t * {@code DISTINCT} added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-percentiledisc\">percentileDisc</a>.\n\t * @param expression a numeric expression\n\t * @param percentile a numeric value between 0.0 and 1.0\n\t * @return a function call for {@code percentileDisc()}\n\t */\n\tstatic FunctionInvocation percentileDiscDistinct(Expression expression, Number percentile) {\n\n\t\tassertPercentileArguments(Aggregates.PERCENTILE_DISC, expression, percentile);\n\n\t\treturn FunctionInvocation.createDistinct(Aggregates.PERCENTILE_DISC, expression, new NumberLiteral(percentile));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code stDev()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-stdev\">stDev</a>.\n\t * @param expression a numeric expression\n\t * @return a function call for {@code stDev()}\n\t */\n\tstatic FunctionInvocation stDev(Expression expression) {\n\n\t\treturn FunctionInvocation.create(Aggregates.ST_DEV, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code stDev()} function with\n\t * {@code DISTINCT} added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-stdev\">stDev</a>.\n\t * @param expression a numeric expression\n\t * @return a function call for {@code stDev()}\n\t */\n\tstatic FunctionInvocation stDevDistinct(Expression expression) {\n\n\t\treturn FunctionInvocation.createDistinct(Aggregates.ST_DEV, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code stDevP()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-stdevp\">stDevP</a>.\n\t * @param expression a numeric expression\n\t * @return a function call for {@code stDevP()}\n\t */\n\tstatic FunctionInvocation stDevP(Expression expression) {\n\n\t\treturn FunctionInvocation.create(Aggregates.ST_DEV_P, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code stDevP()} function with\n\t * {@code DISTINCT} added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-stdevp\">stDevP</a>.\n\t * @param expression a numeric expression\n\t * @return a function call for {@code stDevP()}\n\t */\n\tstatic FunctionInvocation stDevPDistinct(Expression expression) {\n\n\t\treturn FunctionInvocation.createDistinct(Aggregates.ST_DEV_P, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code sum()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-sum\">sum</a>.\n\t * @param expression an expression returning a set of numeric values\n\t * @return a function call for {@code sum()}\n\t */\n\tstatic FunctionInvocation sum(Expression expression) {\n\n\t\treturn FunctionInvocation.create(Aggregates.SUM, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code sum()} function with {@code DISTINCT}\n\t * added. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#functions-sum\">sum</a>.\n\t * @param expression an expression returning a set of numeric values\n\t * @return a function call for {@code sum()}\n\t */\n\tstatic FunctionInvocation sumDistinct(Expression expression) {\n\n\t\treturn FunctionInvocation.createDistinct(Aggregates.SUM, expression);\n\t}\n\n\t/**\n\t * Returns a function call for {@code range()}.\n\t * @param start the range's start\n\t * @param end the range's end\n\t * @return a function call for {@code range()}\n\t * @see #range(Expression, Expression)\n\t */\n\tstatic FunctionInvocation range(Integer start, Integer end) {\n\n\t\treturn range(Cypher.literalOf(start), Cypher.literalOf(end));\n\t}\n\n\t/**\n\t * Return a function call for {@code range()}.\n\t * @param start the range's start\n\t * @param end the range's end\n\t * @return a function call for {@code range()}\n\t * @see #range(Expression, Expression, Expression)\n\t */\n\tstatic FunctionInvocation range(Expression start, Expression end) {\n\t\treturn range(start, end, null);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code range()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-range\">range</a>.\n\t * @param start the range's start\n\t * @param end the range's end\n\t * @param step the range's step\n\t * @return a function call for {@code range()}\n\t * @see #range(Expression, Expression, Expression)\n\t */\n\tstatic FunctionInvocation range(Integer start, Integer end, Integer step) {\n\n\t\treturn range(Cypher.literalOf(start), Cypher.literalOf(end), Cypher.literalOf(step));\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code range()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-range\">range</a>.\n\t * @param start the range's start\n\t * @param end the range's end\n\t * @param step the range's step\n\t * @return a function call for {@code range()}\n\t */\n\tstatic FunctionInvocation range(Expression start, Expression end, Expression step) {\n\n\t\tAssertions.notNull(start, \"The expression for range is required.\");\n\t\tAssertions.notNull(end, \"The expression for range is required.\");\n\n\t\tif (step == null) {\n\t\t\treturn FunctionInvocation.create(Lists.RANGE, start, end);\n\t\t}\n\t\telse {\n\t\t\treturn FunctionInvocation.create(Lists.RANGE, start, end, step);\n\t\t}\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code head()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-head\">head</a>.\n\t * @param expression a list from which the head element is returned\n\t * @return a function call for {@code head()}\n\t */\n\tstatic FunctionInvocation head(Expression expression) {\n\n\t\treturn FunctionInvocation.create(Scalars.HEAD, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for the {@code last()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-last\">last</a>.\n\t * @param expression a list from which the last element is returned\n\t * @return a function call for {@code last()}\n\t */\n\tstatic FunctionInvocation last(Expression expression) {\n\n\t\treturn FunctionInvocation.create(Scalars.LAST, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code nodes{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-nodes\">nodes</a>.\n\t * @param path the path for which the number of nodes should be retrieved\n\t * @return a function call for {@code nodes()} on a path.\n\t * @since 1.1\n\t */\n\tstatic FunctionInvocation nodes(NamedPath path) {\n\n\t\tAssertions.notNull(path, \"The path for nodes is required.\");\n\t\treturn FunctionInvocation.create(Lists.NODES,\n\t\t\t\tpath.getSymbolicName()\n\t\t\t\t\t.orElseThrow(() -> new IllegalArgumentException(\n\t\t\t\t\t\t\tCypher.MESSAGES.getString(MessageKeys.ASSERTIONS_NAMED_PATH_REQUIRED))));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code nodes{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-nodes\">nodes</a>.\n\t * @param symbolicName the symbolic name of a path for which the number of nodes\n\t * should be retrieved\n\t * @return a function call for {@code nodes{}} on a path represented by a symbolic\n\t * name.\n\t * @since 2020.1.5\n\t */\n\tstatic FunctionInvocation nodes(SymbolicName symbolicName) {\n\n\t\tAssertions.notNull(symbolicName, \"The symbolic name of the path for nodes is required.\");\n\t\treturn FunctionInvocation.create(Lists.NODES, symbolicName);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code relationships{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-relationships\">relationships</a>.\n\t * @param path the path for which the relationships should be retrieved\n\t * @return a function call for {@code relationships()} on a path.\n\t * @since 2020.0.2\n\t */\n\tstatic FunctionInvocation relationships(NamedPath path) {\n\n\t\tAssertions.notNull(path, \"The path for relationships is required.\");\n\t\treturn FunctionInvocation.create(Lists.RELATIONSHIPS,\n\t\t\t\tpath.getSymbolicName()\n\t\t\t\t\t.orElseThrow(() -> new IllegalArgumentException(\n\t\t\t\t\t\t\tCypher.MESSAGES.getString(MessageKeys.ASSERTIONS_NAMED_PATH_REQUIRED))));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code relationships{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-relationships\">relationships</a>.\n\t * @param symbolicName the symbolic name of a path for which the relationships should\n\t * be retrieved\n\t * @return a function call for {@code relationships()} on a path represented by a\n\t * symbolic name.\n\t * @since 2020.1.5\n\t */\n\tstatic FunctionInvocation relationships(SymbolicName symbolicName) {\n\n\t\tAssertions.notNull(symbolicName, \"The symbolic name of the path for relationships is required.\");\n\t\treturn FunctionInvocation.create(Lists.RELATIONSHIPS, symbolicName);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code startNode{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-startnode\">startNode</a>.\n\t * @param relationship the relationship for which the start node be retrieved\n\t * @return a function call for {@code startNode()} on a path.\n\t * @since 2020.0.2\n\t */\n\tstatic FunctionInvocation startNode(Relationship relationship) {\n\n\t\tAssertions.notNull(relationship, \"The relationship for endNode is required.\");\n\t\treturn FunctionInvocation.create(Scalars.START_NODE, relationship.getSymbolicName()\n\t\t\t.orElseThrow(() -> new IllegalArgumentException(\"The relationship needs to be named!\")));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code endNode{}}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-endnode\">endNode</a>.\n\t * @param relationship the relationship for which the end node be retrieved\n\t * @return a function call for {@code endNode()} on a path.\n\t * @since 2020.0.2\n\t */\n\tstatic FunctionInvocation endNode(Relationship relationship) {\n\n\t\tAssertions.notNull(relationship, \"The relationship for endNode is required.\");\n\t\treturn FunctionInvocation.create(Scalars.END_NODE, relationship.getSymbolicName()\n\t\t\t.orElseThrow(() -> new IllegalArgumentException(\"The relationship needs to be named!\")));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date()}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * This is the most simple form.\n\t * @return a function call for {@code date()}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation date() {\n\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DATE);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * @param year the year\n\t * @param month the month\n\t * @param day the day\n\t * @return a function call for {@code date({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation calendarDate(Integer year, Integer month, Integer day) {\n\n\t\tAssertions.notNull(year, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_YEAR_REQUIRED));\n\t\tAssertions.notNull(month, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_MONTH_REQUIRED));\n\t\tAssertions.notNull(day, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_DAY_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DATE, Cypher.mapOf(\"year\", Cypher.literalOf(year),\n\t\t\t\t\"month\", Cypher.literalOf(month), \"day\", Cypher.literalOf(day)));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * @param year the year\n\t * @param week the optional week\n\t * @param dayOfWeek the optional day of the week\n\t * @return a function call for {@code date({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation weekDate(Integer year, Integer week, Integer dayOfWeek) {\n\n\t\tAssertions.notNull(year, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_YEAR_REQUIRED));\n\t\tObject[] parameters = new Object[2 + ((week != null) ? 2 : 0) + ((dayOfWeek != null) ? 2 : 0)];\n\t\tint i = 0;\n\t\tparameters[i++] = \"year\";\n\t\tparameters[i++] = Cypher.literalOf(year);\n\t\tif (week != null) {\n\t\t\tparameters[i++] = \"week\";\n\t\t\tparameters[i++] = Cypher.literalOf(week);\n\t\t}\n\t\tif (dayOfWeek != null) {\n\t\t\tif (week == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"week is required when using dayOfWeek.\");\n\t\t\t}\n\t\t\tparameters[i++] = \"dayOfWeek\";\n\t\t\tparameters[i] = Cypher.literalOf(dayOfWeek);\n\t\t}\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DATE, Cypher.mapOf(parameters));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * @param year the year\n\t * @param quarter the optional week\n\t * @param dayOfQuarter the optional day of the week\n\t * @return a function call for {@code date({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation quarterDate(Integer year, Integer quarter, Integer dayOfQuarter) {\n\n\t\tAssertions.notNull(year, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_YEAR_REQUIRED));\n\t\tObject[] parameters = new Object[2 + ((quarter != null) ? 2 : 0) + ((dayOfQuarter != null) ? 2 : 0)];\n\t\tint i = 0;\n\t\tparameters[i++] = \"year\";\n\t\tparameters[i++] = Cypher.literalOf(year);\n\t\tif (quarter != null) {\n\t\t\tparameters[i++] = \"quarter\";\n\t\t\tparameters[i++] = Cypher.literalOf(quarter);\n\t\t}\n\t\tif (dayOfQuarter != null) {\n\t\t\tparameters[i++] = \"dayOfQuarter\";\n\t\t\tparameters[i] = Cypher.literalOf(dayOfQuarter);\n\t\t}\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DATE, Cypher.mapOf(parameters));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * @param year the year\n\t * @param ordinalDay the ordinal day of the year.\n\t * @return a function call for {@code date({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation ordinalDate(Integer year, Integer ordinalDay) {\n\n\t\tAssertions.notNull(year, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_YEAR_REQUIRED));\n\t\tObject[] parameters = new Object[2 + ((ordinalDay != null) ? 2 : 0)];\n\t\tint i = 0;\n\t\tparameters[i++] = \"year\";\n\t\tparameters[i++] = Cypher.literalOf(year);\n\t\tif (ordinalDay != null) {\n\t\t\tparameters[i++] = \"ordinalDay\";\n\t\t\tparameters[i] = Cypher.literalOf(ordinalDay);\n\t\t}\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DATE, Cypher.mapOf(parameters));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * This is the most generic form.\n\t * @param components the map to pass to {@code date({})}\n\t * @return a function call for {@code date({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation date(MapExpression components) {\n\n\t\tAssertions.notNull(components, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_COMPONENTS_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DATE, components);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * This creates a date from a string.\n\t * @param temporalValue a string representing a temporal value.\n\t * @return a function call for {@code date({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation date(String temporalValue) {\n\n\t\tAssertions.hasText(temporalValue, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TEMPORAL_VALUE_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DATE, Cypher.literalOf(temporalValue));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code date({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">date</a>.\n\t * This creates a date from a string.\n\t * @param temporalValue an expression representing a temporal value.\n\t * @return a function call for {@code date({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation date(Expression temporalValue) {\n\n\t\tAssertions.notNull(temporalValue, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TEMPORAL_VALUE_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DATE, temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code datetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/datetime/\">datetime</a>.\n\t * @return a function call for {@code datetime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation datetime() {\n\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DATETIME);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code datetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/datetime/\">datetime</a>.\n\t * @param timeZone the timezone to use when creating the temporal instance\n\t * @return a function call for {@code datetime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation datetime(TimeZone timeZone) {\n\n\t\tAssertions.notNull(timeZone, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TZ_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DATETIME, timezoneMapLiteralOf(timeZone));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code datetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/datetime/\">datetime</a>.\n\t * This is the most generic form.\n\t * @param components the map to pass to {@code datetime({})}\n\t * @return a function call for {@code datetime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation datetime(MapExpression components) {\n\n\t\tAssertions.notNull(components, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_COMPONENTS_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DATETIME, components);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code datetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">datetime</a>.\n\t * This creates a datetime from a string.\n\t * @param temporalValue a string representing a temporal value.\n\t * @return a function call for {@code datetime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation datetime(String temporalValue) {\n\n\t\tAssertions.hasText(temporalValue, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TEMPORAL_VALUE_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DATETIME, Cypher.literalOf(temporalValue));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code datetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/date/\">datetime</a>.\n\t * This creates a datetime from a string.\n\t * @param temporalValue an expression representing a temporal value.\n\t * @return a function call for {@code date({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation datetime(Expression temporalValue) {\n\n\t\tAssertions.notNull(temporalValue, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TEMPORAL_VALUE_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DATETIME, temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localdatetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localdatetime</a>.\n\t * @return a function call for {@code localdatetime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation localdatetime() {\n\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.LOCALDATETIME);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localdatetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localdatetime</a>.\n\t * @param timeZone the timezone to use when creating the temporal instance\n\t * @return a function call for {@code localdatetime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation localdatetime(TimeZone timeZone) {\n\n\t\tAssertions.notNull(timeZone, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TZ_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.LOCALDATETIME, timezoneMapLiteralOf(timeZone));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localdatetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localdatetime</a>.\n\t * This is the most generic form.\n\t * @param components the map to pass to {@code localdatetime({})}\n\t * @return a function call for {@code localdatetime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation localdatetime(MapExpression components) {\n\n\t\tAssertions.notNull(components, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_COMPONENTS_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.LOCALDATETIME, components);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localdatetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localdatetime</a>.\n\t * This creates a localdatetime from a string.\n\t * @param temporalValue a string representing a temporal value.\n\t * @return a function call for {@code localdatetime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation localdatetime(String temporalValue) {\n\n\t\tAssertions.hasText(temporalValue, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TEMPORAL_VALUE_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.LOCALDATETIME, Cypher.literalOf(temporalValue));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localdatetime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localdatetime</a>.\n\t * This creates a localdatetime from a string.\n\t * @param temporalValue an expression representing a temporal value.\n\t * @return a function call for {@code localdatetime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation localdatetime(Expression temporalValue) {\n\n\t\tAssertions.notNull(temporalValue, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TEMPORAL_VALUE_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.LOCALDATETIME, temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localtime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localtime</a>.\n\t * @return a function call for {@code localtime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation localtime() {\n\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.LOCALTIME);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localtime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localtime/\">localtime</a>.\n\t * @param timeZone the timezone to use when creating the temporal instance\n\t * @return a function call for {@code localtime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation localtime(TimeZone timeZone) {\n\n\t\tAssertions.notNull(timeZone, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TZ_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.LOCALTIME, timezoneMapLiteralOf(timeZone));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localtime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localdatetime/\">localtime</a>.\n\t * This is the most generic form.\n\t * @param components the map to pass to {@code localtime({})}\n\t * @return a function call for {@code localtime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation localtime(MapExpression components) {\n\n\t\tAssertions.notNull(components, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_COMPONENTS_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.LOCALTIME, components);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localtime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localtime/\">localtime</a>.\n\t * This creates a localtime from a string.\n\t * @param temporalValue a string representing a temporal value.\n\t * @return a function call for {@code localtime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation localtime(String temporalValue) {\n\n\t\tAssertions.hasText(temporalValue, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TEMPORAL_VALUE_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.LOCALTIME, Cypher.literalOf(temporalValue));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code localtime({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/localtime/\">localtime</a>.\n\t * This creates a localtime from a string.\n\t * @param temporalValue an expression representing a temporal value.\n\t * @return a function call for {@code localtime({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation localtime(Expression temporalValue) {\n\n\t\tAssertions.notNull(temporalValue, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TEMPORAL_VALUE_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.LOCALTIME, temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code time({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/time/\">time</a>.\n\t * @return a function call for {@code time({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation time() {\n\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.TIME);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code time({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/time/\">time</a>.\n\t * @param timeZone the timezone to use when creating the temporal instance\n\t * @return a function call for {@code time({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation time(TimeZone timeZone) {\n\n\t\tAssertions.notNull(timeZone, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TZ_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.TIME, timezoneMapLiteralOf(timeZone));\n\t}\n\n\tprivate static Expression timezoneMapLiteralOf(TimeZone timeZone) {\n\t\treturn Cypher.mapOf(\"timezone\", Cypher.literalOf(timeZone.getID()));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code time({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/time/\">time</a>.\n\t * This is the most generic form.\n\t * @param components the map to pass to {@code time({})}\n\t * @return a function call for {@code time({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation time(MapExpression components) {\n\n\t\tAssertions.notNull(components, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_COMPONENTS_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.TIME, components);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code time({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/time/\">time</a>.\n\t * This creates a time from a string.\n\t * @param temporalValue a string representing a temporal value.\n\t * @return a function call for {@code time({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation time(String temporalValue) {\n\n\t\tAssertions.hasText(temporalValue, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TEMPORAL_VALUE_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.TIME, Cypher.literalOf(temporalValue));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code time({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/time/\">time</a>.\n\t * This creates a time from a string.\n\t * @param temporalValue an expression representing a temporal value.\n\t * @return a function call for {@code time({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation time(Expression temporalValue) {\n\n\t\tAssertions.notNull(temporalValue, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_TEMPORAL_VALUE_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.TIME, temporalValue);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code duration({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/duration/\">duration</a>.\n\t * This is the most generic form.\n\t * @param components the map to pass to {@code duration({})}\n\t * @return a function call for {@code duration({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation duration(MapExpression components) {\n\n\t\tAssertions.notNull(components, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_COMPONENTS_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DURATION, components);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code duration({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/duration/\">duration</a>.\n\t * This creates a duration from a string.\n\t * @param temporalAmount a string representing a temporal amount.\n\t * @return a function call for {@code duration({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation duration(String temporalAmount) {\n\n\t\tAssertions.hasText(temporalAmount, \"The temporalAmount is required.\");\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DURATION, Cypher.literalOf(temporalAmount));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code duration({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/temporal/duration/\">duration</a>.\n\t * This creates a duration from a string.\n\t * @param temporalAmount an expression representing a temporal amount.\n\t * @return a function call for {@code duration({})}.\n\t * @since 2020.1.0\n\t */\n\tstatic FunctionInvocation duration(Expression temporalAmount) {\n\n\t\tAssertions.notNull(temporalAmount, \"The temporalAmount is required.\");\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Temporals.DURATION, temporalAmount);\n\t}\n\n\t/**\n\t * Starts building a function invocation for {@code reduce({})}.\n\t * @param variable the closure will have a variable introduced in its context. We\n\t * decide here which variable to use.\n\t * @return an ongoing definition for a function call to {@code reduce({})}.\n\t * @since 2020.1.5\n\t */\n\tstatic Reduction.OngoingDefinitionWithVariable reduce(SymbolicName variable) {\n\n\t\treturn Reduction.of(variable);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code abs({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-abs\">abs</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code abs({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation abs(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.ABS, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code ceil({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-ceil\">ceil</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code ceil({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation ceil(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.CEIL, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code floor({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-floor\">floor</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code floor({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation floor(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.FLOOR, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code rand({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-rand\">rand</a>.\n\t * @return a function call for {@code rand({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation rand() {\n\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.RAND);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code round({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-round\">round</a>.\n\t * @param value the value to round\n\t * @param expression additional parameters, length must be 0, 1 or 2: First entry is\n\t * the precision, second is the rounding mode\n\t * @return a function call for {@code round({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation round(Expression value, Expression... expression) {\n\n\t\tif (expression == null || expression.length == 0) {\n\t\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.ROUND, value);\n\t\t}\n\t\telse if (expression.length == 1) {\n\t\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.ROUND, value, expression[0]);\n\t\t}\n\t\telse if (expression.length == 2) {\n\t\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.ROUND, value, expression[0],\n\t\t\t\t\texpression[1]);\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"round() must be called with 1, 2 or 3 arguments (value, value + precision or value + precision + rounding mode.\");\n\t\t}\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code sign({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-sign\">sign</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code sign({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation sign(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.SIGN, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code e({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-e\">e</a>.\n\t * @return a function call for {@code e({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation e() {\n\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.E);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code exp({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-exp\">exp</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code exp({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation exp(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.EXP, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code log({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-log\">log</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code log({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation log(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.LOG, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code log10({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-log10\">log10</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code log10({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation log10(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.LOG10, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code sqrt({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-sqrt\">sqrt</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code sqrt({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation sqrt(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.SQRT, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code acos({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-acos\">acos</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code acos({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation acos(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.ACOS, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code asin({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-asin\">asin</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code asin({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation asin(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.ASIN, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code atan({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-atan\">atan</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code atan({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation atan(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.ATAN, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code atan2({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-atan2\">atan2</a>.\n\t * @param y the y value of a point\n\t * @param x the x value of a point\n\t * @return a function call for {@code atan2({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation atan2(Expression y, Expression x) {\n\n\t\tAssertions.notNull(y, \"y is required.\");\n\t\tAssertions.notNull(x, \"x is required.\");\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.ATAN2, y, x);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code cos({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-cos\">cos</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code cos({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation cos(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.COS, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code cot({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-cot\">cot</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code cot({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation cot(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.COT, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code degrees({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-degrees\">degrees</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code degrees({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation degrees(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.DEGREES, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code haversin({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-haversin\">haversin</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code haversin({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation haversin(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.HAVERSIN, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code pi({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-pi\">pi</a>.\n\t * @return a function call for {@code pi({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation pi() {\n\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.PI);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code radians({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-radians\">radians</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code radians({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation radians(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.RADIANS, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code sin({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-sin\">sin</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code sin({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation sin(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.SIN, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code tan({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/mathematical-numeric/#functions-tan\">tan</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code tan({})}.\n\t * @since 2021.0.0\n\t */\n\tstatic FunctionInvocation tan(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(BuiltInFunctions.MathematicalFunctions.TAN, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code toInteger({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-tointeger\">toInteger</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code toInteger({})}.\n\t * @since 2021.2.1\n\t */\n\tstatic FunctionInvocation toInteger(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(Scalars.TO_INTEGER, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code toString({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-tostring\">toString</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code toString({})}.\n\t * @since 2022.3.0\n\t */\n\tstatic FunctionInvocation toString(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(Scalars.TO_STRING, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code toStringOrNull({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/string/#functions-toStringOrNull\">toStringOrNull</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code toStringOrNull({})}.\n\t * @since 2023.0.2\n\t */\n\tstatic FunctionInvocation toStringOrNull(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(Strings.TO_STRING_OR_NULL, expressionOrNullLit(expression));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code toFloat({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-tofloat\">toFloat</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code toFloat({})}.\n\t * @since 2021.2.1\n\t */\n\tstatic FunctionInvocation toFloat(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(Scalars.TO_FLOAT, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code toBoolean({})}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-toboolean\">toBoolean</a>.\n\t * @param expression the value to pass to the function.\n\t * @return a function call for {@code toBoolean({})}.\n\t * @since 2021.2.1\n\t */\n\tstatic FunctionInvocation toBoolean(Expression expression) {\n\n\t\tAssertions.notNull(expression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_EXPRESSION_REQUIRED));\n\t\treturn FunctionInvocation.create(Scalars.TO_BOOLEAN, expression);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code linenumber({})}. Only applicable inside an\n\t * {@code LOAD CSV} clause.\n\t * @return a function call for {@code linenumber({})}.\n\t * @since 2021.2.1\n\t */\n\tstatic FunctionInvocation linenumber() {\n\n\t\treturn FunctionInvocation.create(() -> \"linenumber\");\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code file({})}. Only applicable inside an\n\t * {@code LOAD CSV} clause.\n\t * @return a function call for {@code file({})}.\n\t * @since 2021.2.1\n\t */\n\tstatic FunctionInvocation file() {\n\n\t\treturn FunctionInvocation.create(() -> \"file\");\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code randomUUID({})}. Only applicable inside an\n\t * {@code LOAD CSV} clause.\n\t * @return a function call for {@code randomUUID({})}.\n\t * @since 2022.2.1\n\t */\n\tstatic FunctionInvocation randomUUID() {\n\t\treturn FunctionInvocation.create(() -> \"randomUUID\");\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code length()}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-length\">length</a>.\n\t * @param path the path for which the length should be retrieved\n\t * @return a function call for {@code length()} on a path.\n\t * @since 2023.0.1\n\t */\n\tstatic FunctionInvocation length(NamedPath path) {\n\n\t\tAssertions.notNull(path, \"The path for length is required.\");\n\t\treturn FunctionInvocation.create(Scalars.LENGTH,\n\t\t\t\tpath.getSymbolicName()\n\t\t\t\t\t.orElseThrow(() -> new IllegalArgumentException(\n\t\t\t\t\t\t\tCypher.MESSAGES.getString(MessageKeys.ASSERTIONS_NAMED_PATH_REQUIRED))));\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code graph.names()}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/graph/#functions-graph-names\">graph.names</a>.\n\t * @return a function call for {@code graph.names()}.\n\t * @since 2023.4.0\n\t */\n\t@Neo4jVersion(minimum = \"5.0.0\")\n\tstatic FunctionInvocation graphNames() {\n\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Graph.NAMES);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code graph.propertiesByName()}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/graph/#functions-graph-propertiesByName\">graph.propertiesByName</a>.\n\t * @param name the name of the graph\n\t * @return a function call for {@code graph.propertiesByName()}.\n\t * @since 2023.4.0\n\t */\n\t@Neo4jVersion(minimum = \"5.0.0\")\n\tstatic FunctionInvocation graphPropertiesByName(Expression name) {\n\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Graph.PROPERTIES_BY_NAME, name);\n\t}\n\n\t/**\n\t * Creates a function invocation for {@code graph.byName()}. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/graph/#functions-graph-byname\">graph.byName</a>.\n\t * @param name the name of the graph\n\t * @return a function call for {@code graph.byName()}.\n\t * @since 2023.4.0\n\t */\n\t@Neo4jVersion(minimum = \"5.0.0\")\n\tstatic FunctionInvocation graphByName(Expression name) {\n\n\t\treturn FunctionInvocation.create(BuiltInFunctions.Graph.BY_NAME, name);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/HasLabelCondition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A condition checking for the presence of labels on nodes or types on relationships.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class HasLabelCondition implements Condition {\n\n\tprivate final SymbolicName nodeName;\n\n\tprivate final Visitable labels;\n\n\tprivate HasLabelCondition(SymbolicName nodeName, List<NodeLabel> nodeLabels) {\n\t\tthis.nodeName = nodeName;\n\t\tthis.labels = new TypedSubtree<>(nodeLabels) {\n\t\t\t@Override\n\t\t\tpublic String separator() {\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t};\n\t}\n\n\tprivate HasLabelCondition(SymbolicName nodeName, Labels labels) {\n\t\tthis.nodeName = nodeName;\n\t\tthis.labels = labels;\n\t}\n\n\tstatic HasLabelCondition create(SymbolicName nodeName, String... labels) {\n\n\t\tAssertions.notNull(nodeName, \"A symbolic name for the node is required.\");\n\t\tAssertions.notNull(labels, \"Labels to query are required.\");\n\t\tAssertions.notEmpty(labels, \"At least one label to query is required.\");\n\n\t\tfinal List<NodeLabel> nodeLabels = new ArrayList<>(labels.length);\n\t\tfor (String label : labels) {\n\t\t\tnodeLabels.add(new NodeLabel(label));\n\t\t}\n\n\t\treturn new HasLabelCondition(nodeName, nodeLabels);\n\t}\n\n\tstatic HasLabelCondition create(SymbolicName nodeName, Labels labels) {\n\n\t\tAssertions.notNull(nodeName, \"A symbolic name for the node is required.\");\n\t\tAssertions.notNull(labels, \"Labels to query are required.\");\n\n\t\treturn new HasLabelCondition(nodeName, labels);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.nodeName.accept(visitor);\n\t\tthis.labels.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Hint.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Optional;\n\nimport org.neo4j.cypherdsl.core.ast.ProvidesAffixes;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\n/**\n * Visitable implementing hints. See {@link ExposesHints}.\n *\n * @author Michael J. Simons\n * @since 2021.0.0\n */\npublic final class Hint implements Visitable {\n\n\tprivate final Type type;\n\n\tprivate final IndexReferences indexReferences;\n\n\tprivate final IndexProperties optionalProperties;\n\n\tprivate Hint(Type type, List<IndexReference> indexReferences, IndexProperties optionalProperties) {\n\n\t\tthis.type = type;\n\t\tthis.indexReferences = new IndexReferences(indexReferences);\n\t\tthis.optionalProperties = optionalProperties;\n\t}\n\n\t/**\n\t * Creates an index hint. Mostly useful when building elements outside the fluent DSL.\n\t * @param seek set to true to use the index for seeks only\n\t * @param properties the properties to use in the index, must know their container\n\t * @return a hint\n\t * @since 2021.2.3\n\t */\n\tpublic static Hint useIndexFor(boolean seek, Property... properties) {\n\n\t\tAssertions.notEmpty(properties, \"Cannot use an index without properties!\");\n\n\t\tList<SymbolicName> deferencedProperties = new ArrayList<>();\n\t\tIndexReference indexReference = null;\n\t\tfor (Property property : properties) {\n\t\t\tNamed container = property.getContainer();\n\n\t\t\tAssertions.notNull(container,\n\t\t\t\t\t\"Cannot use a property without a reference to a container inside an index hint.\");\n\t\t\tAssertions.isTrue(property.getNames().size() == 1,\n\t\t\t\t\t\"One single property is required. Nested properties are not supported.\");\n\n\t\t\tNodeLabel label;\n\t\t\tif (container instanceof Node node) {\n\t\t\t\tList<NodeLabel> labels = node.getLabels();\n\t\t\t\tAssertions.isTrue(labels.size() == 1, \"Exactly one label is required to define the index.\");\n\t\t\t\tlabel = labels.get(0);\n\t\t\t}\n\t\t\telse if (container instanceof Relationship relationship) {\n\t\t\t\tList<String> types = relationship.getDetails().getTypes();\n\t\t\t\tAssertions.isTrue(types.size() == 1, \"Exactly one type is required to define the index.\");\n\t\t\t\tlabel = new NodeLabel(types.get(0));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new IllegalArgumentException(\"A property index can only be used for Nodes or Relationships.\");\n\t\t\t}\n\n\t\t\tSymbolicName symbolicName = container.getRequiredSymbolicName();\n\n\t\t\tif (indexReference == null) {\n\t\t\t\tindexReference = new IndexReference(symbolicName, label);\n\t\t\t}\n\t\t\telse if (!indexReference.pointsToSameContainer(symbolicName, label)) {\n\t\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\t\"If you want to use more than one index on different nodes you must use multiple `USING INDEX` statements.\");\n\t\t\t}\n\t\t\tdeferencedProperties.add(property.getNames().get(0).getPropertyKeyName());\n\t\t}\n\n\t\treturn new Hint(seek ? Type.INDEX_SEEK : Type.INDEX, Collections.singletonList(indexReference),\n\t\t\t\tnew IndexProperties(deferencedProperties));\n\t}\n\n\t/**\n\t * Creates an index scan hint. Mostly useful when building elements outside the fluent\n\t * DSL.\n\t * @param node the node who's label and name should be used to define the scan hint\n\t * @return a hint\n\t * @since 2021.2.3\n\t */\n\tpublic static Hint useScanFor(Node node) {\n\n\t\tAssertions.notNull(node, \"Cannot apply a SCAN hint without a node.\");\n\t\tList<NodeLabel> labels = node.getLabels();\n\t\tAssertions.isTrue(labels.size() == 1, \"Exactly one label is required for a SCAN hint.\");\n\n\t\treturn new Hint(Type.SCAN,\n\t\t\t\tCollections.singletonList(new IndexReference(node.getRequiredSymbolicName(), labels.get(0))), null);\n\t}\n\n\t/**\n\t * Creates a join hint on one or more symbolic names.\n\t * @param name the names that are supposed to provide the join point\n\t * @return a hint\n\t * @since 2021.2.3\n\t */\n\tpublic static Hint useJoinOn(SymbolicName... name) {\n\n\t\tAssertions.notEmpty(name, \"At least one name is required to define a JOIN hint.\");\n\t\treturn new Hint(Type.JOIN_ON, Arrays.stream(name).map(IndexReference::new).toList(), null);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.type.accept(visitor);\n\t\tthis.indexReferences.accept(visitor);\n\t\tVisitable.visitIfNotNull(this.optionalProperties, visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\tprivate enum Type implements Visitable {\n\n\t\tINDEX, INDEX_SEEK, SCAN, JOIN_ON;\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn RendererBridge.render(this);\n\t\t}\n\n\t}\n\n\tprivate static final class IndexReference implements Visitable {\n\n\t\tprivate final SymbolicName symbolicName;\n\n\t\tprivate final NodeLabel optionalLabel;\n\n\t\tIndexReference(SymbolicName symbolicName) {\n\t\t\tthis(symbolicName, null);\n\t\t}\n\n\t\tIndexReference(SymbolicName symbolicName, NodeLabel optionalLabel) {\n\t\t\tthis.symbolicName = symbolicName;\n\t\t\tthis.optionalLabel = optionalLabel;\n\t\t}\n\n\t\tboolean pointsToSameContainer(SymbolicName otherSymbolicName, NodeLabel otherLabel) {\n\t\t\treturn this.symbolicName.equals(otherSymbolicName) && Objects.equals(this.optionalLabel, otherLabel);\n\t\t}\n\n\t\t@Override\n\t\tpublic void accept(Visitor visitor) {\n\n\t\t\tvisitor.enter(this);\n\t\t\tthis.symbolicName.accept(visitor);\n\t\t\tVisitable.visitIfNotNull(this.optionalLabel, visitor);\n\t\t\tvisitor.leave(this);\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn RendererBridge.render(this);\n\t\t}\n\n\t}\n\n\tprivate static final class IndexReferences extends TypedSubtree<IndexReference> {\n\n\t\tIndexReferences(List<IndexReference> indexReferences) {\n\t\t\tsuper(indexReferences);\n\t\t}\n\n\t}\n\n\t/**\n\t * Internal helper class to wrap up the properties used inside an index.\n\t */\n\tprivate static final class IndexProperties extends TypedSubtree<SymbolicName> implements ProvidesAffixes {\n\n\t\tIndexProperties(List<SymbolicName> properties) {\n\t\t\tsuper(properties);\n\t\t}\n\n\t\t@Override\n\t\tpublic Optional<String> getPrefix() {\n\t\t\treturn Optional.of(\"(\");\n\t\t}\n\n\t\t@Override\n\t\tpublic Optional<String> getSuffix() {\n\t\t\treturn Optional.of(\")\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/IdentifiableElement.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\n/**\n * This interface represents an element that can be for example an identifiable part of\n * the {@code WITH} clause. It has been introduced to circumvent the absence of union\n * types in Java and to avoid an overload of {@link StatementBuilder#with(String...)} or\n * other expressions with an {@code Object...} parameter. This type here allows passing\n * {@link Named named things}. {@link AliasedExpression aliased expression},\n * {@link SymbolicName symbolic names} into a pipeline.\n * <p>\n * There should be no need to implement this on your own.\n *\n * @author Michael J. Simons\n * @since 2021.2.2\n */\npublic sealed interface IdentifiableElement permits AliasedExpression, Asterisk, Named, Property, SymbolicName {\n\n\t/**\n\t * Transform this element into an expression.\n\t * @return this element as an expression. Will return the same instance if it is\n\t * already an expression.\n\t * @since 2021.2.2\n\t */\n\tExpression asExpression();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ImportingWith.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Arrays;\nimport java.util.Objects;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * This type is used in sub-queries, both for sub-queries with an implicit scope such as\n * {@literal EXISTS{}} and {@literal COUNT{}} and full sub-queries. In the latter case, it\n * will create and visite multiple {@link With with-instances} so that the import actually\n * shadows the outer scope.\n *\n * @author Michael J. Simons\n * @param imports the imported expressions\n * @param renames the renamed expressions, shadowing the outer scope\n * @since 2023.1.0\n */\n@API(status = INTERNAL, since = \"2023.1.0\")\nrecord ImportingWith(With imports, With renames) implements Visitable {\n\n\tImportingWith() {\n\t\tthis(null, null);\n\t}\n\n\tstatic ImportingWith of(IdentifiableElement... imports) {\n\n\t\tWith optionalImports;\n\t\tWith optionalRenames;\n\n\t\tExpressionList returnItems = new ExpressionList(Arrays.stream(imports).map(i -> {\n\t\t\tif (i instanceof AliasedExpression aliasedExpression) {\n\t\t\t\tvar delegate = aliasedExpression.getDelegate();\n\t\t\t\tif (delegate instanceof Literal<?>) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\treturn delegate;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn i.asExpression();\n\t\t\t}\n\t\t}).filter(Objects::nonNull).toList());\n\n\t\toptionalImports = returnItems.isEmpty() ? null : new With(false, returnItems, null, null, null, null);\n\n\t\treturnItems = new ExpressionList(Arrays.stream(imports)\n\t\t\t.filter(AliasedExpression.class::isInstance)\n\t\t\t.map(Expression.class::cast)\n\t\t\t.toList());\n\n\t\toptionalRenames = returnItems.isEmpty() ? null : new With(false, returnItems, null, null, null, null);\n\n\t\treturn new ImportingWith(optionalImports, optionalRenames);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tVisitable.visitIfNotNull(this.imports, visitor);\n\t\tVisitable.visitIfNotNull(this.renames, visitor);\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/InTransactions.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Used for subqueries {@code IN TRANSACTIONS}.\n *\n * @author Michael J. Simons\n * @since 2022.3.0\n */\n@API(status = STABLE, since = \"2022.3.0\")\npublic final class InTransactions implements Visitable {\n\n\tprivate final Subquery subquery;\n\n\tprivate final Integer rows;\n\n\t@API(status = INTERNAL)\n\tInTransactions(Subquery subquery, Integer rows) {\n\t\tthis.subquery = subquery;\n\t\tthis.rows = rows;\n\t}\n\n\t/**\n\t * {@return number of rows in this transaction}\n\t */\n\t@API(status = INTERNAL)\n\tpublic Integer getRows() {\n\t\treturn this.rows;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.subquery.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/InternalNodeImpl.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * An internal implementation of the {@link NodeBase}. It's primary purpose is to have\n * {@link NodeBase#named(SymbolicName)} and {@link NodeBase#withProperties(MapExpression)}\n * abstract method to enforce the correct return type. Otherwise one could extend\n * {@link NodeBase} without overriding those, ignoring unchecked casts and eventually\n * running into a {@link ClassCastException}.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\nfinal class InternalNodeImpl extends NodeBase<InternalNodeImpl> {\n\n\tInternalNodeImpl() {\n\t}\n\n\tInternalNodeImpl(Labels labelExpression, Where innerPredicate) {\n\t\tsuper(null, null, labelExpression, null, innerPredicate);\n\t}\n\n\tInternalNodeImpl(String primaryLabel, String... additionalLabels) {\n\t\tsuper(primaryLabel, additionalLabels);\n\t}\n\n\tInternalNodeImpl(SymbolicName symbolicName, List<NodeLabel> labels, Labels labelExpression, Properties properties,\n\t\t\tWhere innerPredicate) {\n\t\tsuper(symbolicName, labels, labelExpression, properties, innerPredicate);\n\t}\n\n\tInternalNodeImpl(SymbolicName symbolicName, String primaryLabel, MapExpression properties,\n\t\t\tString... additionalLabels) {\n\t\tsuper(symbolicName, primaryLabel, properties, additionalLabels);\n\t}\n\n\t@Override\n\tpublic InternalNodeImpl named(SymbolicName newSymbolicName) {\n\n\t\tAssertions.notNull(newSymbolicName, \"Symbolic name is required.\");\n\t\treturn new InternalNodeImpl(newSymbolicName, this.staticLabels, this.dynamicLabels, this.properties,\n\t\t\t\tthis.innerPredicate);\n\n\t}\n\n\t@Override\n\tpublic InternalNodeImpl withProperties(MapExpression newProperties) {\n\n\t\treturn new InternalNodeImpl(this.getSymbolicName().orElse(null), this.staticLabels, this.dynamicLabels,\n\t\t\t\tProperties.create(newProperties), this.innerPredicate);\n\t}\n\n\t@Override\n\tpublic Node where(Expression predicate) {\n\t\tif (predicate == null) {\n\t\t\treturn this;\n\t\t}\n\n\t\treturn new InternalNodeImpl(this.getSymbolicName().orElse(null), this.staticLabels, this.dynamicLabels,\n\t\t\t\tthis.properties, Where.from(predicate));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/InternalPropertyImpl.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.stream.Collectors;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * An internal implementation of a {@link Property}.\n *\n * @author Michael J. Simons\n * @since 2021.1.10\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\nfinal class InternalPropertyImpl implements Property {\n\n\t/**\n\t * The reference to the container itself is optional.\n\t */\n\tprivate final Named container;\n\n\t/**\n\t * The expression pointing to the {@link #container} above is not.\n\t */\n\tprivate final Expression containerReference;\n\n\t/**\n\t * The name of this property.\n\t */\n\tprivate final List<PropertyLookup> names;\n\n\t/**\n\t * An optional, external (as in external to the graph) reference.\n\t */\n\tprivate final String externalReference;\n\n\t@SuppressWarnings(\"OptionalUsedAsFieldOrParameterType\")\n\tInternalPropertyImpl(Optional<Named> container, Expression containerReference, List<PropertyLookup> names,\n\t\t\tString externalReference) {\n\n\t\tthis.container = container.orElse(null);\n\t\tthis.containerReference = containerReference;\n\t\tthis.names = names;\n\t\tthis.externalReference = externalReference;\n\t}\n\n\tstatic Property create(Named parentContainer, String... names) {\n\n\t\tSymbolicName requiredSymbolicName = extractRequiredSymbolicName(parentContainer);\n\t\treturn new InternalPropertyImpl(Optional.of(parentContainer), requiredSymbolicName,\n\t\t\t\tcreateListOfChainedNames(names), null);\n\t}\n\n\tstatic Property create(Expression containerReference, String... names) {\n\n\t\tAssertions.notNull(containerReference, \"The property container is required.\");\n\t\treturn new InternalPropertyImpl(Optional.empty(), containerReference, createListOfChainedNames(names), null);\n\t}\n\n\tstatic Property create(Named parentContainer, Expression lookup) {\n\n\t\tSymbolicName requiredSymbolicName = extractRequiredSymbolicName(parentContainer);\n\t\treturn new InternalPropertyImpl(Optional.of(parentContainer), requiredSymbolicName,\n\t\t\t\tCollections.singletonList(PropertyLookup.forExpression(lookup)), null);\n\t}\n\n\tstatic Property create(Expression containerReference, Expression lookup) {\n\n\t\treturn new InternalPropertyImpl(Optional.empty(), containerReference,\n\t\t\t\tCollections.singletonList(PropertyLookup.forExpression(lookup)), null);\n\t}\n\n\tprivate static List<PropertyLookup> createListOfChainedNames(String... names) {\n\n\t\tAssertions.notEmpty(names, \"The properties name is required.\");\n\n\t\tif (names.length == 1) {\n\t\t\treturn Collections.singletonList(PropertyLookup.forName(names[0]));\n\t\t}\n\t\telse {\n\t\t\treturn Arrays.stream(names)\n\t\t\t\t.map(PropertyLookup::forName)\n\t\t\t\t.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));\n\t\t}\n\t}\n\n\tprivate static SymbolicName extractRequiredSymbolicName(Named parentContainer) {\n\t\ttry {\n\t\t\treturn parentContainer.getRequiredSymbolicName();\n\t\t}\n\t\tcatch (IllegalStateException ex) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"A property derived from a node or a relationship needs a parent with a symbolic name.\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic List<PropertyLookup> getNames() {\n\t\treturn this.names;\n\t}\n\n\t@Override\n\tpublic Named getContainer() {\n\t\treturn this.container;\n\t}\n\n\t@Override\n\tpublic Expression getContainerReference() {\n\t\treturn this.containerReference;\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn (this.externalReference != null) ? this.externalReference\n\t\t\t\t: this.names.stream()\n\t\t\t\t\t.map(PropertyLookup::getPropertyKeyName)\n\t\t\t\t\t.map(SymbolicName::getValue)\n\t\t\t\t\t.collect(Collectors.joining(\".\"));\n\t}\n\n\t@Override\n\tpublic Property referencedAs(String newReference) {\n\n\t\treturn new InternalPropertyImpl(Optional.ofNullable(this.container), this.containerReference, this.names,\n\t\t\t\tnewReference);\n\t}\n\n\t@Override\n\tpublic Operation to(Expression expression) {\n\t\treturn Operations.set(this, expression);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.containerReference.accept(visitor);\n\t\tthis.names.forEach(name -> name.accept(visitor));\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic Expression asExpression() {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/InternalRelationshipImpl.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * An internal implementation of the {@link RelationshipBase}. It's primary purpose is to\n * have {@link RelationshipBase#named(SymbolicName)} and\n * {@link RelationshipBase#withProperties(MapExpression)} abstract method to enforce the\n * correct return type. Otherwise, one could extend {@link RelationshipBase} without\n * overriding those, ignoring unchecked casts and eventually running into a\n * {@link ClassCastException}.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\nfinal class InternalRelationshipImpl extends RelationshipBase<NodeBase<?>, NodeBase<?>, InternalRelationshipImpl> {\n\n\tInternalRelationshipImpl(SymbolicName symbolicName, Node left, Direction direction,\n\t\t\tQuantifiedPathPattern.Quantifier quantifier, Node right, String... types) {\n\t\tsuper(symbolicName, left, direction, quantifier, right, types);\n\t}\n\n\tInternalRelationshipImpl(SymbolicName symbolicName, Node left, Direction direction, Properties properties,\n\t\t\tQuantifiedPathPattern.Quantifier quantifier, Node right, String... types) {\n\t\tsuper(symbolicName, left, direction, properties, quantifier, right, types);\n\t}\n\n\tInternalRelationshipImpl(Node left, Details details, QuantifiedPathPattern.Quantifier quantifier, Node right) {\n\t\tsuper(left, details, quantifier, right);\n\t}\n\n\t@Override\n\tpublic InternalRelationshipImpl named(SymbolicName newSymbolicName) {\n\n\t\treturn new InternalRelationshipImpl(this.left, this.details.named(newSymbolicName), this.quantifier,\n\t\t\t\tthis.right);\n\t}\n\n\t@Override\n\tpublic InternalRelationshipImpl withProperties(MapExpression newProperties) {\n\n\t\treturn new InternalRelationshipImpl(this.left, this.details.with(Properties.create(newProperties)),\n\t\t\t\tthis.quantifier, this.right);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/KeyValueMapEntry.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Helper class, only for internal use.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class KeyValueMapEntry implements Expression {\n\n\tprivate final String key;\n\n\tprivate final Expression value;\n\n\tprivate KeyValueMapEntry(String key, Expression value) {\n\t\tthis.key = key;\n\t\tthis.value = value;\n\t}\n\n\t/**\n\t * Create a new {@link KeyValueMapEntry}. This is hardly useful in direct usage, but\n\t * might be handy to compose clauses outside the fluent api.\n\t * @param key the key of this entry\n\t * @param value the value of this entry\n\t * @return a new, immutable map entry.\n\t * @since 2021.2.3\n\t */\n\t@API(status = STABLE, since = \"2021.2.3\")\n\tpublic static KeyValueMapEntry create(String key, Expression value) {\n\n\t\tAssertions.notNull(key, \"Key is required.\");\n\t\tAssertions.notNull(value, \"Value is required.\");\n\n\t\treturn new KeyValueMapEntry(key, value);\n\t}\n\n\t/**\n\t * {@return the key of this entry}\n\t */\n\t@API(status = INTERNAL)\n\tpublic String getKey() {\n\t\treturn this.key;\n\t}\n\n\t/**\n\t * {@return the value of this entry}\n\t */\n\t@API(status = INTERNAL)\n\tpublic Expression getValue() {\n\t\treturn this.value;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.value.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/LabelExpression.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\n/**\n * This class is not used or supported anymore and will be removed in the next major\n * version of Cypher-DSL.\n *\n * @author Michael J. Simons\n * @param type whether this is a leaf or another node\n * @param negated a flag if this subtree is negated\n * @param value a single value or a list of value for {@link Type#COLON_DISJUNCTION} or\n * {@link Type#COLON_CONJUNCTION}\n * @param lhs the left hand site of this tree\n * @param rhs the right hand site of this tree\n * @since 2023.0.2\n * @deprecated Use {@link Labels} accessible via {@link Cypher#exactlyLabel(String)},\n * {@link Cypher#allLabels(Expression)} or {@link Cypher#anyLabel(Expression)}\n */\n@Deprecated(forRemoval = true)\npublic record LabelExpression(Type type, boolean negated, List<String> value, LabelExpression lhs,\n\t\tLabelExpression rhs) implements Visitable {\n\n\t/**\n\t * Creates an immutable label expression.\n\t * @param type whether this is a leaf or another node\n\t * @param negated a flag if this subtree is negated\n\t * @param value a single value or a list of value for {@link Type#COLON_DISJUNCTION}\n\t * or {@link Type#COLON_CONJUNCTION}\n\t * @param lhs the left hand site of this tree\n\t * @param rhs the right hand site of this tree\n\t */\n\tpublic LabelExpression {\n\t\tvalue = (value != null) ? List.copyOf(value) : null;\n\t}\n\n\t/**\n\t * Creates a leaf expression from a string.\n\t * @param value the leaf value\n\t */\n\tpublic LabelExpression(String value) {\n\t\tthis(Type.LEAF, false, List.of(value), null, null);\n\t}\n\n\t/**\n\t * Create a conjunction.\n\t * @param next the expression to add\n\t * @return a new expression\n\t */\n\tpublic LabelExpression and(LabelExpression next) {\n\t\treturn new LabelExpression(Type.CONJUNCTION, false, null, this, next);\n\t}\n\n\t/**\n\t * Create a disjunction.\n\t * @param next the expression to add\n\t * @return a new expression\n\t */\n\tpublic LabelExpression or(LabelExpression next) {\n\t\treturn new LabelExpression(Type.DISJUNCTION, false, null, this, next);\n\t}\n\n\t/**\n\t * Negates this expression.\n\t * @return a new expression\n\t */\n\tpublic LabelExpression negate() {\n\t\treturn new LabelExpression(this.type, !this.negated, this.value, this.lhs, this.rhs);\n\t}\n\n\t/**\n\t * Type of this expression.\n\t *\n\t * @deprecated No replacement, see {@link Labels} and its associated type\n\t */\n\t@Deprecated(forRemoval = true)\n\tpublic enum Type {\n\n\t\t/**\n\t\t * A leaf.\n\t\t */\n\t\tLEAF(\"\"),\n\t\t/**\n\t\t * A list of values, conjugated.\n\t\t */\n\t\tCOLON_CONJUNCTION(\":\"),\n\t\t/**\n\t\t * A list of values, disjoined.\n\t\t */\n\t\tCOLON_DISJUNCTION(\":\"),\n\t\t/**\n\t\t * A conjunction.\n\t\t */\n\t\tCONJUNCTION(\"&\"),\n\t\t/**\n\t\t * A disjunction.\n\t\t */\n\t\tDISJUNCTION(\"|\");\n\n\t\tprivate final String value;\n\n\t\tType(String value) {\n\t\t\tthis.value = value;\n\t\t}\n\n\t\t/**\n\t\t * {@return a representation of this type}\n\t\t */\n\t\tpublic String getValue() {\n\t\t\treturn this.value;\n\t\t}\n\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Labels.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.EnumSet;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Set;\n\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\n/**\n * Represents label expressions, that can be in some way combined and may contain dynamic\n * expressions as described <a href=\n * \"https://neo4j.com/docs/cypher-manual/current/clauses/match/#dynamic-match\">here</a>.\n * Labels are essentially modelled as tree, so that they can be properly rendered. <br/>\n * We are using the term Labels here in accordance with GQL, in which a Label is a quality\n * for both a node and a relationship element.\n *\n * @author Michael J. Simons\n * @since 2025.1.0\n */\npublic final class Labels implements Visitable {\n\n\t@SuppressWarnings(\"removal\")\n\t@Deprecated(forRemoval = true)\n\tstatic Labels of(LabelExpression labelExpression) {\n\t\tif (labelExpression == null) {\n\t\t\treturn null;\n\t\t}\n\t\tvar type = Type.valueOf(labelExpression.type().name());\n\t\tvar value = labelExpression.value();\n\t\tList<Value> adaptedValue = (value != null)\n\t\t\t\t? List.of(new Value(Modifier.STATIC, new TypedSubtree<>(value.stream().map(NodeLabel::new).toList()) {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic String separator() {\n\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t}\n\t\t\t\t})) : List.of();\n\t\treturn new Labels(type, labelExpression.negated(), adaptedValue, Labels.of(labelExpression.lhs()),\n\t\t\t\tLabels.of(labelExpression.rhs()));\n\t}\n\n\tstatic Labels exactly(String label) {\n\t\treturn new Labels(Modifier.STATIC, new NodeLabel(label));\n\t}\n\n\t/**\n\t * Returns a new dynamic label expression matching all labels.\n\t * @param expression the labels to match\n\t * @return a new dynamic label expression matching all labels\n\t */\n\tstatic Labels all(Expression expression) {\n\t\treturn new Labels(Modifier.ALL, expression);\n\t}\n\n\t/**\n\t * Returns a new dynamic label expression matching any labels.\n\t * @param expression the labels to match\n\t * @return a new dynamic label expression matching any labels\n\t */\n\tstatic Labels any(Expression expression) {\n\t\treturn new Labels(Modifier.ANY, expression);\n\t}\n\n\t/**\n\t * Creates a colon conjunction of all values.\n\t * @param values the values for the conjunction\n\t * @return a new labels expression\n\t */\n\tpublic static Labels colonConjunction(Collection<Value> values) {\n\t\treturn new Labels(Type.COLON_CONJUNCTION, false, (values != null) ? List.copyOf(values) : List.of(), null,\n\t\t\t\tnull);\n\t}\n\n\t/** Whether this is a leaf or another node. */\n\tprivate final Type type;\n\n\t/** A flag if this subtree is negated. */\n\tprivate final boolean negated;\n\n\t/** The actual value. */\n\tprivate final List<Value> value;\n\n\t/**\n\t * Optional left hand site of this tree.\n\t */\n\tprivate final Labels lhs;\n\n\t/**\n\t * Optional right hand site of this tree.\n\t */\n\tprivate final Labels rhs;\n\n\tLabels(Modifier modifier, Visitable labels) {\n\t\tthis(Type.LEAF, false, List.of(new Value(modifier, labels)), null, null);\n\t}\n\n\tLabels(Type type, boolean negated, List<Value> value, Labels lhs, Labels rhs) {\n\t\tthis.lhs = lhs;\n\t\tthis.type = type;\n\t\tthis.negated = negated;\n\t\tthis.value = value;\n\t\tthis.rhs = rhs;\n\t}\n\n\t/**\n\t * Create a conjunction.\n\t * @param next the expression to add\n\t * @return a new expression\n\t */\n\tpublic Labels and(Labels next) {\n\t\treturn new Labels(Type.CONJUNCTION, false, null, this, next);\n\t}\n\n\t/**\n\t * Create a disjunction.\n\t * @param next the expression to add\n\t * @return a new expression\n\t */\n\tpublic Labels or(Labels next) {\n\t\treturn new Labels(Type.DISJUNCTION, false, null, this, next);\n\t}\n\n\t/**\n\t * Negates this expression.\n\t * @return a new expression\n\t */\n\tpublic Labels negate() {\n\t\treturn new Labels(this.type, !this.negated, this.value, this.lhs, this.rhs);\n\t}\n\n\t/**\n\t * Creates a colon based conjunction.\n\t * @param other the other labels to create a conjunction with\n\t * @return a new labels expression\n\t */\n\tpublic Labels conjunctionWith(Labels other) {\n\t\treturn colonJunction(other, Type.COLON_CONJUNCTION);\n\t}\n\n\tpublic Labels disjunctionWith(Labels other) {\n\t\treturn colonJunction(other, Type.COLON_DISJUNCTION);\n\t}\n\n\tprivate Labels colonJunction(Labels other, Type colonDisjunction) {\n\t\tvar hlp = new ArrayList<Value>(this.value.size() + other.getValue().size());\n\t\thlp.addAll(this.value);\n\t\thlp.addAll(other.value);\n\t\treturn new Labels(colonDisjunction, false, List.copyOf(hlp), null, null);\n\t}\n\n\t/**\n\t * {@return the optional left hand side of this node}\n\t */\n\tpublic Labels getLhs() {\n\t\treturn this.lhs;\n\t}\n\n\t/**\n\t * {@return true if this is a negated expression}\n\t */\n\tpublic boolean isNegated() {\n\t\treturn this.negated;\n\t}\n\n\t/**\n\t * {@return the optional right hand side of this node}\n\t */\n\tpublic Labels getRhs() {\n\t\treturn this.rhs;\n\t}\n\n\tpublic Type getType() {\n\t\treturn this.type;\n\t}\n\n\tpublic List<Value> getValue() {\n\t\treturn this.value;\n\t}\n\n\t/**\n\t * {@return the list of all static labels}\n\t */\n\tpublic Collection<String> getStaticValues() {\n\n\t\tvar staticValues = new LinkedHashSet<String>();\n\t\tcollectLabels(this, staticValues);\n\t\treturn staticValues;\n\t}\n\n\tprivate static void collectLabels(Labels l, Set<String> labels) {\n\t\tif (l == null) {\n\t\t\treturn;\n\t\t}\n\t\tvar current = l.getType();\n\t\tcollectLabels(l.getLhs(), labels);\n\t\tif (current == Labels.Type.LEAF || (l.getLhs() == null && l.getRhs() == null\n\t\t\t\t&& EnumSet.of(Type.COLON_CONJUNCTION, Type.COLON_DISJUNCTION).contains(l.getType()))) {\n\t\t\tl.getValue().forEach(v -> v.accept(segment -> {\n\t\t\t\tif (segment instanceof NodeLabel label) {\n\t\t\t\t\tlabels.add(label.getValue());\n\t\t\t\t}\n\t\t\t}));\n\t\t}\n\t\tcollectLabels(l.getRhs(), labels);\n\t}\n\n\tboolean canBeUsedInUpdate() {\n\t\tvar b = this.lhs == null && this.rhs == null\n\t\t\t\t&& EnumSet.of(Type.LEAF, Type.COLON_CONJUNCTION).contains(this.type);\n\t\tif (b) {\n\t\t\tb = !this.value.isEmpty() && this.value.get(0).modifier == Modifier.ALL;\n\t\t}\n\t\treturn b;\n\t}\n\n\tpublic boolean isEmpty() {\n\t\treturn (this.value == null || this.value.isEmpty()) && (this.lhs == null || this.lhs.isEmpty())\n\t\t\t\t&& (this.rhs == null || this.rhs.isEmpty());\n\t}\n\n\t/**\n\t * An enum describing whether a {@link Labels} should match all or any labels the\n\t * expression resolves to.\n\t */\n\tpublic enum Modifier {\n\n\t\t/** Dynamically matching all labels. */\n\t\tALL,\n\t\t/** Dynamically matching any label. */\n\t\tANY,\n\t\t/** Static label expression. */\n\t\tSTATIC\n\n\t}\n\n\t/**\n\t * The content of this expression. Depending on the modifier, the expression can be\n\t * dynamically or statically matched. The actual {@code value} must resolve to an\n\t * expression that either is\n\t * <ul>\n\t * <li>A single string</li>\n\t * <li>A list of strings</li>\n\t * <li>A parameter holding either a single or a list of strings</li>\n\t * </ul>\n\t *\n\t * @param modifier modifier for the given content\n\t * @param visitable the actual value\n\t */\n\tpublic record Value(Modifier modifier, Visitable visitable) implements Visitable {\n\t\t@Override\n\t\tpublic void accept(Visitor visitor) {\n\t\t\tvisitor.enter(this);\n\t\t\tthis.visitable.accept(visitor);\n\t\t\tvisitor.leave(this);\n\t\t}\n\t}\n\n\t/**\n\t * Type of this expression.\n\t */\n\tpublic enum Type {\n\n\t\t/**\n\t\t * A leaf.\n\t\t */\n\t\tLEAF(\"\"),\n\t\t/**\n\t\t * A list of values, conjugated.\n\t\t */\n\t\tCOLON_CONJUNCTION(\":\"),\n\t\t/**\n\t\t * A list of values, disjoined.\n\t\t */\n\t\tCOLON_DISJUNCTION(\":\"),\n\t\t/**\n\t\t * A conjunction.\n\t\t */\n\t\tCONJUNCTION(\"&\"),\n\t\t/**\n\t\t * A disjunction.\n\t\t */\n\t\tDISJUNCTION(\"|\");\n\n\t\tprivate final String value;\n\n\t\tType(String value) {\n\t\t\tthis.value = value;\n\t\t}\n\n\t\t/**\n\t\t * {@return a representation of this type}\n\t\t */\n\t\tpublic String getValue() {\n\t\t\treturn this.value;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Limit.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Representation of the {@code LIMIT} clause.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Limit implements Visitable {\n\n\tprivate final Expression limitExpression;\n\n\tprivate Limit(Expression limitExpression) {\n\t\tthis.limitExpression = limitExpression;\n\t}\n\n\tstatic Limit create(Expression value) {\n\n\t\tAssertions.notNull(value, \"A limit cannot have a null value.\");\n\n\t\treturn new Limit(value);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.limitExpression.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ListComprehension.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Atom.html#ListComprehension\">ListComprehension</a>\n * and <a href=\n * \"https://neo4j.com/docs/cypher-manual/current/syntax/lists/#cypher-list-comprehension\">the\n * corresponding cypher manual entry</a>.\n *\n * @author Michael J. Simons\n * @since 1.0.1\n */\n@API(status = STABLE, since = \"1.0.1\")\npublic final class ListComprehension implements Expression {\n\n\t// Modelling from the FilterExpression:\n\t// https://s3.amazonaws.com/artifacts.opencypher.org/M14/railroad/FilterExpression.html\n\t// */\n\n\t/**\n\t * The variable for the where part.\n\t */\n\tprivate final SymbolicName variable;\n\n\t/**\n\t * The list expression. No further assertions are taken to check beforehand if it is\n\t * actually a Cypher List atm.\n\t */\n\tprivate final Expression listExpression;\n\n\t/**\n\t * Filtering on the list.\n\t */\n\tprivate final Where where;\n\n\t/**\n\t * The new list to be returned.\n\t */\n\tprivate final Expression listDefinition;\n\n\tprivate ListComprehension(SymbolicName variable, Expression listExpression, Where where,\n\t\t\tExpression listDefinition) {\n\t\tthis.variable = variable;\n\t\tthis.listExpression = listExpression;\n\t\tthis.where = where;\n\t\tthis.listDefinition = listDefinition;\n\t}\n\n\tstatic OngoingDefinitionWithVariable with(SymbolicName variable) {\n\n\t\tAssertions.notNull(variable, \"A variable is required\");\n\t\treturn new Builder(variable);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.variable.accept(visitor);\n\t\tOperator.IN.accept(visitor);\n\t\tthis.listExpression.accept(visitor);\n\t\tVisitable.visitIfNotNull(this.where, visitor);\n\t\tif (this.listDefinition != null) {\n\t\t\tOperator.PIPE.accept(visitor);\n\t\t\tthis.listDefinition.accept(visitor);\n\t\t}\n\t\tvisitor.leave(this);\n\t}\n\n\t/**\n\t * {@link #in(Expression)} must be used to define the source list.\n\t */\n\tpublic interface OngoingDefinitionWithVariable {\n\n\t\t/**\n\t\t * Create a list comprehension past on a literal list.\n\t\t * @param list the source list.\n\t\t * @return an ongoing definition\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingDefinitionWithList in(Expression list);\n\n\t}\n\n\t/**\n\t * Allows to add a where clause into the definition of the list.\n\t */\n\tpublic interface OngoingDefinitionWithList extends OngoingDefinitionWithoutReturn {\n\n\t\t/**\n\t\t * Adds a {@code WHERE} clause to this comprehension.\n\t\t * @param condition the condition to start the {@code WHERE} clause with.\n\t\t * @return an ongoing definition\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingDefinitionWithoutReturn where(Condition condition);\n\n\t}\n\n\t/**\n\t * Provides the final step of defining a list comprehension.\n\t */\n\tpublic interface OngoingDefinitionWithoutReturn {\n\n\t\t/**\n\t\t * Defines the {@code RETURN} clause.\n\t\t * @param variables the elements to be returned from the list\n\t\t * @return the final definition of the list comprehension\n\t\t * @see #returning(Expression...)\n\t\t */\n\t\tdefault ListComprehension returning(Named... variables) {\n\t\t\treturn returning(Expressions.createSymbolicNames(variables));\n\t\t}\n\n\t\t/**\n\t\t * Defines the {@code RETURN} clause.\n\t\t * @param listDefinition defines the elements to be returned from the pattern\n\t\t * @return the final definition of the list comprehension\n\t\t */\n\t\tListComprehension returning(Expression... listDefinition);\n\n\t\t/**\n\t\t * Defines an empty {@code RETURN} clause.\n\t\t * @return returns the list comprehension as is, without a {@literal WHERE} and\n\t\t * returning each element of the original list\n\t\t */\n\t\tListComprehension returning();\n\n\t}\n\n\tprivate static final class Builder implements OngoingDefinitionWithVariable, OngoingDefinitionWithList {\n\n\t\tprivate final SymbolicName variable;\n\n\t\tprivate Expression listExpression;\n\n\t\tprivate Where where;\n\n\t\tprivate Builder(SymbolicName variable) {\n\t\t\tthis.variable = variable;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingDefinitionWithList in(Expression list) {\n\t\t\tthis.listExpression = list;\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingDefinitionWithoutReturn where(Condition condition) {\n\t\t\tthis.where = new Where(condition);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic ListComprehension returning() {\n\n\t\t\treturn new ListComprehension(this.variable, this.listExpression, this.where, null);\n\t\t}\n\n\t\t@Override\n\t\tpublic ListComprehension returning(Expression... expressions) {\n\n\t\t\treturn new ListComprehension(this.variable, this.listExpression, this.where,\n\t\t\t\t\tListExpression.listOrSingleExpression(expressions));\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ListExpression.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Represents a list expression as in\n * {@code [expression1, expression2, ..., expressionN]}.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class ListExpression implements Expression {\n\n\tprivate final ExpressionList content;\n\n\tprivate ListExpression(ExpressionList content) {\n\t\tthis.content = content;\n\t}\n\n\tstatic Expression listOrSingleExpression(Expression... expressions) {\n\n\t\tAssertions.notNull(expressions, \"Expressions are required.\");\n\t\tAssertions.notEmpty(expressions, \"At least one expression is required.\");\n\n\t\tif (expressions.length == 1) {\n\t\t\treturn expressions[0];\n\t\t}\n\t\telse {\n\t\t\treturn ListExpression.create(expressions);\n\t\t}\n\t}\n\n\tstatic ListExpression create(Expression... expressions) {\n\n\t\treturn new ListExpression(new ExpressionList(expressions));\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.content.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ListLiteral.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.stream.Collectors;\nimport java.util.stream.StreamSupport;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A list of literals.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class ListLiteral extends LiteralBase<Iterable<Literal<?>>> {\n\n\tListLiteral(Iterable<Literal<?>> content) {\n\t\tsuper(content);\n\t}\n\n\t@Override\n\tpublic String asString() {\n\n\t\treturn StreamSupport.stream(this.content.spliterator(), false)\n\t\t\t.map(Literal::asString)\n\t\t\t.collect(Collectors.joining(\", \", \"[\", \"]\"));\n\t}\n\n\t@Override\n\tpublic Iterable<Literal<?>> getContent() {\n\t\treturn super.content;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ListOperator.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Optional;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.ProvidesAffixes;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Represents a range literal applied to another expression.\n *\n * @author Michael J. Simons\n * @since 2020.1.0\n */\n@API(status = API.Status.EXPERIMENTAL, since = \"2020.1.0\")\npublic final class ListOperator implements Expression, Visitable {\n\n\t/**\n\t * A literal for the dots.\n\t */\n\tstatic final Literal<String> DOTS = new LiteralBase<>(\"..\") {\n\t\t@Override\n\t\tpublic String asString() {\n\t\t\treturn this.content;\n\t\t}\n\t};\n\n\t/**\n\t * The target expression to which the literal should be applied.\n\t */\n\tprivate final Expression targetExpression;\n\n\t/**\n\t * The actual operator's details.\n\t */\n\tprivate final Details details;\n\n\tprivate ListOperator(Expression targetExpression, Expression optionalStart, Literal<String> dots,\n\t\t\tExpression optionalEnd) {\n\n\t\tthis.targetExpression = targetExpression;\n\t\tthis.details = new Details(optionalStart, dots, optionalEnd);\n\t}\n\n\t/**\n\t * Creates a closed range with given boundaries.\n\t * @param targetExpression the target expression for the range\n\t * @param start the inclusive start\n\t * @param end the exclusive end\n\t * @return a range literal.\n\t */\n\tstatic ListOperator subList(Expression targetExpression, Expression start, Expression end) {\n\n\t\tAssertions.notNull(targetExpression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RANGE_TARGET_REQUIRED));\n\t\tAssertions.notNull(start, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RANGE_START_REQUIRED));\n\t\tAssertions.notNull(end, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RANGE_END_REQUIRED));\n\n\t\treturn new ListOperator(targetExpression, start, DOTS, end);\n\t}\n\n\t/**\n\t * Creates an open range starting at {@code start}.\n\t * @param targetExpression the target expression for the range\n\t * @param start the inclusive start\n\t * @return a range literal.\n\t */\n\tstatic ListOperator subListFrom(Expression targetExpression, Expression start) {\n\n\t\tAssertions.notNull(targetExpression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RANGE_TARGET_REQUIRED));\n\t\tAssertions.notNull(start, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RANGE_START_REQUIRED));\n\n\t\treturn new ListOperator(targetExpression, start, DOTS, null);\n\t}\n\n\t/**\n\t * Creates an open range starting at {@code start}.\n\t * @param targetExpression the target expression for the range\n\t * @param end the exclusive end\n\t * @return a range literal.\n\t */\n\tstatic ListOperator subListUntil(Expression targetExpression, Expression end) {\n\n\t\tAssertions.notNull(targetExpression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RANGE_TARGET_REQUIRED));\n\t\tAssertions.notNull(end, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RANGE_END_REQUIRED));\n\n\t\treturn new ListOperator(targetExpression, null, DOTS, end);\n\t}\n\n\t/**\n\t * Creates a single valued range at {@code index}.\n\t * @param targetExpression the target expression for the range\n\t * @param index the index of the range\n\t * @return a range literal.\n\t */\n\tstatic ListOperator valueAt(Expression targetExpression, Expression index) {\n\n\t\tAssertions.notNull(targetExpression, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RANGE_TARGET_REQUIRED));\n\t\tAssertions.notNull(index, Cypher.MESSAGES.getString(MessageKeys.ASSERTIONS_RANGE_INDEX_REQUIRED));\n\n\t\treturn new ListOperator(targetExpression, index, null, null);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.targetExpression.accept(visitor);\n\t\tthis.details.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@API(status = INTERNAL, since = \"1.0\")\n\tstatic final class Details implements Visitable, ProvidesAffixes {\n\n\t\t/**\n\t\t * An optional start for the range (inclusive if given).\n\t\t */\n\t\tprivate final Expression optionalStart;\n\n\t\t/**\n\t\t * Optional dots between the start and end.\n\t\t */\n\t\tprivate final Literal<String> dots;\n\n\t\t/**\n\t\t * An optional end for the range (exclusive if given).\n\t\t */\n\t\tprivate final Expression optionalEnd;\n\n\t\tDetails(Expression optionalStart, Literal<String> dots, Expression optionalEnd) {\n\t\t\tthis.optionalStart = optionalStart;\n\t\t\tthis.dots = dots;\n\t\t\tthis.optionalEnd = optionalEnd;\n\t\t}\n\n\t\t@Override\n\t\tpublic void accept(Visitor visitor) {\n\n\t\t\tvisitor.enter(this);\n\t\t\tVisitable.visitIfNotNull(this.optionalStart, visitor);\n\t\t\tVisitable.visitIfNotNull(this.dots, visitor);\n\t\t\tVisitable.visitIfNotNull(this.optionalEnd, visitor);\n\t\t\tvisitor.leave(this);\n\t\t}\n\n\t\t@Override\n\t\tpublic Optional<String> getPrefix() {\n\t\t\treturn Optional.of(\"[\");\n\t\t}\n\n\t\t@Override\n\t\tpublic Optional<String> getSuffix() {\n\t\t\treturn Optional.of(\"]\");\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn RendererBridge.render(this);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ListPredicate.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * A list predicate.\n *\n * @author Michael J. Simons\n * @since 1.1 /\n */\n@API(status = INTERNAL, since = \"1.1\")\nfinal class ListPredicate implements Expression {\n\n\t/**\n\t * The variable for the where part.\n\t */\n\tprivate final SymbolicName variable;\n\n\t/**\n\t * The list expression. No further assertions are taken to check beforehand if it is\n\t * actually a Cypher List atm.\n\t */\n\tprivate final Expression listExpression;\n\n\t/**\n\t * Filtering on the list.\n\t */\n\tprivate final Where where;\n\n\tListPredicate(SymbolicName variable, Expression listExpression, Where where) {\n\n\t\tthis.variable = variable;\n\t\tthis.listExpression = listExpression;\n\t\tthis.where = where;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.variable.accept(visitor);\n\t\tOperator.IN.accept(visitor);\n\t\tthis.listExpression.accept(visitor);\n\t\tthis.where.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Literal.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Represents a literal with an optional content.\n *\n * @param <T> type of content\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface Literal<T> extends Expression {\n\n\t/**\n\t * The string representation should be designed in such a way the a renderer can use\n\t * it correctly in the given context of the literal, i.e. a literal containing a\n\t * string should quote that string and escape all reserved characters.\n\t * @return a string representation to be used literally in a cypher statement.\n\t */\n\tString asString();\n\n\t/**\n\t * Retrieves the actual content of this literal, might not be supported by all\n\t * literals.\n\t * @return the actual content of this literal\n\t * @since 2023.4.0\n\t */\n\tdefault T getContent() {\n\t\tthrow new UnsupportedOperationException(\"Retrieving content not supported\");\n\t}\n\n\t/**\n\t * Thrown when a given object cannot be used as a Cypher-DSL-Literal.\n\t *\n\t * @since 2021.1.0\n\t */\n\t@API(status = STABLE, since = \"2021.1.0\")\n\tfinal class UnsupportedLiteralException extends IllegalArgumentException {\n\n\t\tprivate static final long serialVersionUID = 864563506445498829L;\n\n\t\t/**\n\t\t * Value holding the unsupported type.\n\t\t */\n\t\tprivate final Class<?> unsupportedType;\n\n\t\tUnsupportedLiteralException(String message, Object unsupportedObject) {\n\t\t\tsuper(message);\n\t\t\tthis.unsupportedType = unsupportedObject.getClass();\n\t\t}\n\n\t\tUnsupportedLiteralException(Object unsupportedObject) {\n\t\t\tsuper(\"Unsupported literal type: \" + unsupportedObject.getClass());\n\t\t\tthis.unsupportedType = unsupportedObject.getClass();\n\t\t}\n\n\t\t/**\n\t\t * {@return the type that wasn't supported as literal}\n\t\t */\n\t\tpublic Class<?> getUnsupportedType() {\n\t\t\treturn this.unsupportedType;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/LiteralBase.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Objects;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Represents a literal with an optional content.\n *\n * @param <T> type of content\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\nabstract class LiteralBase<T> implements Literal<T> {\n\n\t/**\n\t * A literal for the blank.\n\t */\n\tstatic final Literal<String> BLANK = new LiteralBase<>(\" \") {\n\t\t@Override\n\t\tpublic String asString() {\n\t\t\treturn this.content;\n\t\t}\n\t};\n\n\t/**\n\t * The content of this literal.\n\t */\n\tprotected final T content;\n\n\t/**\n\t * Creates a new literal from the given content.\n\t * @param content the content of the new literal\n\t */\n\tprotected LiteralBase(T content) {\n\t\tthis.content = content;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (this == o) {\n\t\t\treturn true;\n\t\t}\n\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\treturn false;\n\t\t}\n\t\tLiteralBase<?> that = (LiteralBase<?>) o;\n\t\treturn this.content.equals(that.content);\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn Objects.hash(this.content);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/LoadCSVStatementBuilder.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.net.URI;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.DefaultLoadCSVStatementBuilder.PrepareLoadCSVStatementImpl;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A builder dedicated to the creation of the {@code LOAD CSV} statement.\n *\n * @author Michael J. Simons\n * @since 2021.2.1\n */\n@API(status = STABLE, since = \"2021.2.1\")\npublic interface LoadCSVStatementBuilder extends StatementBuilder {\n\n\t/**\n\t * Starts building a {@code LOAD CSV} clause by using a periodic commit.\n\t * @param rate the rate to be used. No checks are done on the rate, the database will\n\t * verify valid values.\n\t * @return an ongoing definition of a {@code LOAD CSV} clause\n\t */\n\tstatic ExposesLoadCSV usingPeriodicCommit(Integer rate) {\n\t\treturn new PrepareLoadCSVStatementImpl(rate);\n\t}\n\n\t/**\n\t * Starts building a {@code LOAD CSV}.\n\t * @param from the {@link URI} to load data from. Any uri that is resolvable by the\n\t * database itself is valid.\n\t * @param withHeaders set to {@literal true} if the csv file contains header\n\t * @return an ongoing definition of a {@code LOAD CSV} clause\n\t */\n\tstatic OngoingLoadCSV loadCSV(URI from, boolean withHeaders) {\n\t\treturn new PrepareLoadCSVStatementImpl(from, withHeaders);\n\t}\n\n\t/**\n\t * Configure a field terminator in case the fields aren't separated with the default\n\t * {@code ,}.\n\t * @param fieldTerminator a new field terminator\n\t * @return a statement builder supporting all available clauses\n\t */\n\tStatementBuilder withFieldTerminator(String fieldTerminator);\n\n\t/**\n\t * An instance of this interface will be provided after pointing the database to a\n\t * valid {@link URI} of a CSV resource.\n\t */\n\tinterface OngoingLoadCSV {\n\n\t\t/**\n\t\t * Configure the alias for each line contained in the CSV resource.\n\t\t * @param alias the alias for each line\n\t\t * @return a statement builder supporting all available clauses plus an option to\n\t\t * configure the field terminator\n\t\t */\n\t\tdefault LoadCSVStatementBuilder as(SymbolicName alias) {\n\t\t\treturn as(alias.getValue());\n\t\t}\n\n\t\t/**\n\t\t * Configure the alias for each line contained in the CSV resource.\n\t\t * @param alias the alias for each line\n\t\t * @return a statement builder supporting all available clauses plus an option to\n\t\t * configure the field terminator\n\t\t */\n\t\tLoadCSVStatementBuilder as(String alias);\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/MapExpression.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A dedicated map expression.\n * <p>\n * Most of the comparison methods on this expression will not result in a sensible query\n * fragment. A {@link MapExpression} is be useful as a concrete parameter to functions or\n * as properties on {@link Node nodes} or {@link Relationship relationships}.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class MapExpression extends TypedSubtree<Expression> implements Expression {\n\n\tprivate MapExpression(List<Expression> children) {\n\t\tsuper(children);\n\t}\n\n\tstatic MapExpression create(Map<String, Object> map) {\n\n\t\tObject[] args = new Object[map.size() * 2];\n\t\tint i = 0;\n\t\tfor (Map.Entry<String, Object> entry : map.entrySet()) {\n\t\t\tObject value = entry.getValue();\n\t\t\targs[i++] = entry.getKey();\n\t\t\targs[i++] = (value instanceof Expression) ? value : Cypher.literalOf(value);\n\t\t}\n\t\treturn create(false, args);\n\t}\n\n\tstatic MapExpression create(boolean sort, Object... input) {\n\n\t\tAssertions.isTrue(input.length % 2 == 0, \"Need an even number of input parameters\");\n\t\tList<Expression> newContent = new ArrayList<>(input.length / 2);\n\t\tSet<String> knownKeys = new HashSet<>();\n\n\t\tfor (int i = 0; i < input.length; i += 2) {\n\t\t\tObject keyCandidate = input[i];\n\t\t\tString key;\n\t\t\tif (keyCandidate instanceof String v) {\n\t\t\t\tkey = v;\n\t\t\t}\n\t\t\telse if (keyCandidate instanceof Property property) {\n\t\t\t\tList<PropertyLookup> names = property.getNames();\n\t\t\t\tif (names.size() != 1) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Nested properties are not supported in a map expression\");\n\t\t\t\t}\n\t\t\t\tkey = names.get(0).getPropertyKeyName().getValue();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new IllegalStateException(\"Key needs to be of type String or Property.\");\n\t\t\t}\n\t\t\tAssertions.isInstanceOf(Expression.class, input[i + 1], \"Value needs to be of type Expression.\");\n\t\t\tAssertions.isTrue(!knownKeys.contains(input[i]), \"Duplicate key '\" + input[i] + \"'\");\n\n\t\t\tfinal KeyValueMapEntry entry = KeyValueMapEntry.create(key, (Expression) input[i + 1]);\n\t\t\tnewContent.add(entry);\n\t\t\tknownKeys.add(entry.getKey());\n\t\t}\n\n\t\tif (sort) {\n\t\t\tnewContent.sort(Comparator.comparing(o -> ((KeyValueMapEntry) o).getKey()));\n\t\t}\n\t\treturn new MapExpression(newContent);\n\t}\n\n\tstatic MapExpression withEntries(List<Expression> entries) {\n\t\treturn new MapExpression(entries);\n\t}\n\n\tMapExpression addEntries(List<Expression> entries) {\n\t\tList<Expression> newContent = new ArrayList<>(super.children.size() + entries.size());\n\t\tnewContent.addAll(super.children);\n\t\tnewContent.addAll(entries);\n\t\treturn new MapExpression(newContent);\n\t}\n\n\t@Override\n\tprotected Visitable prepareVisit(Expression child) {\n\t\treturn Expressions.nameOrExpression(child);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/MapLiteral.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A map of literals.\n *\n * @author Aaron Hiniker\n * @since 2023.2.0\n */\n@API(status = STABLE, since = \"2023.2.0\")\npublic final class MapLiteral extends LiteralBase<Map<String, Literal<?>>> {\n\n\tMapLiteral(Map<String, Literal<?>> content) {\n\t\tsuper(content);\n\t}\n\n\t@Override\n\tpublic String asString() {\n\t\treturn this.content.entrySet()\n\t\t\t.stream()\n\t\t\t.map(entry -> entry.getKey() + \": \" + entry.getValue().asString())\n\t\t\t.collect(Collectors.joining(\", \", \"{\", \"}\"));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/MapProjection.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Represents a map projection as described <a href=\n * \"https://medium.com/neo4j/loading-graph-data-for-an-object-graph-mapper-or-graphql-5103b1a8b66e\">here</a>.\n *\n * @author Michael J. Simons\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class MapProjection implements Expression {\n\n\tprivate final SymbolicName name;\n\n\tprivate final MapExpression map;\n\n\tMapProjection(SymbolicName name, MapExpression map) {\n\t\tthis.name = name;\n\t\tthis.map = map;\n\t}\n\n\t/**\n\t * Create a new map projection with the given, mixed content.\n\t * @param name the symbolic name of this project\n\t * @param content the projected content\n\t * @return a new map projection\n\t * @since 2021.2.3\n\t */\n\t@API(status = INTERNAL, since = \"2023.9.0\")\n\tpublic static MapProjection create(SymbolicName name, Object... content) {\n\n\t\treturn new MapProjection(name, MapExpression.withEntries(createNewContent(false, content)));\n\t}\n\n\t/**\n\t * Create a new map projection with the given, mixed content.\n\t * @param name the symbolic name of this project\n\t * @param content the projected content\n\t * @return a new map projection\n\t * @since 2024.1.1\n\t */\n\t@API(status = INTERNAL, since = \"2024.1.1\")\n\tpublic static MapProjection sorted(SymbolicName name, Object... content) {\n\n\t\treturn new MapProjection(name, MapExpression.withEntries(createNewContent(true, content)));\n\t}\n\n\tprivate static Object contentAt(Object[] content, int i) {\n\n\t\tObject currentObject = content[i];\n\t\tif (currentObject instanceof Expression expression) {\n\t\t\treturn Expressions.nameOrExpression(expression);\n\t\t}\n\t\telse if (currentObject instanceof Named named) {\n\t\t\treturn named.getSymbolicName().map(Object.class::cast).orElse(currentObject);\n\t\t}\n\t\treturn currentObject;\n\t}\n\n\tprivate static List<Expression> createNewContent(boolean sort, Object... content) {\n\t\tfinal List<Expression> newContent = new ArrayList<>(content.length);\n\t\tfinal Set<String> knownKeys = new HashSet<>();\n\n\t\tString lastKey = null;\n\t\tExpression lastExpression = null;\n\t\tint i = 0;\n\t\twhile (i < content.length) {\n\n\t\t\tObject next;\n\t\t\tif (i + 1 >= content.length) {\n\t\t\t\tnext = null;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tnext = contentAt(content, i + 1);\n\t\t\t}\n\t\t\tObject current = contentAt(content, i);\n\n\t\t\tif (current instanceof String stringValue) {\n\t\t\t\tif (next instanceof Expression expression) {\n\t\t\t\t\tlastKey = stringValue;\n\t\t\t\t\tlastExpression = expression;\n\t\t\t\t\ti += 2;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tlastExpression = PropertyLookup.forName((String) current);\n\t\t\t\t\ti += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (current instanceof Expression expression) {\n\t\t\t\tlastExpression = expression;\n\t\t\t\ti += 1;\n\t\t\t}\n\t\t\tif (lastExpression instanceof Asterisk) {\n\t\t\t\tlastExpression = PropertyLookup.wildcard();\n\t\t\t}\n\n\t\t\tif (lastKey != null) {\n\t\t\t\tAssertions.isTrue(!knownKeys.contains(lastKey), \"Duplicate key '\" + lastKey + \"'\");\n\t\t\t\tnewContent.add(KeyValueMapEntry.create(lastKey, lastExpression));\n\t\t\t\tknownKeys.add(lastKey);\n\t\t\t}\n\t\t\telse if (lastExpression instanceof SymbolicName || lastExpression instanceof PropertyLookup) {\n\t\t\t\tnewContent.add(lastExpression);\n\t\t\t}\n\t\t\telse if (lastExpression instanceof Property property) {\n\t\t\t\tList<PropertyLookup> names = property.getNames();\n\t\t\t\tif (names.size() > 1) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Cannot project nested properties!\");\n\t\t\t\t}\n\t\t\t\tnewContent.addAll(names);\n\t\t\t}\n\t\t\telse if (lastExpression instanceof AliasedExpression aliasedExpression) {\n\t\t\t\tnewContent.add(KeyValueMapEntry.create(aliasedExpression.getAlias(), aliasedExpression));\n\t\t\t}\n\t\t\telse if (lastExpression instanceof KeyValueMapEntry) {\n\t\t\t\tnewContent.add(lastExpression);\n\t\t\t}\n\t\t\telse if (lastExpression == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"Could not determine an expression from the given content!\");\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new IllegalArgumentException(lastExpression + \" of type \" + lastExpression.getClass()\n\t\t\t\t\t\t+ \" cannot be used with an implicit name as map entry.\");\n\t\t\t}\n\n\t\t\tlastKey = null;\n\t\t\tlastExpression = null;\n\t\t}\n\n\t\tif (sort) {\n\t\t\tnewContent.sort((o1, o2) -> {\n\t\t\t\tif (o1 instanceof KeyValueMapEntry kvm1 && o2 instanceof KeyValueMapEntry kvm2) {\n\t\t\t\t\treturn kvm1.getKey().compareTo(kvm2.getKey());\n\t\t\t\t}\n\t\t\t\telse if (o1 instanceof PropertyLookup pl1 && o2 instanceof PropertyLookup pl2) {\n\t\t\t\t\tif (pl1 == PropertyLookup.wildcard()) {\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t}\n\t\t\t\t\telse if (pl2 == PropertyLookup.wildcard()) {\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn pl1.getPropertyKeyName().getValue().compareTo(pl2.getPropertyKeyName().getValue());\n\t\t\t\t}\n\t\t\t\telse if (o1 instanceof PropertyLookup) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\treturn -1;\n\t\t\t});\n\t\t}\n\n\t\treturn newContent;\n\t}\n\n\t/**\n\t * Adds additional content. The current projection is left unchanged and a new one is\n\t * returned.\n\t * @param content the additional content for a new projection.\n\t * @return a new map projection with additional content.\n\t */\n\tpublic MapProjection and(Object... content) {\n\t\treturn new MapProjection(this.name, this.map.addEntries(createNewContent(false, content)));\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.name.accept(visitor);\n\t\tthis.map.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Match.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Match.html\">Match</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Match extends AbstractClause implements ReadingClause {\n\n\tfinal Pattern pattern;\n\n\tprivate final boolean optional;\n\n\t/**\n\t * A Neo4j extension to the match clause that allows to specify hints via the\n\t * {@code USING} clause.\n\t */\n\tprivate final List<Hint> hints;\n\n\tprivate final Where optionalWhere;\n\n\tMatch(boolean optional, Pattern pattern, Where optionalWhere, List<Hint> optionalHints) {\n\t\tthis.optional = optional;\n\t\tthis.pattern = pattern;\n\t\tthis.optionalWhere = optionalWhere;\n\t\tthis.hints = (optionalHints != null) ? new ArrayList<>(optionalHints) : Collections.emptyList();\n\t}\n\n\t/**\n\t * {@return true if this is an optional match}\n\t */\n\t@API(status = INTERNAL)\n\tpublic boolean isOptional() {\n\t\treturn this.optional;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.pattern.accept(visitor);\n\t\tthis.hints.forEach(value -> value.accept(visitor));\n\t\tVisitable.visitIfNotNull(this.optionalWhere, visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Merge.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Create.html\">Create</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Merge extends AbstractClause implements UpdatingClause {\n\n\tprivate final Pattern pattern;\n\n\tprivate final List<Visitable> onCreateOrMatchEvents;\n\n\tMerge(Pattern pattern, List<MergeAction> mergeActions) {\n\t\tthis.pattern = pattern;\n\n\t\tthis.onCreateOrMatchEvents = new ArrayList<>();\n\t\tthis.onCreateOrMatchEvents.add(LiteralBase.BLANK);\n\t\tthis.onCreateOrMatchEvents.addAll(mergeActions);\n\t}\n\n\t/**\n\t * {@return true if there are any events defined for the merge statement}\n\t */\n\t@API(status = INTERNAL)\n\tpublic boolean hasEvents() {\n\t\treturn !this.onCreateOrMatchEvents.isEmpty();\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.pattern.accept(visitor);\n\t\tthis.onCreateOrMatchEvents.forEach(s -> s.accept(visitor));\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/MergeAction.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * An action or event that happens after a {@code MERGE} clause. It can either be one of\n * two types: {@link Type#ON_CREATE} or {@link Type#ON_MATCH}.\n *\n * <p>\n * Both events support the setting of properties, but not removing or adding labels.\n * Multiple properties should be set in one action, but Cypher and <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Merge.html\">openCypher</a>\n * allow for multiple {@link MergeAction merge actions}, with the same or different types.\n *\n * @author Michael J. Simons\n * @since 2020.1.2\n */\n@API(status = STABLE, since = \"2020.1.2\")\npublic final class MergeAction implements Visitable {\n\n\tprivate final Type type;\n\n\tprivate final UpdatingClause set;\n\n\tprivate MergeAction(Type type, UpdatingClause set) {\n\t\tthis.type = type;\n\t\tthis.set = set;\n\t}\n\n\t/**\n\t * Creates a new merge action. Mostly useful when building the AST outside the fluent\n\t * DSL.\n\t * @param type the type of the action\n\t * @param set the corresponding updating clause\n\t * @return an immutable action\n\t * @since 2021.3.0\n\t */\n\tpublic static MergeAction of(Type type, Set set) {\n\t\treturn new MergeAction(type, set);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n\t/**\n\t * {@return event type of this action}\n\t */\n\t@API(status = INTERNAL)\n\tpublic Type getType() {\n\t\treturn this.type;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.set.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t/**\n\t * The type of the action.\n\t */\n\tpublic enum Type {\n\n\t\t/**\n\t\t * Triggered when a pattern has been created.\n\t\t */\n\t\tON_CREATE,\n\t\t/**\n\t\t * Triggered when a pattern has been fully matched.\n\t\t */\n\t\tON_MATCH\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/MessageKeys.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\n/**\n * The message keys available in the {@code messages}-bundle.\n *\n * @author Michael J. Simons\n */\nfinal class MessageKeys {\n\n\tstatic final String ASSERTIONS_EXPRESSION_REQUIRED = \"assertions.expression-required\";\n\n\tstatic final String ASSERTIONS_EXPRESSIONS_REQUIRED = \"assertions.expressions-required\";\n\n\tstatic final String ASSERTIONS_AT_LEAST_ONE_EXPRESSION_REQUIRED = \"assertions.at-least-one-expression-required\";\n\n\tstatic final String ASSERTIONS_NODE_REQUIRED = \"assertions.node-required\";\n\n\tstatic final String ASSERTIONS_RELATIONSHIP_REQUIRED = \"assertions.relationship-required\";\n\n\tstatic final String ASSERTIONS_VARIABLE_REQUIRED = \"assertions.variable-required\";\n\n\tstatic final String ASSERTIONS_COMPONENTS_REQUIRED = \"assertions.components-required\";\n\n\tstatic final String ASSERTIONS_TEMPORAL_VALUE_REQUIRED = \"assertions.temporal-value-required\";\n\n\tstatic final String ASSERTIONS_YEAR_REQUIRED = \"assertions.year-required\";\n\n\tstatic final String ASSERTIONS_MONTH_REQUIRED = \"assertions.month-required\";\n\n\tstatic final String ASSERTIONS_DAY_REQUIRED = \"assertions.day-required\";\n\n\tstatic final String ASSERTIONS_TZ_REQUIRED = \"assertions.tz-required\";\n\n\tstatic final String ASSERTIONS_RANGE_TARGET_REQUIRED = \"assertions.range-target-required\";\n\n\tstatic final String ASSERTIONS_RANGE_INDEX_REQUIRED = \"assertions.range-index-required\";\n\n\tstatic final String ASSERTIONS_RANGE_START_REQUIRED = \"assertions.range-start-required\";\n\n\tstatic final String ASSERTIONS_RANGE_END_REQUIRED = \"assertions.range-end-required\";\n\n\tstatic final String ASSERTIONS_EXPRESSION_FOR_FUNCTION_REQUIRED = \"assertions.expression-for-function-required\";\n\n\tstatic final String ASSERTIONS_PATTERN_FOR_FUNCTION_REQUIRED = \"assertions.pattern-for-function-required\";\n\n\tstatic final String ASSERTIONS_AT_LEAST_ONE_ARG_REQUIRED = \"assertions.at-least-one-arg-required\";\n\n\tstatic final String ASSERTIONS_CORRECT_USAGE_OF_DISTINCT = \"assertions.correct-usage-of-distinct\";\n\n\tstatic final String ASSERTIONS_NAMED_PATH_REQUIRED = \"assertions.named-path-required\";\n\n\tstatic final String ASSERTIONS_REQUIRES_NAME_FOR_MUTATION = \"assertions.requires-name-for-mutation\";\n\n\tprivate MessageKeys() {\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/MultiPartElement.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\n/**\n * Connects several visitables into one element.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\nclass MultiPartElement implements Visitable {\n\n\tprivate final List<Visitable> precedingClauses;\n\n\tprivate final With with;\n\n\tMultiPartElement(List<Visitable> precedingClauses, With with) {\n\n\t\tif (precedingClauses == null || precedingClauses.isEmpty()) {\n\t\t\tthis.precedingClauses = Collections.emptyList();\n\t\t}\n\t\telse {\n\t\t\tthis.precedingClauses = new ArrayList<>(precedingClauses);\n\t\t}\n\n\t\tthis.with = with;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.precedingClauses.forEach(c -> c.accept(visitor));\n\t\tthis.with.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n\tboolean isImporting() {\n\t\treturn this.precedingClauses.isEmpty() && !this.with.getItems().isEmpty()\n\t\t\t\t&& this.with.getItems().stream().allMatch(IdentifiableElement.class::isInstance);\n\t}\n\n\tIdentifiableElement[] getImports() {\n\t\treturn this.with.getItems().stream().map(IdentifiableElement.class::cast).toArray(IdentifiableElement[]::new);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/MultiPartQuery.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/MultiPartQuery.html\">MultiPartQuery</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = INTERNAL, since = \"1.0\")\nclass MultiPartQuery extends AbstractStatement implements Statement.SingleQuery {\n\n\tprivate final List<MultiPartElement> parts;\n\n\tprivate final SinglePartQuery remainder;\n\n\tprivate MultiPartQuery(List<MultiPartElement> parts, SinglePartQuery remainder) {\n\n\t\tthis.parts = new ArrayList<>(parts);\n\t\tthis.remainder = remainder;\n\t}\n\n\tstatic MultiPartQuery create(List<MultiPartElement> parts, SinglePartQuery remainder) {\n\n\t\tif (remainder instanceof ResultStatement) {\n\t\t\treturn new MultiPartQueryWithResult(parts, remainder);\n\t\t}\n\t\telse {\n\t\t\treturn new MultiPartQuery(parts, remainder);\n\t\t}\n\t}\n\n\tList<MultiPartElement> getParts() {\n\t\treturn this.parts;\n\t}\n\n\tStatement stripFirst() {\n\t\treturn new MultiPartQuery((this.parts.size() > 1) ? this.parts.subList(1, this.parts.size()) : List.of(),\n\t\t\t\tthis.remainder);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tthis.parts.forEach(p -> p.accept(visitor));\n\t\tthis.remainder.accept(visitor);\n\t}\n\n\tstatic final class MultiPartQueryWithResult extends MultiPartQuery implements ResultStatement {\n\n\t\tprivate MultiPartQueryWithResult(List<MultiPartElement> parts, SinglePartQuery remainder) {\n\t\t\tsuper(parts, remainder);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Named.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Optional;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A named thing exposes {@link #getSymbolicName()}, making the thing identifiable.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic non-sealed interface Named extends IdentifiableElement {\n\n\t/**\n\t * {@return an optional symbolic name}\n\t */\n\tOptional<SymbolicName> getSymbolicName();\n\n\t/**\n\t * Return a symbolic name.\n\t * @return a symbolic name\n\t * @throws IllegalStateException if this has not been named yet.\n\t */\n\tdefault SymbolicName getRequiredSymbolicName() {\n\t\treturn getSymbolicName().orElseThrow(() -> new IllegalStateException(\"No name present.\"));\n\t}\n\n\t@Override\n\tdefault Expression asExpression() {\n\t\treturn getRequiredSymbolicName();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/NamedPath.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Optional;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.FunctionInvocation.FunctionDefinition;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Represents a named path. A named path can be either a {@link RelationshipPattern} that\n * has been assigned to a variable as in {@code p := (a)-->(b)}, a call to functions known\n * to return paths or an existing, symbolic name that might come from an arbitrary\n * procedure returning path elements. <br>\n * <b>Note</b>: We cannot check a value that has been yielded from a procedure upfront to\n * verify that it is a named path. This is up to the caller.\n *\n * @author Michael J. Simons\n * @since 1.1\n */\n@API(status = STABLE, since = \"1.1\")\npublic final class NamedPath implements PatternElement, Named {\n\n\t/**\n\t * The name of this path expression.\n\t */\n\tprivate final SymbolicName name;\n\n\t/**\n\t * An optional {@code SHORTEST} keyword element.\n\t */\n\tprivate final PatternSelector optionalPatternSelector;\n\n\t/**\n\t * The pattern defining this path.\n\t */\n\tprivate final Visitable optionalPattern;\n\n\tprivate NamedPath(SymbolicName name) {\n\t\tthis.name = name;\n\t\tthis.optionalPatternSelector = null;\n\t\tthis.optionalPattern = null;\n\t}\n\n\tprivate NamedPath(SymbolicName name, PatternSelector optionalPatternSelector, PatternElement optionalPattern) {\n\t\tthis.name = name;\n\t\tthis.optionalPatternSelector = optionalPatternSelector;\n\t\tthis.optionalPattern = optionalPattern;\n\t}\n\n\tprivate NamedPath(SymbolicName name, FunctionInvocation algorithm) {\n\t\tthis.name = name;\n\t\tthis.optionalPatternSelector = null;\n\t\tthis.optionalPattern = algorithm;\n\t}\n\n\tstatic OngoingDefinitionWithName named(String name) {\n\n\t\treturn named(SymbolicName.of(name));\n\t}\n\n\tstatic OngoingDefinitionWithName named(SymbolicName name) {\n\n\t\tAssertions.notNull(name, \"A name is required\");\n\t\treturn new Builder(name);\n\t}\n\n\tstatic OngoingShortestPathDefinitionWithName named(String name, FunctionDefinition algorithm) {\n\n\t\treturn new ShortestPathBuilder(SymbolicName.of(name), algorithm);\n\t}\n\n\tstatic OngoingShortestPathDefinitionWithName named(SymbolicName name, FunctionDefinition algorithm) {\n\n\t\tAssertions.notNull(name, \"A name is required\");\n\t\treturn new ShortestPathBuilder(name, algorithm);\n\t}\n\n\tstatic OngoingShortestDefinition shortest(int k) {\n\t\treturn new ShortestBuilder(PatternSelector.shortestK(k));\n\t}\n\n\tstatic OngoingShortestDefinition allShortest() {\n\t\treturn new ShortestBuilder(PatternSelector.allShortest());\n\t}\n\n\tstatic OngoingShortestDefinition shortestKGroups(int k) {\n\t\treturn new ShortestBuilder(PatternSelector.shortestKGroups(k));\n\t}\n\n\tstatic OngoingShortestDefinition any() {\n\t\treturn new ShortestBuilder(PatternSelector.any());\n\t}\n\n\t@API(status = INTERNAL, since = \"2024.7.0\")\n\tpublic static NamedPath select(PatternSelector patternSelector, PatternElement patternElement) {\n\t\tif (patternElement instanceof NamedPath namedPath\n\t\t\t\t&& namedPath.optionalPattern instanceof PatternElement target) {\n\t\t\treturn new NamedPath(namedPath.name, patternSelector, target);\n\t\t}\n\t\treturn new NamedPath(SymbolicName.unresolved(), patternSelector, patternElement);\n\t}\n\n\t@Override\n\tpublic Optional<SymbolicName> getSymbolicName() {\n\t\treturn Optional.of(this.name);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.name.accept(visitor);\n\t\tif (this.optionalPattern != null) {\n\t\t\tOperator.ASSIGMENT.accept(visitor);\n\t\t\tif (this.optionalPatternSelector != null) {\n\t\t\t\tvisitor.enter(this.optionalPatternSelector);\n\t\t\t}\n\t\t\tthis.optionalPattern.accept(visitor);\n\t\t\tif (this.optionalPatternSelector != null) {\n\t\t\t\tvisitor.leave(this.optionalPatternSelector);\n\t\t\t}\n\t\t}\n\t\tvisitor.leave(this);\n\t}\n\n\t/**\n\t * Partial path that has a name, introduced as a superinterface for\n\t * {@link OngoingDefinitionWithName} to avoid dragging\n\t * {@link OngoingDefinitionWithName#get()}.\n\t */\n\tpublic interface OngoingNamedDefinition {\n\n\t\t/**\n\t\t * Create a new named path based on a {@link PatternElement}.\n\t\t * @param pattern the pattern to be matched for the named path.\n\t\t * @return a named path.\n\t\t */\n\t\tNamedPath definedBy(PatternElement pattern);\n\n\t}\n\n\t/**\n\t * Partial path that has a name ({@code p = }).\n\t */\n\tpublic interface OngoingDefinitionWithName extends OngoingNamedDefinition {\n\n\t\t/**\n\t\t * Create a new named path that references a given, symbolic name. No checks are\n\t\t * done if the referenced name actually points to a path.\n\t\t * @return a named path.\n\t\t * @since 2020.1.4\n\t\t */\n\t\tNamedPath get();\n\n\t}\n\n\t/**\n\t * Partial path that has a name ({@code p = }) and is based on a graph algorithm\n\t * function.\n\t */\n\tpublic interface OngoingShortestPathDefinitionWithName {\n\n\t\t/**\n\t\t * Create a new named path based on a single relationship.\n\t\t * @param relationship the relationship to be passed to {@code shortestPath}.\n\t\t * @return a named path.\n\t\t */\n\t\tNamedPath definedBy(Relationship relationship);\n\n\t}\n\n\t/**\n\t * Partial path with the number of paths to match.\n\t */\n\tpublic interface OngoingShortestDefinition {\n\n\t\tdefault OngoingNamedDefinition named(String name) {\n\t\t\treturn named(Cypher.name(name));\n\t\t}\n\n\t\tOngoingNamedDefinition named(SymbolicName name);\n\n\t}\n\n\tprivate record Builder(SymbolicName name) implements OngoingDefinitionWithName {\n\n\t\t@Override\n\t\tpublic NamedPath definedBy(PatternElement pattern) {\n\t\t\tif (pattern instanceof NamedPath namedPath) {\n\t\t\t\treturn namedPath;\n\t\t\t}\n\t\t\treturn new NamedPath(this.name, null, pattern);\n\t\t}\n\n\t\t@Override\n\t\tpublic NamedPath get() {\n\t\t\treturn new NamedPath(this.name);\n\t\t}\n\t}\n\n\tprivate record ShortestPathBuilder(SymbolicName name,\n\t\t\tFunctionDefinition algorithm) implements OngoingShortestPathDefinitionWithName {\n\n\t\t@Override\n\t\tpublic NamedPath definedBy(Relationship relationship) {\n\t\t\treturn new NamedPath(this.name, FunctionInvocation.create(this.algorithm, relationship));\n\t\t}\n\t}\n\n\tprivate static final class ShortestBuilder implements OngoingShortestDefinition, OngoingNamedDefinition {\n\n\t\tprivate final PatternSelector shortest;\n\n\t\tprivate SymbolicName name;\n\n\t\tprivate ShortestBuilder(PatternSelector shortest) {\n\t\t\tthis.shortest = shortest;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingNamedDefinition named(SymbolicName newName) {\n\t\t\tthis.name = newName;\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic NamedPath definedBy(PatternElement pattern) {\n\t\t\treturn new NamedPath(this.name, this.shortest, pattern);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Neo4jVersion.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * This annotation provides information which Neo4j version is required to be able to\n * successfully run a query containing a fragment generated via a method annotated with\n * it.\n *\n * @author Michael J. Simons\n * @since 2020.1.2\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ ElementType.METHOD, ElementType.TYPE })\n@Documented\n@API(status = STABLE, since = \"2020.1.2\")\npublic @interface Neo4jVersion {\n\n\t/**\n\t * {@return the minimum version of Neo4j required to run the annotated construct}\n\t */\n\tString minimum();\n\n\t/**\n\t * {@return the last version of Neo4j that supports running the annotated construct}\n\t */\n\tString last() default \"\";\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/NestedExpression.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A nested expression.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class NestedExpression implements Expression {\n\n\tprivate final Expression delegate;\n\n\tNestedExpression(Expression delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tExpressions.nameOrExpression(this.delegate).accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Node.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/NodePattern.html\">NodePattern</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface Node\n\t\textends PatternElement, PropertyContainer, ExposesProperties<Node>, ExposesRelationships<Relationship> {\n\n\t/**\n\t * {@return the labels associated with this <code>Node</code>}\n\t */\n\tList<NodeLabel> getLabels();\n\n\t/**\n\t * Creates a copy of this node with a new symbolic name.\n\t * @param newSymbolicName the new symbolic name.\n\t * @return the new node.\n\t */\n\tNode named(String newSymbolicName);\n\n\t/**\n\t * Creates a copy of this node with a new symbolic name.\n\t * @param newSymbolicName the new symbolic name.\n\t * @return the new node.\n\t */\n\tNode named(SymbolicName newSymbolicName);\n\n\t/**\n\t * A condition that checks for the presence of labels on a node.\n\t * @param labelsToQuery a list of labels to query\n\t * @return a condition that checks whether this node has all the labels to query\n\t */\n\tCondition hasLabels(String... labelsToQuery);\n\n\t/**\n\t * Returns a condition that checks for the presence of a label expression on a node.\n\t * @param labels the labels to check\n\t * @return a condition that checks whether this node has all the labels to query\n\t * @since 2024.3.0\n\t * @deprecated use {@link #hasLabels(Labels)}\n\t */\n\t@SuppressWarnings(\"removal\")\n\t@Deprecated(forRemoval = true)\n\tCondition hasLabels(LabelExpression labels);\n\n\t/**\n\t * Returns a condition that checks for the presence of a label expression on a node.\n\t * @param labels the labels to check\n\t * @return a condition that checks whether this node has all the labels to query\n\t * @since 2025.1.0\n\t */\n\tCondition hasLabels(Labels labels);\n\n\t/**\n\t * Creates a new condition whether this node is equal to {@literal otherNode}.\n\t * @param otherNode the node to compare this node to.\n\t * @return a condition.\n\t */\n\tCondition isEqualTo(Node otherNode);\n\n\t/**\n\t * Creates a new condition whether this node is not equal to {@literal otherNode}.\n\t * @param otherNode the node to compare this node to.\n\t * @return a condition.\n\t */\n\tCondition isNotEqualTo(Node otherNode);\n\n\t/**\n\t * Creates a new condition based on this node whether it is null.\n\t * @return a condition.\n\t */\n\tCondition isNull();\n\n\t/**\n\t * Creates a new condition based on this node whether it is not null.\n\t * @return a condition.\n\t */\n\tCondition isNotNull();\n\n\t/**\n\t * Creates a new sort item of this node in descending order.\n\t * @return a sort item.\n\t */\n\tSortItem descending();\n\n\t/**\n\t * Creates a new sort item of this node in ascending order.\n\t * @return a sort item.\n\t */\n\tSortItem ascending();\n\n\t/**\n\t * Creates an alias for this node.\n\t * @param alias the alias to use.\n\t * @return the aliased expression.\n\t */\n\tAliasedExpression as(String alias);\n\n\t/**\n\t * Returns a new function invocation returning the internal id of this node.\n\t * @return a new function invocation returning the internal id of this node\n\t * @deprecated Use {@link #elementId}\n\t */\n\t@Deprecated(since = \"2022.6.0\")\n\t// The deprecation warning on any client code calling this is actually the point.\n\t@SuppressWarnings({ \"DeprecatedIsStillUsed\", \"squid:S1133\" })\n\tFunctionInvocation internalId();\n\n\t/**\n\t * Returns a new function invocation returning the element id of this node.\n\t * @return a new function invocation returning the element id of this node\n\t * @since 2022.6.0\n\t */\n\tdefault FunctionInvocation elementId() {\n\t\treturn Functions.elementId(this);\n\t}\n\n\t/**\n\t * {@return a new function invocation returning the labels of this node}\n\t */\n\tFunctionInvocation labels();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/NodeBase.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * This is the base class for all nodes. It can be used with generics, specifying a valid\n * type. This is useful when using it as a base class for a static metamodel.\n *\n * @param <SELF> the type of this node\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = STABLE, since = \"2021.1.0\")\n@SuppressWarnings(\"deprecation\") // IDEA is stupid.\npublic abstract class NodeBase<SELF extends Node> extends AbstractNode implements Node {\n\n\tfinal List<NodeLabel> staticLabels;\n\n\tfinal Labels dynamicLabels;\n\n\tfinal Properties properties;\n\n\tfinal Where innerPredicate;\n\n\t@SuppressWarnings(\"squid:S3077\") // Symbolic name is unmodifiable\n\tprivate volatile SymbolicName symbolicName;\n\n\t// ------------------------------------------------------------------------\n\t// Public API to be used by the static meta model.\n\t// Non-final methods are ok to be overwritten.\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Creates a new base object from a set of labels.\n\t * @param primaryLabel the primary label\n\t * @param additionalLabels an optional list of additional ones.\n\t */\n\tprotected NodeBase(String primaryLabel, String... additionalLabels) {\n\n\t\tthis(null, primaryLabel, null, additionalLabels);\n\t}\n\n\t/**\n\t * Creates a new base object from a {@link SymbolicName} name, a list of labels and a\n\t * set of properties.\n\t * @param symbolicName the symbolic name for this node object\n\t * @param staticLabels the list of labels, no primary is given\n\t * @param properties a set of properties\n\t */\n\tprotected NodeBase(SymbolicName symbolicName, List<NodeLabel> staticLabels, Properties properties) {\n\t\tthis(symbolicName, new ArrayList<>(staticLabels), null, properties, null);\n\t}\n\n\tNodeBase() {\n\n\t\tthis(null, Collections.emptyList(), null);\n\t}\n\n\tNodeBase(SymbolicName symbolicName, String primaryLabel, MapExpression properties, String... additionalLabels) {\n\n\t\tthis(symbolicName, assertLabels(primaryLabel, additionalLabels), Properties.create(properties));\n\t}\n\n\tNodeBase(SymbolicName symbolicName, List<NodeLabel> staticLabels, Labels dynamicLabels, Properties properties,\n\t\t\tWhere innerPredicate) {\n\n\t\tthis.symbolicName = symbolicName;\n\t\tthis.staticLabels = staticLabels;\n\t\tthis.dynamicLabels = dynamicLabels;\n\t\tthis.properties = properties;\n\t\tthis.innerPredicate = innerPredicate;\n\t}\n\n\tprivate static List<NodeLabel> assertLabels(String primaryLabel, String[] additionalLabels) {\n\n\t\tAssertions.hasText(primaryLabel, \"A primary label is required.\");\n\n\t\tif (additionalLabels != null) {\n\t\t\tfor (String additionalLabel : additionalLabels) {\n\t\t\t\tAssertions.hasText(additionalLabel, \"An empty label is not allowed.\");\n\t\t\t}\n\t\t}\n\n\t\tList<NodeLabel> labels = new ArrayList<>();\n\t\tlabels.add(new NodeLabel(primaryLabel));\n\t\tif (additionalLabels != null) {\n\t\t\tlabels.addAll(Arrays.stream(additionalLabels).map(NodeLabel::new).toList());\n\t\t}\n\n\t\treturn labels;\n\t}\n\n\t@Override\n\tpublic final SELF named(String newSymbolicName) {\n\n\t\tAssertions.hasText(newSymbolicName, \"Symbolic name is required.\");\n\t\treturn named(SymbolicName.of(newSymbolicName));\n\t}\n\n\t/**\n\t * This method needs to be implemented to provide new, type safe instances of this\n\t * node.\n\t * @param newSymbolicName the new symbolic name.\n\t * @return a new node\n\t */\n\t@Override\n\t// This is overridden to make sure we allow a covariant return type\n\t@SuppressWarnings(\"squid:S3038\")\n\tpublic abstract SELF named(SymbolicName newSymbolicName);\n\n\t@Override\n\tpublic final SELF withProperties(Object... keysAndValues) {\n\n\t\tMapExpression newProperties = null;\n\t\tif (keysAndValues != null && keysAndValues.length != 0) {\n\t\t\tnewProperties = MapExpression.create(false, keysAndValues);\n\t\t}\n\t\treturn withProperties(newProperties);\n\t}\n\n\t/**\n\t * A new object with a new set of properties.\n\t * @param newProperties a map with the new properties\n\t * @return a new object\n\t */\n\t@Override\n\tpublic final SELF withProperties(Map<String, Object> newProperties) {\n\n\t\treturn withProperties(MapExpression.create(newProperties));\n\t}\n\n\t/**\n\t * This method needs to be implemented to provide new, type safe instances of this\n\t * node.\n\t * @param newProperties the new properties (can be {@literal null} to remove exiting\n\t * properties).\n\t * @return a new node\n\t */\n\t@Override\n\t// This is overridden to make sure we allow a covariant return type\n\t@SuppressWarnings(\"squid:S3038\")\n\tpublic abstract SELF withProperties(MapExpression newProperties);\n\n\t// ------------------------------------------------------------------------\n\t// Internal API.\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * {@return set of properties for this node}\n\t */\n\tprotected final Properties getProperties() {\n\t\treturn this.properties;\n\t}\n\n\t@Override\n\tpublic final List<NodeLabel> getLabels() {\n\t\treturn (this.staticLabels != null) ? List.copyOf(this.staticLabels) : List.of();\n\t}\n\n\t@Override\n\tpublic final Optional<SymbolicName> getSymbolicName() {\n\t\treturn Optional.ofNullable(this.symbolicName);\n\t}\n\n\t@Override\n\tpublic final SymbolicName getRequiredSymbolicName() {\n\n\t\tSymbolicName requiredSymbolicName = this.symbolicName;\n\t\tif (requiredSymbolicName == null) {\n\t\t\tsynchronized (this) {\n\t\t\t\trequiredSymbolicName = this.symbolicName;\n\t\t\t\tif (requiredSymbolicName == null) {\n\t\t\t\t\tthis.symbolicName = SymbolicName.unresolved();\n\t\t\t\t\trequiredSymbolicName = this.symbolicName;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn requiredSymbolicName;\n\t}\n\n\t@Override\n\tpublic final void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.getSymbolicName().ifPresent(s -> s.accept(visitor));\n\t\tif (this.staticLabels != null) {\n\t\t\tthis.staticLabels.forEach(label -> label.accept(visitor));\n\t\t}\n\t\tVisitable.visitIfNotNull(this.dynamicLabels, visitor);\n\t\tVisitable.visitIfNotNull(this.properties, visitor);\n\t\tVisitable.visitIfNotNull(this.innerPredicate, visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/NodeLabel.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Expression for a single Node label.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class NodeLabel implements Visitable {\n\n\tprivate final String value;\n\n\tNodeLabel(String value) {\n\t\tthis.value = value;\n\t}\n\n\t/**\n\t * {@return the actual value of this label. Needs to be escaped before rendering}\n\t */\n\tpublic String getValue() {\n\t\treturn this.value;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"NodeLabel{\" + \"value='\" + this.value + '\\'' + '}';\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/NullLiteral.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Represents the literal value {@literal null}.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class NullLiteral extends LiteralBase<Void> {\n\n\tstatic final NullLiteral INSTANCE = new NullLiteral();\n\n\tprivate NullLiteral() {\n\n\t\tsuper(null);\n\t}\n\n\t@Override\n\tpublic String asString() {\n\t\treturn \"NULL\";\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/NumberLiteral.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Representation of a numeric literal.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class NumberLiteral extends LiteralBase<Number> {\n\n\tNumberLiteral(Number content) {\n\t\tsuper(content);\n\t}\n\n\t@Override\n\tpublic String asString() {\n\n\t\treturn String.valueOf(getContent());\n\t}\n\n\t@Override\n\tpublic Number getContent() {\n\t\treturn this.content;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/OngoingListBasedPredicateFunction.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\n\n/**\n * Allows to define the source of the list predicate.\n *\n * @author Michael J. Simons\n * @since 2024.0.0\n */\npublic interface OngoingListBasedPredicateFunction {\n\n\t/**\n\t * Returns a builder to specify the where condition for the list based predicate.\n\t * @param list a list expression\n\t * @return a builder to specify the where condition for the list based predicate\n\t */\n\t@CheckReturnValue\n\tOngoingListBasedPredicateFunctionWithList in(Expression list);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/OngoingListBasedPredicateFunctionWithList.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\n/**\n * Allows to specify the where condition for the list based predicate.\n *\n * @author Michael J. Simons\n * @since 2024.0.0\n */\npublic interface OngoingListBasedPredicateFunctionWithList {\n\n\t/**\n\t * Returns the final list based predicate function.\n\t * @param condition the condition for the list based predicate.\n\t * @return the final list based predicate function\n\t */\n\tCondition where(Condition condition);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Operation.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Arrays;\nimport java.util.EnumSet;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A binary operation.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Operation implements Expression {\n\n\t/**\n\t * A set of operators triggering operations on labels.\n\t */\n\tprivate static final EnumSet<Operator> LABEL_OPERATORS = EnumSet.of(Operator.SET_LABEL, Operator.REMOVE_LABEL);\n\n\tprivate static final EnumSet<Operator.Type> NEEDS_GROUPING_BY_TYPE = EnumSet\n\t\t.complementOf(EnumSet.of(Operator.Type.PROPERTY, Operator.Type.LABEL));\n\n\tprivate static final EnumSet<Operator> DONT_GROUP = EnumSet.of(Operator.EXPONENTIATION, Operator.PIPE,\n\t\t\tOperator.UNARY_MINUS, Operator.UNARY_PLUS);\n\n\tprivate final Expression left;\n\n\tprivate final Operator operator;\n\n\tprivate final Visitable right;\n\n\tOperation(Expression left, Operator operator, Expression right) {\n\n\t\tthis.left = left;\n\t\tthis.operator = operator;\n\t\tthis.right = right;\n\t}\n\n\tOperation(Expression left, Operator operator, Visitable right) {\n\n\t\tthis.left = left;\n\t\tthis.operator = operator;\n\t\tthis.right = right;\n\t}\n\n\tstatic Operation create(Operator operator, Expression expression) {\n\n\t\tAssertions.notNull(operator, \"Operator must not be null.\");\n\t\tAssertions.isTrue(operator.isUnary(), \"Operator must be unary.\");\n\t\tAssertions.notNull(expression, \"The expression must not be null.\");\n\n\t\treturn switch (operator.getType()) {\n\t\t\tcase PREFIX -> new Operation(null, operator, expression);\n\t\t\tcase POSTFIX -> new Operation(expression, operator, (Expression) null);\n\t\t\tdefault -> throw new IllegalArgumentException(\"Invalid operator type \" + operator.getType());\n\t\t};\n\t}\n\n\tstatic Operation create(Expression op1, Operator operator, Expression op2) {\n\n\t\tAssertions.notNull(op1, \"The first operand must not be null.\");\n\t\tAssertions.notNull(operator, \"Operator must not be null.\");\n\t\tAssertions.notNull(op2, \"The second operand must not be null.\");\n\n\t\treturn new Operation(op1, operator, op2);\n\t}\n\n\tstatic Operation create(Node op1, Operator operator, String... nodeLabels) {\n\n\t\tAssertions.notNull(op1, \"The first operand must not be null.\");\n\t\tAssertions.isTrue(op1.getSymbolicName().isPresent(), \"The node must have a name.\");\n\t\tAssertions.isTrue(LABEL_OPERATORS.contains(operator),\n\t\t\t\tString.format(\"Only operators %s can be used to modify labels\", LABEL_OPERATORS));\n\t\tAssertions.notEmpty(nodeLabels, \"The labels cannot be empty.\");\n\n\t\tvar listOfNodeLabels = new TypedSubtree<>(Arrays.stream(nodeLabels).map(NodeLabel::new).toList()) {\n\t\t\t@Override\n\t\t\tpublic String separator() {\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t};\n\t\treturn new Operation(op1.getRequiredSymbolicName(), operator, listOfNodeLabels);\n\t}\n\n\tstatic Operation create(Node op1, Operator operator, Labels labels) {\n\n\t\tAssertions.notNull(op1, \"The first operand must not be null.\");\n\t\tAssertions.isTrue(op1.getSymbolicName().isPresent(), \"The node must have a name.\");\n\t\tAssertions.isTrue(LABEL_OPERATORS.contains(operator),\n\t\t\t\tString.format(\"Only operators %s can be used to modify labels\", LABEL_OPERATORS));\n\t\tAssertions.notNull(labels, \"The labels cannot be empty.\");\n\t\tAssertions.isTrue(labels.canBeUsedInUpdate(),\n\t\t\t\t\"Only a single dynamic label expression or a set of static labels might be used in an updating clause\");\n\n\t\treturn new Operation(op1.getRequiredSymbolicName(), operator, labels);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tif (this.left != null) {\n\t\t\tExpressions.nameOrExpression(this.left).accept(visitor);\n\t\t}\n\t\tthis.operator.accept(visitor);\n\t\tVisitable.visitIfNotNull(this.right, visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t/**\n\t * Checks, whether this operation needs grouping.\n\t * @return true, if this operation needs grouping.\n\t */\n\tpublic boolean needsGrouping() {\n\t\treturn NEEDS_GROUPING_BY_TYPE.contains(this.operator.getType()) && !DONT_GROUP.contains(this.operator);\n\t}\n\n\t@API(status = INTERNAL)\n\tOperator getOperator() {\n\t\treturn this.operator;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Operations.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Set;\n\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\n/**\n * A set of operations.\n *\n * @author Michael J. Simons\n * @since 1.0 be accessible.\n */\nfinal class Operations {\n\n\tprivate static final java.util.Set<Class<? extends Expression>> VALID_MUTATORS = Set.of(MapExpression.class,\n\t\t\tParameter.class, MapProjection.class, SymbolicName.class, FunctionInvocation.class);\n\n\t/**\n\t * Not to be instantiated.\n\t */\n\tprivate Operations() {\n\t}\n\n\t/**\n\t * Creates a unary minus operation.\n\t * @param e the expression to which the unary minus should be applied. We don't check\n\t * if it's a numeric expression, but in hindsight to generate semantically correct\n\t * Cypher, it's recommended that is one.\n\t * @return an unary minus operation.\n\t * @since 2021.2.3\n\t */\n\tstatic Operation minus(Expression e) {\n\n\t\treturn Operation.create(Operator.UNARY_MINUS, e);\n\t}\n\n\t/**\n\t * Creates an unary plus operation.\n\t * @param e the expression to which the unary plus should be applied. We don't check\n\t * if it's a numeric expression, but in hindsight to generate semantically correct\n\t * Cypher, it's recommended that is one.\n\t * @return an unary plus operation.\n\t * @since 2021.2.3\n\t */\n\tstatic Expression plus(Expression e) {\n\n\t\treturn Operation.create(Operator.UNARY_PLUS, e);\n\t}\n\n\tstatic Operation concat(Expression op1, Expression op2) {\n\n\t\treturn Operation.create(op1, Operator.CONCAT, op2);\n\t}\n\n\tstatic Operation add(Expression op1, Expression op2) {\n\n\t\treturn Operation.create(op1, Operator.ADDITION, op2);\n\t}\n\n\tstatic Operation subtract(Expression op1, Expression op2) {\n\n\t\treturn Operation.create(op1, Operator.SUBTRACTION, op2);\n\t}\n\n\tstatic Operation multiply(Expression op1, Expression op2) {\n\n\t\treturn Operation.create(op1, Operator.MULTIPLICATION, op2);\n\t}\n\n\tstatic Operation divide(Expression op1, Expression op2) {\n\n\t\treturn Operation.create(op1, Operator.DIVISION, op2);\n\t}\n\n\tstatic Operation remainder(Expression op1, Expression op2) {\n\n\t\treturn Operation.create(op1, Operator.MODULO_DIVISION, op2);\n\t}\n\n\tstatic Operation pow(Expression op1, Expression op2) {\n\n\t\treturn Operation.create(op1, Operator.EXPONENTIATION, op2);\n\t}\n\n\t/**\n\t * Creates a {@code =} operation. The left hand side should resolve to a property or\n\t * to something which has labels or types to modify and the right hand side should\n\t * either be new properties or labels.\n\t * @param target the target that should be modified\n\t * @param value the new value of the target\n\t * @return a new operation.\n\t * @since 2021.2.3\n\t */\n\tstatic Operation set(Expression target, Expression value) {\n\n\t\treturn Operation.create(target, Operator.SET, value);\n\t}\n\n\t/**\n\t * Creates a {@code +=} operation. The left hand side must resolve to a container\n\t * (either a node or a relationship) of properties and the right hand side must be a\n\t * map of new or updated properties\n\t * @param target the target container that should be modified\n\t * @param value the new properties\n\t * @return a new operation.\n\t * @since 2020.1.5\n\t */\n\tstatic Operation mutate(Expression target, MapExpression value) {\n\n\t\treturn Operation.create(target, Operator.MUTATE, value);\n\t}\n\n\t/**\n\t * Creates a {@code +=} operation. The left hand side must resolve to a container\n\t * (either a node or a relationship) of properties and the right hand side must be a\n\t * map of new or updated properties\n\t * @param target the target container that should be modified\n\t * @param value the new properties\n\t * @return a new operation.\n\t * @since 2020.1.5\n\t */\n\tstatic Operation mutate(Expression target, Expression value) {\n\n\t\tAssertions.notNull(value, \"New properties value must not be null\");\n\t\tAssertions.isTrue(\n\t\t\t\tProperty.class.isAssignableFrom(value.getClass()) || VALID_MUTATORS.contains(value.getClass()),\n\t\t\t\t\"A property container can only be mutated by a map, or a parameter or property pointing to a map.\");\n\n\t\treturn Operation.create(target, Operator.MUTATE, value);\n\t}\n\n\t/**\n\t * Creates an operation adding one or more labels from a given {@link Node node}.\n\t * @param target the target of the new labels\n\t * @param label the labels to be added\n\t * @return a set operation\n\t * @since 2021.2.3\n\t */\n\tstatic Operation set(Node target, String... label) {\n\n\t\treturn Operation.create(target, Operator.SET_LABEL, label);\n\t}\n\n\t/**\n\t * Creates an operation adding one or more labels from a given {@link Node node}.\n\t * @param target the target of the new labels\n\t * @param labels the labels to be added\n\t * @return a set operation\n\t * @since 2025.1.0\n\t */\n\tstatic Operation set(Node target, Labels labels) {\n\n\t\treturn Operation.create(target, Operator.SET_LABEL, labels);\n\t}\n\n\t/**\n\t * Creates an operation removing one or more labels from a given {@link Node node}.\n\t * @param target the target of the remove operation\n\t * @param label the labels to be removed\n\t * @return a remove operation\n\t * @since 2021.2.3\n\t */\n\tstatic Operation remove(Node target, String... label) {\n\n\t\treturn Operation.create(target, Operator.REMOVE_LABEL, label);\n\t}\n\n\t/**\n\t * Creates an operation removing one or more labels from a given {@link Node node}.\n\t * @param node the node from which the labels should be removed\n\t * @param labels the labels to be removed\n\t * @return a remove operation\n\t * @since 2025.1.0\n\t */\n\tstatic Expression remove(Node node, Labels labels) {\n\n\t\treturn Operation.create(node, Operator.REMOVE_LABEL, labels);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Operator.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * An operator. See <a href=\n * \"https://neo4j.com/docs/cypher-manual/current/syntax/operators/#query-operators-summary\">Operators</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic enum Operator implements Visitable {\n\n\t// Mathematical operators\n\t/**\n\t * Standard addition operator.\n\t */\n\tADDITION(\"+\"),\n\t/**\n\t * Standard subtraction operator.\n\t */\n\tSUBTRACTION(\"-\"),\n\t/**\n\t * Unary minus operator.\n\t */\n\tUNARY_MINUS(\"-\", Type.PREFIX),\n\t/**\n\t * Unary plus operator.\n\t */\n\tUNARY_PLUS(\"+\", Type.PREFIX),\n\t/**\n\t * Standard multiplication operator.\n\t */\n\tMULTIPLICATION(\"*\"),\n\t/**\n\t * Standard division operator.\n\t */\n\tDIVISION(\"/\"),\n\t/**\n\t * Standard modulo operator.\n\t */\n\tMODULO_DIVISION(\"%\"),\n\t/**\n\t * Operator for exponentiation.\n\t */\n\tEXPONENTIATION(\"^\"),\n\n\t// Comparison operators\n\t/**\n\t * Comparison for equality.\n\t */\n\tEQUALITY(\"=\"),\n\t/**\n\t * Comparison for inequality.\n\t */\n\tINEQUALITY(\"<>\"),\n\t/**\n\t * &lt; comparison.\n\t */\n\tLESS_THAN(\"<\"),\n\t/**\n\t * &gt; comparison.\n\t */\n\tGREATER_THAN(\">\"),\n\t/**\n\t * &le; comparison.\n\t */\n\tLESS_THAN_OR_EQUAL_TO(\"<=\"),\n\t/**\n\t * &ge; comparison.\n\t */\n\tGREATER_THAN_OR_EQUAL_TO(\">=\"),\n\t/**\n\t * {@code IS NULL} comparison.\n\t */\n\tIS_NULL(\"IS NULL\", Type.POSTFIX),\n\t/**\n\t * {@code IS NOT NULL} comparison.\n\t */\n\tIS_NOT_NULL(\"IS NOT NULL\", Type.POSTFIX),\n\n\t/**\n\t * String operator for {@code STARTS WITH}.\n\t */\n\tSTARTS_WITH(\"STARTS WITH\"),\n\t/**\n\t * String operator for {@code ENDS WITH}.\n\t */\n\tENDS_WITH(\"ENDS WITH\"),\n\t/**\n\t * String operator for {@code CONTAINS}.\n\t */\n\tCONTAINS(\"CONTAINS\"),\n\n\t// Boolean operators\n\t/**\n\t * The AND operator.\n\t */\n\tAND(\"AND\"),\n\t/**\n\t * The OR operator.\n\t */\n\tOR(\"OR\"),\n\t/**\n\t * The XOR operator.\n\t */\n\tXOR(\"XOR\"),\n\t/**\n\t * The NOT operator.\n\t */\n\tNOT(\"NOT\", Type.PREFIX),\n\n\t// String operators\n\t/**\n\t * The string concatenating operator.\n\t */\n\tCONCAT(\"+\"),\n\t/**\n\t * The string matching operator.\n\t */\n\tMATCHES(\"=~\"),\n\n\t// List operators\n\t/**\n\t * {@code IN} operator.\n\t */\n\tIN(\"IN\"),\n\n\t// Property operators\n\t/**\n\t * Property operator for assigning properties.\n\t */\n\tSET(\"=\", Type.PROPERTY),\n\t/**\n\t * Property operator for retrieving properties.\n\t */\n\tGET(\".\", Type.PROPERTY),\n\t/**\n\t * Property operator for modifying properties.\n\t */\n\tMUTATE(\"+=\", Type.PROPERTY),\n\n\t// Node operators\n\t/**\n\t * The label operator adding labels.\n\t */\n\tSET_LABEL(\"\", Type.LABEL),\n\t/**\n\t * The label operator removing labels.\n\t */\n\tREMOVE_LABEL(\"\", Type.LABEL),\n\n\t// Misc\n\t/**\n\t * The assigment operator (Read as in `p := (a)--&gt;(b)`).\n\t */\n\tASSIGMENT(\"=\"),\n\t/**\n\t * The pipe operator.\n\t */\n\tPIPE(\"|\");\n\n\tprivate final String representation;\n\n\tprivate final Type type;\n\n\tOperator(String representation) {\n\t\tthis(representation, Type.BINARY);\n\t}\n\n\tOperator(String representation, Type type) {\n\t\tthis.representation = representation;\n\t\tthis.type = type;\n\t}\n\n\t/**\n\t * {@return the operators textual representation}\n\t */\n\t@API(status = INTERNAL)\n\tpublic String getRepresentation() {\n\t\treturn this.representation;\n\t}\n\n\t/**\n\t * {@return true if this is a unary operator}\n\t */\n\tboolean isUnary() {\n\t\treturn this.type != Type.BINARY;\n\t}\n\n\t/**\n\t * {@return the type of this operator}\n\t */\n\t@API(status = INTERNAL)\n\tpublic Type getType() {\n\t\treturn this.type;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n\t/**\n\t * {@link Operator} type.\n\t *\n\t * @since 1.0\n\t */\n\tpublic enum Type {\n\n\t\t/**\n\t\t * Describes a binary operator (An operator with to operands).\n\t\t */\n\t\tBINARY,\n\t\t/**\n\t\t * Describes a unary prefix operator (An operator with one operand after the\n\t\t * operator).\n\t\t */\n\t\tPREFIX,\n\t\t/**\n\t\t * Describes a unary postfix operator (An operator with one operand before the\n\t\t * operator).\n\t\t */\n\t\tPOSTFIX,\n\t\t/**\n\t\t * Describes an operator working with properties of entities.\n\t\t */\n\t\tPROPERTY,\n\t\t/**\n\t\t * The binary operator modifying labels of nodes.\n\t\t */\n\t\tLABEL\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Order.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Represents the list of sort items that make up the order of records in a result set.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Order extends TypedSubtree<SortItem> {\n\n\tOrder(List<SortItem> sortItems) {\n\t\tsuper(sortItems);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Parameter.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Objects;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Represents a named parameter inside a Cypher statement.\n *\n * @param <T> the type of the parameter. Defaults to {@link Object} for a parameter\n * without a value from which to derive the actual type.\n * @author Michael J. Simons\n * @author Andreas Berger\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Parameter<T> implements Expression {\n\n\tstatic final Object NO_VALUE = new Object();\n\n\tprivate final String name;\n\n\tprivate final T value;\n\n\tprivate Parameter(String name, T value) {\n\n\t\tthis.name = name;\n\t\tthis.value = value;\n\t}\n\n\tstatic Parameter<Object> create(String name) {\n\t\treturn create(name, NO_VALUE);\n\t}\n\n\tstatic <T> Parameter<T> create(String name, T value) {\n\n\t\tAssertions.hasText(name, \"The name of the parameter is required!\");\n\n\t\tif (name.startsWith(\"$\")) {\n\t\t\treturn create(name.substring(1), value);\n\t\t}\n\n\t\treturn new Parameter<>(name, value);\n\t}\n\n\tstatic <T> Parameter<T> anon(T value) {\n\n\t\treturn new Parameter<>(null, value);\n\t}\n\n\t/**\n\t * Query method to check if this is an anonymous parameter.\n\t * @return true if this is an anonymous parameter\n\t * @since 2021.1.0\n\t */\n\t@API(status = STABLE, since = \"2021.0.0\")\n\tpublic boolean isAnon() {\n\t\treturn this.name == null || this.name.trim().isEmpty();\n\t}\n\n\t/**\n\t * Returns the name of this parameter.\n\t * @return the name of this parameter\n\t * @since 2023.1.0\n\t */\n\t@API(status = STABLE, since = \"2023.1.0\")\n\tpublic String getName() {\n\t\treturn this.name;\n\t}\n\n\t/**\n\t * Returns a new parameter with a bound value.\n\t * @param newValue the new value that should be bound by this parameter\n\t * @return a new parameter with a bound value\n\t * @since 2021.0.0\n\t */\n\t@API(status = STABLE, since = \"2021.0.0\")\n\tpublic Parameter<?> withValue(Object newValue) {\n\t\treturn create(this.name, newValue);\n\t}\n\n\t/**\n\t * {@return the value bound to this parameter}\n\t */\n\t@API(status = INTERNAL, since = \"2021.1.0\")\n\tpublic T getValue() {\n\t\treturn this.value;\n\t}\n\n\t/**\n\t * {@return true if the Parameter has a bound value}\n\t */\n\tboolean hasValue() {\n\t\treturn !Objects.equals(this.value, NO_VALUE);\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (this == o) {\n\t\t\treturn true;\n\t\t}\n\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\treturn false;\n\t\t}\n\n\t\tParameter<?> parameter = (Parameter<?>) o;\n\t\tif (this.isAnon() && parameter.isAnon()) {\n\t\t\treturn Objects.deepEquals(this.value, parameter.value);\n\t\t}\n\t\telse if (this.isAnon() != parameter.isAnon()) {\n\t\t\treturn false;\n\t\t}\n\t\treturn Objects.equals(this.name, parameter.name);\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn this.isAnon() ? Objects.hashCode(this.value) : Objects.hash(this.name);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ParameterCollectingVisitor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.TreeMap;\nimport java.util.TreeSet;\n\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.ConstantParameterHolder;\nimport org.neo4j.cypherdsl.core.internal.NameResolvingStrategy;\nimport org.neo4j.cypherdsl.core.internal.ReflectiveVisitor;\n\n/**\n * This is an implementation of a visitor to the Cypher AST created by the Cypher builder\n * based on the {@link ReflectiveVisitor reflective visitor}.\n * <p>\n * It collects all parameters with bound value into a map of used parameters.\n * <p>\n *\n * @author Andreas Berger\n * @author Michael J. Simons\n * @since 2021.0.0\n */\nfinal class ParameterCollectingVisitor implements Visitor {\n\n\tfinal Map<String, String> parameterMapping = new TreeMap<>();\n\n\tprivate final StatementContext statementContext;\n\n\tprivate final boolean renderConstantsAsParameters;\n\n\tprivate final Set<String> parameterNames = new TreeSet<>();\n\n\tprivate final Map<String, Object> parameterValues = new TreeMap<>();\n\n\tprivate final Map<String, Set<Object>> erroneousParameters = new TreeMap<>();\n\n\tprivate final NameResolvingStrategy nameGenerator;\n\n\tParameterCollectingVisitor(StatementContext statementContext, boolean renderConstantsAsParameters) {\n\t\tthis.statementContext = statementContext;\n\t\tthis.nameGenerator = NameResolvingStrategy.useGeneratedParameterNames(statementContext);\n\t\tthis.renderConstantsAsParameters = renderConstantsAsParameters;\n\t}\n\n\t@Override\n\tpublic void enter(Visitable segment) {\n\n\t\tif (!(segment instanceof Parameter<?> parameter)) {\n\t\t\treturn;\n\t\t}\n\n\t\tString parameterName = this.statementContext.getParameterName(parameter);\n\t\tObject newValue = parameter.getValue();\n\t\tif (newValue instanceof ConstantParameterHolder constantParameterHolder) {\n\t\t\tif (!this.renderConstantsAsParameters) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tnewValue = constantParameterHolder.getValue();\n\t\t}\n\t\tboolean knownParameterName = !this.parameterNames.add(parameterName);\n\t\tif (!(knownParameterName || parameter.isAnon())) {\n\t\t\tthis.parameterMapping.put(parameterName, this.nameGenerator.resolve(parameter));\n\t\t}\n\n\t\tObject oldValue = (knownParameterName && this.parameterValues.containsKey(parameterName))\n\t\t\t\t? this.parameterValues.get(parameterName) : Parameter.NO_VALUE;\n\t\tif (parameter.hasValue()) {\n\t\t\tthis.parameterValues.put(parameterName, newValue);\n\t\t}\n\t\tif (knownParameterName && !Objects.equals(oldValue, newValue)) {\n\t\t\tSet<Object> conflictingObjects = this.erroneousParameters.computeIfAbsent(parameterName, s -> {\n\t\t\t\tHashSet<Object> list = new HashSet<>();\n\t\t\t\tlist.add(oldValue);\n\t\t\t\treturn list;\n\t\t\t});\n\t\t\tconflictingObjects.add(newValue);\n\t\t}\n\t}\n\n\tParameterInformation getResult() {\n\n\t\tif (!this.erroneousParameters.isEmpty()) {\n\t\t\tthrow new ConflictingParametersException(this.erroneousParameters);\n\t\t}\n\n\t\treturn new ParameterInformation(this.parameterNames, this.parameterValues, this.parameterMapping);\n\t}\n\n\tstatic final class ParameterInformation {\n\n\t\tfinal Set<String> names;\n\n\t\tfinal Map<String, Object> values;\n\n\t\tfinal Map<String, String> renames;\n\n\t\tParameterInformation(Set<String> names, Map<String, Object> values, Map<String, String> renames) {\n\t\t\tthis.names = Collections.unmodifiableSet(names);\n\t\t\tthis.values = Collections.unmodifiableMap(values);\n\t\t\tthis.renames = Collections.unmodifiableMap(renames);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ParameterLiteral.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\n/**\n * Representation of a parameter literal. For internal use only.\n *\n * @author Michael J. Simons\n * @since 2025.2.0\n */\nfinal class ParameterLiteral extends LiteralBase<Parameter<?>> {\n\n\tprivate ParameterLiteral(Parameter<?> content) {\n\t\tsuper(content);\n\t}\n\n\tstatic Literal<Parameter<?>> of(Parameter<?> content) {\n\t\tif (content.isAnon()) {\n\t\t\tthrow new IllegalArgumentException(\"Anonymous parameters cannot be used as parameter literals\");\n\t\t}\n\t\treturn new ParameterLiteral(content);\n\t}\n\n\t@Override\n\tpublic String asString() {\n\n\t\treturn \"$\" + content.getName();\n\t}\n\n\t@Override\n\tpublic Parameter<?> getContent() {\n\t\treturn this.content;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Pattern.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * A pattern is something that can be matched. It consists of one or more pattern\n * elements. Those can be nodes or chains of nodes and relationships.\n * <p>\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Pattern.html\">Pattern</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = INTERNAL, since = \"1.0\")\nfinal class Pattern extends TypedSubtree<PatternElement> {\n\n\tprivate Pattern(List<PatternElement> patternElements) {\n\t\tsuper(patternElements);\n\t}\n\n\tstatic Pattern of(PatternElement requiredPattern, PatternElement... patternElement) {\n\t\tList<PatternElement> elements;\n\t\tif (patternElement == null || patternElement.length == 0) {\n\t\t\telements = List.of(requiredPattern);\n\t\t}\n\t\telse {\n\t\t\telements = new ArrayList<>();\n\t\t\telements.add(requiredPattern);\n\t\t\telements.addAll(Arrays.asList(patternElement));\n\t\t}\n\t\treturn Pattern.of(elements);\n\t}\n\n\tstatic Pattern of(Collection<? extends PatternElement> elements) {\n\t\treturn new Pattern(elements.stream().map(PatternElement.class::cast).toList());\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/PatternComprehension.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.RelationshipPatternCondition;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/PatternComprehension.html\">PatternComprehension</a>\n * and <a href=\n * \"https://neo4j.com/docs/cypher-manual/current/syntax/lists/#cypher-pattern-comprehension\">the\n * corresponding cypher manual entry</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class PatternComprehension implements Expression {\n\n\tprivate final PatternElement pattern;\n\n\tprivate final Where where;\n\n\tprivate final Expression listDefinition;\n\n\tprivate PatternComprehension(PatternElement pattern, Where where, Expression listDefinition) {\n\t\tthis.pattern = pattern;\n\t\tthis.where = where;\n\t\tthis.listDefinition = listDefinition;\n\t}\n\n\tstatic OngoingDefinitionWithPattern basedOn(RelationshipPattern pattern) {\n\n\t\tAssertions.notNull(pattern, \"A pattern is required\");\n\t\treturn new Builder(pattern);\n\t}\n\n\tstatic OngoingDefinitionWithPattern basedOn(NamedPath pattern) {\n\n\t\tAssertions.notNull(pattern, \"A pattern is required\");\n\t\treturn new Builder(pattern);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.pattern.accept(visitor);\n\t\tVisitable.visitIfNotNull(this.where, visitor);\n\t\tOperator.PIPE.accept(visitor);\n\t\tthis.listDefinition.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t/**\n\t * Provides the final step of defining a pattern comprehension.\n\t */\n\tpublic interface OngoingDefinitionWithoutReturn {\n\n\t\t/**\n\t\t * Defines the returning named items.\n\t\t * @param variables the elements to be returned from the pattern\n\t\t * @return the final definition of the pattern comprehension\n\t\t * @see #returning(Expression...)\n\t\t */\n\t\tdefault PatternComprehension returning(Named... variables) {\n\t\t\treturn returning(Expressions.createSymbolicNames(variables));\n\t\t}\n\n\t\t/**\n\t\t * Defines the returning exoression items.\n\t\t * @param listDefinition defines the elements to be returned from the pattern\n\t\t * @return the final definition of the pattern comprehension\n\t\t */\n\t\tPatternComprehension returning(Expression... listDefinition);\n\n\t}\n\n\t/**\n\t * Allows to add a where clause into the definition of the pattern.\n\t */\n\tpublic interface OngoingDefinitionWithPattern extends OngoingDefinitionWithoutReturn {\n\n\t\t/**\n\t\t * Adds a {@code WHERE} clause to the inner statement of the pattern\n\t\t * comprehension.\n\t\t * @param condition an initial condition to be used with {@code WHERE}\n\t\t * @return an ongoing definition of a pattern comprehension for furhter\n\t\t * modification\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingDefinitionWithPatternAndWhere where(Condition condition);\n\n\t\t/**\n\t\t * Adds a where clause based on a path pattern to the ongoing definition.\n\t\t * @param pathPattern the path pattern to add to the where clause. This path\n\t\t * pattern must not be {@literal null} and must not introduce new variables not\n\t\t * available in the match.\n\t\t * @return a match or a call restricted by a where clause with no return items\n\t\t * yet.\n\t\t * @since 2020.1.4\n\t\t */\n\t\t@CheckReturnValue\n\t\tdefault OngoingDefinitionWithPatternAndWhere where(RelationshipPattern pathPattern) {\n\n\t\t\tAssertions.notNull(pathPattern, \"The path pattern must not be null.\");\n\t\t\treturn this.where(RelationshipPatternCondition.of(pathPattern));\n\t\t}\n\n\t}\n\n\t/**\n\t * Intermediate step that allows expressing additional, logical operators.\n\t */\n\tpublic interface OngoingDefinitionWithPatternAndWhere\n\t\t\textends OngoingDefinitionWithoutReturn, ExposesLogicalOperators<OngoingDefinitionWithPatternAndWhere> {\n\n\t}\n\n\t/**\n\t * Ongoing definition of a pattern comprehension. Can be defined without a\n\t * where-clause now.\n\t */\n\tprivate static final class Builder implements OngoingDefinitionWithPattern, OngoingDefinitionWithPatternAndWhere {\n\n\t\tprivate final PatternElement pattern;\n\n\t\tprivate final DefaultStatementBuilder.ConditionBuilder conditionBuilder = new DefaultStatementBuilder.ConditionBuilder();\n\n\t\tprivate Builder(PatternElement pattern) {\n\t\t\tthis.pattern = pattern;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingDefinitionWithPatternAndWhere where(Condition condition) {\n\t\t\tthis.conditionBuilder.where(condition);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingDefinitionWithPatternAndWhere and(Condition condition) {\n\t\t\tthis.conditionBuilder.and(condition);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingDefinitionWithPatternAndWhere or(Condition condition) {\n\t\t\tthis.conditionBuilder.or(condition);\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic PatternComprehension returning(Expression... expressions) {\n\t\t\tWhere where = this.conditionBuilder.buildCondition().map(Where::new).orElse(null);\n\t\t\treturn new PatternComprehension(this.pattern, where, ListExpression.listOrSingleExpression(expressions));\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/PatternElement.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/PatternElement.html\">PatternElement</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface PatternElement extends Visitable {\n\n\t/**\n\t * Creates a new {@link PatternElement} which including an additional filter. Returns\n\t * {@code this} pattern. when {@code predicate} is literal {@code null}.\n\t * <p>\n\t * The pattern might be a {@link Node node pattern} or a {@link RelationshipPattern\n\t * relationship pattern}.\n\t * <p>\n\t * A {@code WHERE} on a pattern is only supported from Neo4j 5.0 onwards.\n\t * @param predicate the predicate to filter on\n\t * @return a new pattern element or this instance if the predicate to this method was\n\t * literal {@code null}\n\t * @throws UnsupportedOperationException in cases the underlying element does not\n\t * support a {@code WHERE} clause\n\t * @since 2023.9.0\n\t */\n\t@Neo4jVersion(minimum = \"5.0\")\n\tdefault PatternElement where(Expression predicate) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/PatternExpression.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\n/**\n * A marker interface used for pattern appearing in {@code exists} or {@code size}\n * statements.\n *\n * @author Michael J. Simons\n * @since 2023.9.8\n */\npublic sealed interface PatternExpression permits PatternExpressionImpl {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/PatternExpressionImpl.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nfinal class PatternExpressionImpl implements PatternExpression, Visitable {\n\n\tprivate final Pattern pattern;\n\n\tPatternExpressionImpl(PatternElement patternElement) {\n\n\t\tthis.pattern = Pattern.of(List.of(patternElement));\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.pattern.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/PatternSelector.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A type resenting the {@code SHORTEST} keyword and it's variants.\n *\n * @author Michael J. Simons\n * @since 2024.7.0\n *\n */\n@API(status = STABLE, since = \"2024.7.0\")\npublic sealed interface PatternSelector extends Visitable {\n\n\t// Yes, we could use an enum here, but that would lead to two instances with a k, two\n\t// without,\n\t// hence, sealed classes are better as they model what we want to express, and in the\n\t// visitor\n\t// we can use switch with pattern matching on classes at some point in the future for\n\t// sure.\n\n\tstatic PatternSelector shortestK(int k) {\n\t\tif (k <= 0) {\n\t\t\tthrow new IllegalArgumentException(\"The path count needs to be greater than 0.\");\n\t\t}\n\t\treturn new ShortestK(k);\n\t}\n\n\tstatic PatternSelector allShortest() {\n\t\treturn new AllShortest();\n\t}\n\n\tstatic PatternSelector shortestKGroups(int k) {\n\t\tif (k <= 0) {\n\t\t\tthrow new IllegalArgumentException(\"The path count needs to be greater than 0.\");\n\t\t}\n\t\treturn new ShortestKGroups(k);\n\t}\n\n\tstatic PatternSelector any() {\n\t\treturn new Any();\n\t}\n\n\t/**\n\t * Representing {@code SHORTEST K}.\n\t */\n\tfinal class ShortestK implements PatternSelector {\n\n\t\tprivate final int k;\n\n\t\tpublic ShortestK(Integer k) {\n\t\t\tthis.k = k;\n\t\t}\n\n\t\tpublic int getK() {\n\t\t\treturn this.k;\n\t\t}\n\n\t}\n\n\t/**\n\t * Representing {@code ALL SHORTEST}.\n\t */\n\tfinal class AllShortest implements PatternSelector {\n\n\t\tprivate AllShortest() {\n\t\t}\n\n\t}\n\n\t/**\n\t * Representing {@code ANY}.\n\t */\n\tfinal class Any implements PatternSelector {\n\n\t\tprivate Any() {\n\t\t}\n\n\t}\n\n\t/**\n\t * Representing {@code SHORTEST K GROUPS}.\n\t */\n\tfinal class ShortestKGroups implements PatternSelector {\n\n\t\tprivate final int k;\n\n\t\tShortestKGroups(Integer k) {\n\t\t\tthis.k = k;\n\t\t}\n\n\t\tpublic int getK() {\n\t\t\treturn this.k;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/PeriodLiteral.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.time.Period;\n\n/**\n * A literal representing a period value to be formatted in a way that Neo4j's Cypher\n * understands it.\n *\n * @author Michael J. Simons\n * @since 2023.2.1\n */\nfinal class PeriodLiteral extends LiteralBase<Period> {\n\n\tprivate PeriodLiteral(Period content) {\n\t\tsuper(content);\n\t}\n\n\tstatic Literal<Period> of(Period duration) {\n\t\treturn new PeriodLiteral(duration);\n\t}\n\n\t@Override\n\tpublic Period getContent() {\n\t\treturn this.content;\n\t}\n\n\t@Override\n\tpublic String asString() {\n\t\tvar result = new StringBuilder();\n\t\tresult.append(\"duration('P\");\n\n\t\tif (this.content.getYears() != 0) {\n\t\t\tresult.append(this.content.getYears()).append(\"Y\");\n\t\t}\n\t\tif (this.content.getMonths() != 0) {\n\t\t\tresult.append(this.content.getMonths()).append(\"M\");\n\t\t}\n\t\tif (this.content.getDays() != 0) {\n\t\t\tresult.append(this.content.getDays()).append(\"D\");\n\t\t}\n\t\tresult.append(\"')\");\n\t\treturn result.toString();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Predicates.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\n/**\n * Factory methods for creating predicates.\n *\n * @author Michael J. Simons\n * @since 1.0 be accessible.\n */\nfinal class Predicates {\n\n\tprivate Predicates() {\n\t}\n\n\t/**\n\t * Creates a new condition based on a function invocation for the {@code exists()}\n\t * function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-exists\">exists</a>.\n\t * @param property the property to be passed to {@code exists()}\n\t * @return a function call for {@code exists()} for one property\n\t */\n\tstatic Condition exists(Property property) {\n\n\t\treturn new BooleanFunctionCondition(FunctionInvocation.create(BuiltInFunctions.Predicates.EXISTS, property));\n\t}\n\n\t/**\n\t * Creates a new condition based on a function invocation for the {@code exists()}\n\t * function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-exists\">exists</a>.\n\t * @param pattern the pattern to be passed to {@code exists()}\n\t * @return a function call for {@code exists()} for one pattern\n\t */\n\tstatic Condition exists(RelationshipPattern pattern) {\n\n\t\treturn new BooleanFunctionCondition(FunctionInvocation.create(BuiltInFunctions.Predicates.EXISTS, pattern));\n\t}\n\n\t/**\n\t * Creates a new condition via an <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/syntax/expressions/#existential-subqueries\">existential\n\t * sub-query</a>. The statement may or may not have a {@literal  RETURN} clause. It\n\t * must however not contain any updates. While it would render syntactically correct\n\t * Cypher, Neo4j does not support updates inside existential sub-queries.\n\t * @param statement the statement to be passed to {@code exists{}}\n\t * @param imports optional imports to be used in the statement (will be imported with\n\t * {@literal WITH})\n\t * @return an existential sub-query.\n\t * @since 2023.1.0\n\t */\n\tstatic Condition exists(Statement statement, IdentifiableElement... imports) {\n\n\t\treturn ExistentialSubquery.exists(statement, imports);\n\t}\n\n\t/**\n\t * Creates a new condition via an <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/syntax/expressions/#existential-subqueries\">existential\n\t * sub-query</a> based on the list of patterns.\n\t * @param pattern the pattern that must exists\n\t * @return an existential sub-query.\n\t * @since 2023.9.0\n\t */\n\tstatic Condition exists(PatternElement pattern) {\n\n\t\treturn ExistentialSubquery.exists(List.of(pattern), null);\n\t}\n\n\t/**\n\t * Creates a new condition via an <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/syntax/expressions/#existential-subqueries\">existential\n\t * sub-query</a> based on the list of patterns.\n\t * @param pattern the list of patterns that must exists\n\t * @return an existential sub-query.\n\t * @since 2023.9.0\n\t */\n\tstatic Condition exists(List<PatternElement> pattern) {\n\n\t\treturn ExistentialSubquery.exists(pattern, null);\n\t}\n\n\t/**\n\t * Creates a new condition via an <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/syntax/expressions/#existential-subqueries\">existential\n\t * sub-query</a> based on the list of patterns and an optional {@link Where\n\t * where-clause}.\n\t * @param pattern the list of patterns that must exists\n\t * @param where an optional where-clause\n\t * @return an existential sub-query.\n\t * @since 2023.9.0\n\t */\n\tstatic Condition exists(List<PatternElement> pattern, Where where) {\n\n\t\treturn ExistentialSubquery.exists(pattern, where);\n\t}\n\n\t/**\n\t * Creates the {@literal ALL} predicate.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code all()} predicate function\n\t * @since 1.1\n\t * @see #all(SymbolicName)\n\t */\n\tstatic OngoingListBasedPredicateFunction all(String variable) {\n\n\t\treturn all(SymbolicName.of(variable));\n\t}\n\n\t/**\n\t * Starts building a new condition based on a function invocation for the\n\t * {@code all()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-all\">exists</a>.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code all()} predicate function\n\t * @since 1.1\n\t */\n\tstatic OngoingListBasedPredicateFunction all(SymbolicName variable) {\n\n\t\treturn new Builder(BuiltInFunctions.Predicates.ALL, variable);\n\t}\n\n\t/**\n\t * Creates the {@literal ANY} predicate.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code any()} predicate function\n\t * @since 1.1\n\t * @see #any(SymbolicName)\n\t */\n\tstatic OngoingListBasedPredicateFunction any(String variable) {\n\n\t\treturn any(SymbolicName.of(variable));\n\t}\n\n\t/**\n\t * Starts building a new condition based on a function invocation for the\n\t * {@code any()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-any\">exists</a>.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code any()} predicate function\n\t * @since 1.1\n\t */\n\tstatic OngoingListBasedPredicateFunction any(SymbolicName variable) {\n\n\t\treturn new Builder(BuiltInFunctions.Predicates.ANY, variable);\n\t}\n\n\t/**\n\t * Creates the {@literal NONE} predicate.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code none()} predicate function\n\t * @since 1.1\n\t * @see #none(SymbolicName)\n\t */\n\tstatic OngoingListBasedPredicateFunction none(String variable) {\n\n\t\treturn none(SymbolicName.of(variable));\n\t}\n\n\t/**\n\t * Starts building a new condition based on a function invocation for the\n\t * {@code none()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-none\">exists</a>.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code none()} predicate function\n\t * @since 1.1\n\t */\n\tstatic OngoingListBasedPredicateFunction none(SymbolicName variable) {\n\n\t\treturn new Builder(BuiltInFunctions.Predicates.NONE, variable);\n\t}\n\n\t/**\n\t * Creates the {@literal SINGLE} predicate.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code single()} predicate function\n\t * @since 1.1\n\t * @see #single(SymbolicName)\n\t */\n\tstatic OngoingListBasedPredicateFunction single(String variable) {\n\n\t\treturn single(SymbolicName.of(variable));\n\t}\n\n\t/**\n\t * Starts building a new condition based on a function invocation for the\n\t * {@code single()} function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-single\">exists</a>.\n\t * @param variable the variable referring to elements of a list\n\t * @return a builder for the {@code single()} predicate function\n\t * @since 1.1\n\t */\n\tstatic OngoingListBasedPredicateFunction single(SymbolicName variable) {\n\n\t\treturn new Builder(BuiltInFunctions.Predicates.SINGLE, variable);\n\t}\n\n\t/**\n\t * Creates a new condition based on a function invocation for the {@code isEmpty()}\n\t * function. See <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-isempty\">isEmpty</a>.\n\t * <p>\n\t * The argument {@code e} must refer to an expression that evaluates to a list for\n\t * {@code isEmpty()} to work\n\t * @param e an expression referring to a list\n\t * @return a function call for {@code isEmpty()} for a list\n\t * @since 2023.6.1\n\t */\n\tstatic Condition isEmpty(Expression e) {\n\n\t\treturn new BooleanFunctionCondition(FunctionInvocation.create(BuiltInFunctions.Predicates.IS_EMPTY, e));\n\t}\n\n\tprivate static class Builder\n\t\t\timplements OngoingListBasedPredicateFunction, OngoingListBasedPredicateFunctionWithList {\n\n\t\tprivate final BuiltInFunctions.Predicates predicate;\n\n\t\tprivate final SymbolicName name;\n\n\t\tprivate Expression listExpression;\n\n\t\tBuilder(BuiltInFunctions.Predicates predicate, SymbolicName name) {\n\n\t\t\tAssertions.notNull(predicate, \"The predicate is required\");\n\t\t\tAssertions.notNull(name, \"The name is required\");\n\t\t\tthis.predicate = predicate;\n\t\t\tthis.name = name;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingListBasedPredicateFunctionWithList in(Expression list) {\n\n\t\t\tAssertions.notNull(list, \"The list expression is required\");\n\t\t\tthis.listExpression = list;\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic Condition where(Condition condition) {\n\n\t\t\tAssertions.notNull(condition, \"The condition is required\");\n\t\t\treturn new BooleanFunctionCondition(FunctionInvocation.create(this.predicate,\n\t\t\t\t\tnew ListPredicate(this.name, this.listExpression, new Where(condition))));\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ProcedureCall.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/StandaloneCall.html\">StandaloneCall</a>.\n *\n * @author Michael J. Simons\n * @since 2020.0.1\n */\n@API(status = STABLE, since = \"2020.0.1\")\npublic interface ProcedureCall extends Statement, Clause {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ProcedureCallImpl.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.ProcedureName;\nimport org.neo4j.cypherdsl.core.internal.YieldItems;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * An internal implementation of a {@link ProcedureCall} to distinguish between calls that\n * return (\"yield\") a set of things and those who don't.\n *\n * @author Michael J. Simons\n * @since 2021.2.1\n */\n@API(status = INTERNAL, since = \"2021.2.1\")\nclass ProcedureCallImpl extends AbstractStatement implements ProcedureCall {\n\n\tprivate final ProcedureName name;\n\n\tprivate final Arguments arguments;\n\n\tprivate final YieldItems yieldItems;\n\n\tprivate final Where optionalWhere;\n\n\tprivate ProcedureCallImpl(ProcedureName name, Arguments arguments, YieldItems yieldItems, Where optionalWhere) {\n\n\t\tthis.name = name;\n\t\tthis.arguments = (arguments != null) ? arguments : new Arguments();\n\t\tthis.yieldItems = yieldItems;\n\t\tthis.optionalWhere = optionalWhere;\n\t}\n\n\tstatic ProcedureCall create(ProcedureName name, Arguments arguments, YieldItems yieldItems, Where optionalWhere) {\n\n\t\tif (yieldItems != null) {\n\t\t\treturn new ProcedureCallImplWithResult(name, arguments, yieldItems, optionalWhere);\n\t\t}\n\t\telse {\n\t\t\treturn new ProcedureCallImpl(name, arguments, null, optionalWhere);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.name.accept(visitor);\n\t\tVisitable.visitIfNotNull(this.arguments, visitor);\n\t\tVisitable.visitIfNotNull(this.yieldItems, visitor);\n\t\tVisitable.visitIfNotNull(this.optionalWhere, visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\tstatic final class ProcedureCallImplWithResult extends ProcedureCallImpl implements ResultStatement {\n\n\t\tprivate ProcedureCallImplWithResult(ProcedureName name, Arguments arguments, YieldItems yieldItems,\n\t\t\t\tWhere optionalWhere) {\n\t\t\tsuper(name, arguments, yieldItems, optionalWhere);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Properties.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Represents the properties of a {@link Node node} or a {@link Relationship relationship}\n * when used as part of the whole pattern (inside a {@code MATCH}, {@code CREATE} or\n * {@code MERGE} clause as {@code {p1: v1, p2: v2, pn: vn}}.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Properties implements Visitable {\n\n\tprivate final MapExpression value;\n\n\tprivate Properties(MapExpression value) {\n\t\tthis.value = value;\n\t}\n\n\t/**\n\t * Wraps an expression into a {@link Properties} node.\n\t * @param expression nullable expression\n\t * @return a properties expression\n\t */\n\tpublic static Properties create(MapExpression expression) {\n\n\t\treturn (expression != null) ? new Properties(expression) : null;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.value.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Property.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A property. A property might belong to a container such as a {@link Node} or\n * {@link Relationship}, but it's not uncommon to extract single properties from maps or\n * from various datatypes such as a duration returned from stored procedures. The\n * container can be retrieved via {@link #getContainer()} in case the property belongs to\n * a node or relationship.\n * <p>\n * A property has always a reference to the name of the object it was extracted from.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic non-sealed interface Property extends Expression, IdentifiableElement {\n\n\t/**\n\t * Returns the concatenated names of the property or the external reference (See\n\t * {@link #referencedAs(String)}) if set.\n\t * @return a name to reference the property under in an external application\n\t */\n\t@API(status = STABLE, since = \"2021.1.0\")\n\tString getName();\n\n\t/**\n\t * Returns the actual property being looked up. The order matters, so this will return\n\t * a list, not a random collection.\n\t * @return the actual property being looked up\n\t */\n\tList<PropertyLookup> getNames();\n\n\t/**\n\t * {@return the container \"owning\" this property}\n\t */\n\tNamed getContainer();\n\n\t/**\n\t * {@return a reference to the container owning this property}\n\t */\n\t@API(status = INTERNAL, since = \"2023.1.0\")\n\tdefault Expression getContainerReference() {\n\t\tif (getContainer() == null) {\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\t\treturn getContainer().getRequiredSymbolicName();\n\t}\n\n\t/**\n\t * Creates a new property with an external reference.\n\t * @param newReference an arbitrary, external reference\n\t * @return a new property\n\t */\n\t@API(status = STABLE, since = \"2021.1.0\")\n\tProperty referencedAs(String newReference);\n\n\t/**\n\t * Creates an {@link Operation} setting this property to a new value. The property\n\t * does not track the operations created with this method.\n\t * @param expression expression describing the new value\n\t * @return a new operation.\n\t */\n\tOperation to(Expression expression);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/PropertyAccessor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * This interface represents an element that has properties.\n *\n * @author Andreas Berger\n * @author Michael J. Simons\n * @since 2024.1.0\n */\n@API(status = STABLE, since = \"2024.1.0\")\npublic interface PropertyAccessor {\n\n\t/**\n\t * Creates a new {@link Property} associated with this element. This property can be\n\t * used as a lookup in other expressions. It does not add a value to the property.\n\t * <p>\n\t * Note: The element does not track property creation and there is no possibility to\n\t * enumerate all properties that have been created for this property container.\n\t * @param name property name, must not be {@literal null} or empty.\n\t * @return a new {@link Property} associated with this element\n\t */\n\tdefault Property property(String name) {\n\t\treturn property(new String[] { name });\n\t}\n\n\t/**\n\t * Returns a new {@link Property} associated with this element.\n\t * @param names a list of nested property names\n\t * @return a new {@link Property} associated with this element\n\t * @see #property(String)\n\t */\n\tProperty property(String... names);\n\n\t/**\n\t * Creates a new {@link Property} associated with this element. This property can be\n\t * used as a lookup in other expressions. It does not add a value to the property.\n\t * <p>\n\t * The new {@link Property} object is a dynamic lookup, based on the\n\t * {@code expression} passed to this method. The expression can be example another\n\t * property, a function result or a Cypher parameter. A property defined in such a way\n\t * will render as {@code p[expression]}.\n\t * <p>\n\t * Note: The element does not track property creation and there is no possibility to\n\t * enumerate all properties that have been created for this property container.\n\t * @param lookup the expression that is evaluated to lookup this property.\n\t * @return a new {@link Property} associated with this element\n\t */\n\tProperty property(Expression lookup);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/PropertyContainer.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A container having properties. A property container must be {@link Named} with a non\n * empty name to be able to refer to properties.\n *\n * @author Andreas Berger\n * @author Michael J. Simons\n * @since 1.1\n */\n@API(status = STABLE, since = \"1.1\")\npublic interface PropertyContainer extends Named, PropertyAccessor {\n\n\t/**\n\t * Creates an {@link Operation} mutating the properties of this container to a new\n\t * value. The container does not track the operations created with this method.\n\t * @param parameter the new properties\n\t * @return a new operation.\n\t * @since 2020.1.5\n\t */\n\tOperation mutate(Parameter<?> parameter);\n\n\t/**\n\t * Creates an {@link Operation} mutating the properties of this container to a new\n\t * value. The container does not track the operations created with this method.\n\t * @param properties the new properties\n\t * @return a new operation.\n\t * @since 2020.1.5\n\t */\n\tOperation mutate(MapExpression properties);\n\n\t/**\n\t * Creates an {@link Operation SET operation} setting the properties of this container\n\t * to a new value. The container does not track the operations created with this\n\t * method.\n\t * @param parameter the new properties\n\t * @return a new operation.\n\t * @since 2022.5.0\n\t */\n\tOperation set(Parameter<?> parameter);\n\n\t/**\n\t * Creates an {@link Operation SET operation} setting the properties of this container\n\t * to a new value. The container does not track the operations created with this\n\t * method.\n\t * @param properties the new properties\n\t * @return a new operation.\n\t * @since 2022.5.0\n\t */\n\tOperation set(MapExpression properties);\n\n\t/**\n\t * Unwraps the list of entries into an array before creating a projection out of it.\n\t * @param entries a list of entries for the projection\n\t * @return a map projection.\n\t * @see SymbolicName#project(List)\n\t */\n\tMapProjection project(List<Object> entries);\n\n\t/**\n\t * Creates a map projection based on this container. The container needs a symbolic\n\t * name for this to work.\n\t * @param entries a list of entries for the projection\n\t * @return a map projection.\n\t * @see SymbolicName#project(Object...)\n\t */\n\tMapProjection project(Object... entries);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/PropertyLookup.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M14/railroad/PropertyLookup.html\">PropertyLookup</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class PropertyLookup implements Expression {\n\n\tprivate static final PropertyLookup WILDCARD = new PropertyLookup(Asterisk.INSTANCE, false);\n\n\tprivate final Expression propertyKeyName;\n\n\t/** This flag is set to true for dynamic lookups via `p['x']` notation. */\n\tprivate final boolean dynamicLookup;\n\n\tprivate PropertyLookup(Expression propertyKeyName, boolean dynamicLookup) {\n\n\t\tthis.propertyKeyName = propertyKeyName;\n\t\tthis.dynamicLookup = dynamicLookup;\n\t}\n\n\t/**\n\t * This creates a property lookup for a given name. It is mostly usable when building\n\t * an AST outside the fluent API. If you need to create property lookup for a\n\t * {@link SymbolicName symbolic name}, most likely you can just use the symbolic name.\n\t * @param name the name to lookup\n\t * @return a property lookup\n\t * @since 2021.3.0\n\t */\n\tpublic static PropertyLookup forName(String name) {\n\n\t\tAssertions.hasText(name, \"The property's name is required.\");\n\t\treturn new PropertyLookup(SymbolicName.unsafe(name), false);\n\t}\n\n\tstatic PropertyLookup forExpression(Expression expression) {\n\n\t\tAssertions.notNull(expression, \"The expression is required\");\n\t\treturn new PropertyLookup(expression, true);\n\t}\n\n\tstatic PropertyLookup wildcard() {\n\n\t\treturn WILDCARD;\n\t}\n\n\t@API(status = INTERNAL)\n\tSymbolicName getPropertyKeyName() {\n\n\t\tAssertions.isTrue(this != WILDCARD, \"The wildcard property lookup does not reference a specific property!\");\n\t\treturn (SymbolicName) this.propertyKeyName;\n\t}\n\n\t/**\n\t * {@return <code>true</code> if this is a dynamic property}\n\t */\n\t@API(status = INTERNAL)\n\tpublic boolean isDynamicLookup() {\n\t\treturn this.dynamicLookup;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.propertyKeyName.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/QuantifiedPathPattern.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Representation of quantified path patterns.\n *\n * @author Michael J. Simons\n * @since 2023.9.0\n */\n@Neo4jVersion(minimum = \"5.9\")\n@API(status = STABLE, since = \"2023.9.0\")\npublic final class QuantifiedPathPattern implements PatternElement {\n\n\tprivate final TargetPattern delegate;\n\n\tprivate final Quantifier quantifier;\n\n\tprivate QuantifiedPathPattern(TargetPattern delegate, Quantifier quantifier) {\n\t\tthis.delegate = delegate;\n\t\tthis.quantifier = quantifier;\n\t}\n\n\t/**\n\t * Creates an interval quantifier.\n\t * @param lowerBound lower bound, must be greater than or equal to 0\n\t * @param upperBound upper bound, must be greater than or equal to the lower bound\n\t * @return a quantifier\n\t */\n\tpublic static Quantifier interval(Integer lowerBound, Integer upperBound) {\n\n\t\treturn new IntervalQuantifier(lowerBound, upperBound);\n\t}\n\n\t/**\n\t * {@return the <code>+</code> quantifier}\n\t */\n\tpublic static Quantifier plus() {\n\n\t\treturn PlusQuantifier.INSTANCE;\n\t}\n\n\t/**\n\t * {@return the <code>*</code> quantifier}\n\t */\n\tpublic static Quantifier star() {\n\n\t\treturn StarQuantifier.INSTANCE;\n\t}\n\n\tstatic QuantifiedPathPattern of(PatternElement patternElement, Quantifier quantifier) {\n\n\t\tvar delegate = (patternElement instanceof TargetPattern ppp) ? ppp : new TargetPattern(patternElement, null);\n\n\t\treturn new QuantifiedPathPattern(delegate, quantifier);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.delegate.accept(visitor);\n\t\tVisitable.visitIfNotNull(this.quantifier, visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic PatternElement where(Expression predicate) {\n\t\tif (predicate == null) {\n\t\t\treturn this;\n\t\t}\n\t\treturn of(this.delegate.where(predicate), this.quantifier);\n\t}\n\n\t/**\n\t * Specialized quantifier for 1 or more iterations ({@literal +} quantifier).\n\t */\n\t@SuppressWarnings(\"squid:S6548\") // I do like enums as singletons, deal with it,\n\tprivate enum PlusQuantifier implements Quantifier {\n\n\t\tINSTANCE;\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn \"+\";\n\t\t}\n\n\t}\n\n\t/**\n\t * Specialized quantifier for 0 or more iterations ({@literal *} quantifier).\n\t */\n\t@SuppressWarnings(\"squid:S6548\") // I do like enums as singletons, deal with it,\n\tprivate enum StarQuantifier implements Quantifier {\n\n\t\tINSTANCE;\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn \"*\";\n\t\t}\n\n\t}\n\n\t/**\n\t * Quantifier for path patterns.\n\t */\n\tpublic sealed interface Quantifier extends Visitable {\n\n\t}\n\n\t/**\n\t * Synthetic element for the Cypher-DSL AST.\n\t */\n\t@API(status = API.Status.INTERNAL)\n\tpublic static final class TargetPattern implements PatternElement {\n\n\t\tprivate final PatternElement delegate;\n\n\t\tprivate final Where innerPredicate;\n\n\t\tprivate TargetPattern(PatternElement delegate, Where innerPredicate) {\n\t\t\tthis.delegate = delegate;\n\t\t\tthis.innerPredicate = innerPredicate;\n\t\t}\n\n\t\t@Override\n\t\tpublic void accept(Visitor visitor) {\n\n\t\t\tvisitor.enter(this);\n\t\t\tthis.delegate.accept(visitor);\n\t\t\tVisitable.visitIfNotNull(this.innerPredicate, visitor);\n\t\t\tvisitor.leave(this);\n\t\t}\n\n\t\t@Override\n\t\tpublic PatternElement where(Expression predicate) {\n\t\t\tif (predicate == null) {\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\treturn new TargetPattern(this.delegate, Where.from(predicate));\n\t\t}\n\n\t}\n\n\t/**\n\t * Qualifier for an interval.\n\t *\n\t * @param lowerBound the lower bound to use\n\t * @param upperBound the upper bound to use\n\t */\n\tprivate record IntervalQuantifier(Integer lowerBound, Integer upperBound) implements Quantifier {\n\n\t\tpublic IntervalQuantifier {\n\t\t\tif (lowerBound != null && lowerBound < 0) {\n\t\t\t\tthrow new IllegalArgumentException(\"Lower bound must be greater than or equal to zero\");\n\t\t\t}\n\t\t\tif (upperBound != null && upperBound <= 0) {\n\t\t\t\tthrow new IllegalArgumentException(\"Upper bound must be greater than zero\");\n\t\t\t}\n\t\t\tif (lowerBound != null && upperBound != null && upperBound < lowerBound) {\n\t\t\t\tthrow new IllegalArgumentException(\"Upper bound must be greater than or equal to \" + lowerBound);\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\tvar result = \"{\";\n\t\t\tresult += ((lowerBound() == null) ? \"0\" : lowerBound());\n\t\t\tresult += \",\";\n\t\t\tif (upperBound() != null) {\n\t\t\t\tresult += upperBound();\n\t\t\t}\n\t\t\tresult += \"}\";\n\t\t\treturn result;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/QueryDSLAdapter.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport com.querydsl.core.BooleanBuilder;\nimport com.querydsl.core.types.Path;\nimport com.querydsl.core.types.Predicate;\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.build.annotations.RegisterForReflection;\nimport org.neo4j.cypherdsl.core.querydsl.CypherContext;\nimport org.neo4j.cypherdsl.core.querydsl.ToCypherFormatStringVisitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * This is a utility class to turn a several Query-DSL\n * {@link com.querydsl.core.types.Expression expressions} into something the Cypher-DSL\n * can understand. It can only be used when `com.querydsl:querydsl-core` is on the\n * classpath. While we try our best to translate as many expression as possible into\n * syntactically correct Cypher, we don't provide any guarantees that the expressions and\n * conditions generated are semantically correct in the context of the final query\n * generated.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\n@SuppressWarnings(\"unused\")\n@RegisterForReflection(allDeclaredConstructors = true)\nfinal class QueryDSLAdapter implements ForeignAdapter<com.querydsl.core.types.Expression<?>> {\n\n\tprivate final com.querydsl.core.types.Expression<?> expression;\n\n\tQueryDSLAdapter(com.querydsl.core.types.Expression<?> expression) {\n\t\tthis.expression = expression;\n\t}\n\n\t@Override\n\tpublic Condition asCondition() {\n\n\t\tif (!(this.expression instanceof Predicate)) {\n\t\t\tthrow new IllegalArgumentException(\"Only Query-DSL predicates can be turned into Cypher-DSL's predicates.\");\n\t\t}\n\n\t\tif (this.expression instanceof BooleanBuilder booleanBuilder && !booleanBuilder.hasValue()) {\n\t\t\treturn Conditions.noCondition();\n\t\t}\n\n\t\tCypherContext context = new CypherContext();\n\t\tString formatString = this.expression.accept(ToCypherFormatStringVisitor.INSTANCE, context);\n\n\t\treturn new ExpressionCondition(Cypher.raw(formatString, (Object[]) context.getExpressions()));\n\t}\n\n\t@Override\n\tpublic Expression asExpression() {\n\n\t\tCypherContext context = new CypherContext();\n\t\tString formatString = this.expression.accept(ToCypherFormatStringVisitor.INSTANCE, context);\n\n\t\treturn Cypher.raw(formatString, (Object[]) context.getExpressions());\n\t}\n\n\t@Override\n\tpublic Node asNode() {\n\n\t\tif (!(this.expression instanceof Path<?> entityPath)) {\n\t\t\tthrow new IllegalArgumentException(\"Only Query-DSL paths can be turned into nodes.\");\n\t\t}\n\n\t\treturn Cypher.node(entityPath.getRoot().getType().getSimpleName()).named(entityPath.getMetadata().getName());\n\t}\n\n\t@Override\n\tpublic Relationship asRelationship() {\n\n\t\tthrow new UnsupportedOperationException(\"Not yet implemented.\");\n\t}\n\n\t@Override\n\tpublic SymbolicName asName() {\n\n\t\tif (!(this.expression instanceof Path<?> entityPath)) {\n\t\t\tthrow new IllegalArgumentException(\"Only Query-DSL paths can be turned into names.\");\n\t\t}\n\n\t\treturn Cypher.name(entityPath.getMetadata().getName());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/RawLiteral.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport org.apiguardian.api.API;\nimport org.apiguardian.api.API.Status;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\n/**\n * Generates a raw cypher literal. The factory method is able to replace {@code $E}\n * placeholders with expressions passed to it. To use a {@literal $E} escape it as\n * {$literal \\$E}.\n *\n * @author Michael J. Simons\n * @since 2021.0.2\n */\n@API(status = Status.INTERNAL)\nfinal class RawLiteral implements Expression {\n\n\tprivate static final Pattern EXPRESSION_PATTERN = Pattern.compile(\"((\\\\\\\\?\\\\$(\\\\w+))(?:\\\\s*|$))\");\n\n\tprivate static final String EXPRESSION_PLACEHOLDER = \"$E\";\n\n\tprivate final List<Expression> content;\n\n\tRawLiteral(List<Expression> content) {\n\t\tthis.content = content;\n\t}\n\n\tstatic RawLiteral create(String format, Object... mixedArgs) {\n\n\t\tAssertions.hasText(format, \"Cannot create a raw literal without a format.\");\n\n\t\tMap<String, Parameter<?>> parameters = new HashMap<>();\n\t\tList<Object> all = new ArrayList<>();\n\t\tfor (Object mixedArg : mixedArgs) {\n\t\t\tif (mixedArg instanceof Parameter) {\n\t\t\t\tParameter<?> parameter = (Parameter<?>) mixedArg;\n\t\t\t\tif (!parameter.isAnon()) {\n\t\t\t\t\tparameters.put(parameter.getName(), parameter);\n\t\t\t\t}\n\t\t\t}\n\t\t\tall.add(mixedArg);\n\t\t}\n\n\t\tMatcher m;\n\t\tif (!parameters.isEmpty()) {\n\t\t\tm = EXPRESSION_PATTERN.matcher(format);\n\t\t\t// \"Reserve\" all placeholders that match actual parameter names by removing\n\t\t\t// them from the all\n\t\t\t// args list so that they are taken with precedence.\n\t\t\twhile (m.find()) {\n\t\t\t\tif (parameters.containsKey(m.group(3))) {\n\t\t\t\t\tall.remove(parameters.get(m.group(3)));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tList<Expression> content = new ArrayList<>();\n\t\tm = EXPRESSION_PATTERN.matcher(format);\n\t\tint i = 0;\n\t\tint cnt = 0;\n\t\twhile (m.find()) {\n\t\t\tif (EXPRESSION_PLACEHOLDER.equals(m.group(2))) {\n\t\t\t\tcontent.add(new RawElement(format.substring(i, m.start(2))));\n\t\t\t\tif (cnt >= all.size()) {\n\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\t\"Too few arguments for the raw literal format `\" + format + \"`.\");\n\t\t\t\t}\n\t\t\t\tcontent.add(getMixedArg(all.get(cnt++)));\n\t\t\t\ti = m.end(2);\n\t\t\t}\n\t\t\telse if (parameters.containsKey(m.group(3))) {\n\t\t\t\tParameter<?> e = parameters.get(m.group(3));\n\n\t\t\t\tcontent.add(new RawElement(format.substring(i, m.start(2))));\n\t\t\t\tcontent.add(e);\n\t\t\t\ti = m.end(2);\n\n\t\t\t\tall.remove(e);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tcontent.add(new RawElement(format.substring(i, m.end())));\n\t\t\t\ti = m.end();\n\t\t\t}\n\t\t}\n\n\t\tif (cnt < all.size()) {\n\t\t\tthrow new IllegalArgumentException(\"Too many arguments for the raw literal format `\" + format + \"`.\");\n\t\t}\n\n\t\tcontent.add(new RawElement(format.substring(i)));\n\n\t\treturn new RawLiteral(Collections.unmodifiableList(content));\n\t}\n\n\tprivate static Expression getMixedArg(Object argument) {\n\t\tif (argument instanceof Expression expression) {\n\t\t\treturn expression;\n\t\t}\n\t\treturn Cypher.literalOf(argument);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.content.forEach(expression -> expression.accept(visitor));\n\t\tvisitor.leave(this);\n\t}\n\n\tstatic class RawElement extends LiteralBase<String> {\n\n\t\tRawElement(String content) {\n\t\t\tsuper(unescapeEscapedPlaceholders(content));\n\t\t}\n\n\t\tprivate static String unescapeEscapedPlaceholders(String content) {\n\t\t\treturn content.replace(\"\\\\$E\", \"$E\");\n\t\t}\n\n\t\t@Override\n\t\tpublic String asString() {\n\n\t\t\treturn this.content;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ReadingClause.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\n/**\n * A reading clause does not do any updates.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\ninterface ReadingClause extends Clause {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Reduction.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A typed subtree representing the arguments of a call to the {@code reduce()} function.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n * @since 2020.1.5\n * @see Cypher#reduce(SymbolicName)\n */\n@API(status = STABLE, since = \"2020.1.5\")\npublic final class Reduction extends TypedSubtree<Visitable> {\n\n\tprivate Reduction(Visitable... children) {\n\t\tsuper(children);\n\t}\n\n\t/**\n\t * Step 1: Define the variable of the reduction.\n\t * @param variable the closure will have a variable introduced in its context. We\n\t * decide here which variable to use.\n\t * @return an ongoing definition\n\t */\n\tstatic OngoingDefinitionWithVariable of(SymbolicName variable) {\n\n\t\tAssertions.notNull(variable, \"A variable is required\");\n\t\treturn new Builder(variable);\n\t}\n\n\t/**\n\t * Step 2: Define the list.\n\t */\n\tpublic interface OngoingDefinitionWithVariable {\n\n\t\t/**\n\t\t * Returns an ongoing definition.\n\t\t * @param list the list that is the subject of the reduction\n\t\t * @return an ongoing definition\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingDefinitionWithList in(Expression list);\n\n\t}\n\n\t/**\n\t * Step 3: Define the map expression.\n\t */\n\tpublic interface OngoingDefinitionWithList {\n\n\t\t/**\n\t\t * Return an ongoing definition.\n\t\t * @param mapper this expression will run once per value in the list, and produce\n\t\t * the result value.\n\t\t * @return an ongoing definition\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingDefinitionWithReducer map(Expression mapper);\n\n\t}\n\n\t/**\n\t * Step 4a: Define the accumulator.\n\t */\n\tpublic interface OngoingDefinitionWithReducer {\n\n\t\t/**\n\t\t * Return an ongoing definition.\n\t\t * @param accumulator a variable that will hold the result and the partial results\n\t\t * as the list is iterated.\n\t\t * @return an ongoing definition\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingDefinitionWithInitial accumulateOn(Expression accumulator);\n\n\t}\n\n\t/**\n\t * Step 4b: Define the initial value.\n\t */\n\tpublic interface OngoingDefinitionWithInitial {\n\n\t\t/**\n\t\t * Return an ongoing definition.\n\t\t * @param initialValue an expression that runs once to give a starting value to\n\t\t * the accumulator.\n\t\t * @return an ongoing definition\n\t\t */\n\t\tFunctionInvocation withInitialValueOf(Expression initialValue);\n\n\t}\n\n\tprivate static final class Builder implements OngoingDefinitionWithVariable, OngoingDefinitionWithList,\n\t\t\tOngoingDefinitionWithInitial, OngoingDefinitionWithReducer {\n\n\t\tprivate final SymbolicName variable;\n\n\t\tprivate Expression accumulatorExpression;\n\n\t\tprivate Expression listExpression;\n\n\t\tprivate Expression mapExpression;\n\n\t\tprivate Builder(SymbolicName variable) {\n\t\t\tthis.variable = variable;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingDefinitionWithList in(Expression list) {\n\n\t\t\tthis.listExpression = list;\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingDefinitionWithReducer map(Expression mapper) {\n\n\t\t\tthis.mapExpression = mapper;\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic OngoingDefinitionWithInitial accumulateOn(Expression accumulator) {\n\n\t\t\tthis.accumulatorExpression = accumulator;\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic FunctionInvocation withInitialValueOf(Expression initialValue) {\n\n\t\t\tExpression accumulatorAssignment = this.accumulatorExpression.isEqualTo(initialValue);\n\t\t\tReductionPipeline reductionPipeline = new ReductionPipeline(this.variable, this.listExpression,\n\t\t\t\t\tthis.mapExpression);\n\n\t\t\tReduction reduction = new Reduction(accumulatorAssignment, reductionPipeline);\n\t\t\treturn FunctionInvocation.create(BuiltInFunctions.Lists.REDUCE, reduction);\n\t\t}\n\n\t}\n\n\tprivate static final class ReductionPipeline implements Visitable {\n\n\t\tprivate final SymbolicName variable;\n\n\t\tprivate final Expression list;\n\n\t\tprivate final Expression expression;\n\n\t\tReductionPipeline(SymbolicName variable, Expression list, Expression expression) {\n\n\t\t\tthis.variable = variable;\n\t\t\tthis.list = list;\n\t\t\tthis.expression = expression;\n\t\t}\n\n\t\t@Override\n\t\tpublic void accept(Visitor visitor) {\n\t\t\tvisitor.enter(this);\n\t\t\tthis.variable.accept(visitor);\n\t\t\tOperator.IN.accept(visitor);\n\t\t\tthis.list.accept(visitor);\n\t\t\tOperator.PIPE.accept(visitor);\n\t\t\tthis.expression.accept(visitor);\n\t\t\tvisitor.leave(this);\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn RendererBridge.render(this);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Relationship.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Optional;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.RelationshipLength;\nimport org.neo4j.cypherdsl.core.internal.RelationshipTypes;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/RelationshipPattern.html\">RelationshipPattern</a>.\n *\n * @author Michael J. Simons\n * @author Philipp Tölle\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface Relationship extends RelationshipPattern, PropertyContainer, ExposesProperties<Relationship>,\n\t\tExposesPatternLengthAccessors<Relationship> {\n\n\t/**\n\t * {@return the left-hand side of this relationship}\n\t */\n\tNode getLeft();\n\n\t/**\n\t * The details containing the types, properties and cardinality.\n\t * @return a wrapper around the details of this relationship.\n\t */\n\tDetails getDetails();\n\n\t/**\n\t * {@return the right-hand side of this relationship}\n\t */\n\tNode getRight();\n\n\t/**\n\t * {@return the quantifier of this relationship if any}\n\t */\n\tQuantifiedPathPattern.Quantifier getQuantifier();\n\n\t/**\n\t * Creates a copy of this relationship with a new symbolic name.\n\t * @param newSymbolicName the new symbolic name.\n\t * @return the new relationship.\n\t */\n\tRelationship named(String newSymbolicName);\n\n\t/**\n\t * Creates a copy of this relationship with a new symbolic name.\n\t * @param newSymbolicName the new symbolic name.\n\t * @return the new relationship.\n\t */\n\tRelationship named(SymbolicName newSymbolicName);\n\n\t/**\n\t * Creates a new relationship, inverting the direction but keeping the semantics\n\t * intact ({@code (a) --> (b)} becomes {@code (b) <-- (a)}). A symbolic name will be\n\t * removed from this relationship if any, as the it wouldn't be the same pattern to\n\t * match against.\n\t * @return the new relationship\n\t */\n\tRelationship inverse();\n\n\t/**\n\t * While the direction in the schema package is centered around the node, the\n\t * direction here is the direction between two nodes.\n\t *\n\t * @since 1.0\n\t */\n\t@API(status = INTERNAL, since = \"1.0\")\n\tenum Direction {\n\n\t\t/**\n\t\t * Left to right.\n\t\t */\n\t\tLTR(\"-\", \"->\"),\n\t\t/**\n\t\t * Right to left.\n\t\t */\n\t\tRTL(\"<-\", \"-\"),\n\t\t/**\n\t\t * None.\n\t\t */\n\t\tUNI(\"-\", \"-\");\n\n\t\tprivate final String symbolLeft;\n\n\t\tprivate final String symbolRight;\n\n\t\tDirection(String symbolLeft, String symbolRight) {\n\t\t\tthis.symbolLeft = symbolLeft;\n\t\t\tthis.symbolRight = symbolRight;\n\t\t}\n\n\t\t/**\n\t\t * {@return the symbol to render on the left side of the relationship types}\n\t\t */\n\t\t@API(status = INTERNAL)\n\t\tpublic String getSymbolLeft() {\n\t\t\treturn this.symbolLeft;\n\t\t}\n\n\t\t/**\n\t\t * {@return the symbol to render on the right side of the relationship types}\n\t\t */\n\t\t@API(status = INTERNAL)\n\t\tpublic String getSymbolRight() {\n\t\t\treturn this.symbolRight;\n\t\t}\n\n\t}\n\n\t/**\n\t * See <a href=\n\t * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/RelationshipDetail.html\">RelationshipDetail</a>.\n\t */\n\t@API(status = STABLE, since = \"1.0\")\n\tfinal class Details implements Visitable {\n\n\t\t/**\n\t\t * The direction between the nodes of the relationship.\n\t\t */\n\t\tprivate final Direction direction;\n\n\t\tprivate final RelationshipTypes types;\n\n\t\tprivate final RelationshipLength length;\n\n\t\tprivate final Properties properties;\n\n\t\tprivate final Where innerPredicate;\n\n\t\t@SuppressWarnings(\"squid:S3077\") // Symbolic name is unmodifiable\n\t\tprivate volatile SymbolicName symbolicName;\n\n\t\tprivate Details(Direction direction, SymbolicName symbolicName, RelationshipTypes types,\n\t\t\t\tRelationshipLength length, Properties properties, Where innerPredicate) {\n\n\t\t\tthis.direction = Optional.ofNullable(direction).orElse(Direction.UNI);\n\t\t\tthis.symbolicName = symbolicName;\n\t\t\tthis.types = types;\n\t\t\tthis.length = length;\n\t\t\tthis.properties = properties;\n\t\t\tthis.innerPredicate = innerPredicate;\n\t\t}\n\n\t\tstatic Details create(Direction direction, SymbolicName symbolicName, String... types) {\n\n\t\t\tList<String> listOfTypes = Arrays.stream(types).filter(type -> !(type == null || type.isEmpty())).toList();\n\n\t\t\treturn create(direction, symbolicName, listOfTypes.isEmpty() ? null : RelationshipTypes.of(types));\n\t\t}\n\n\t\tstatic Details create(Direction direction, SymbolicName symbolicName, RelationshipTypes types) {\n\n\t\t\treturn new Details(direction, symbolicName, types, null, null, null);\n\t\t}\n\n\t\t/**\n\t\t * Internal helper method indicating whether the details have content or not.\n\t\t * @return true if any of the details are filled\n\t\t */\n\t\tpublic boolean hasContent() {\n\t\t\treturn this.symbolicName != null || this.types != null || this.length != null || this.properties != null;\n\t\t}\n\n\t\tDetails named(SymbolicName newSymbolicName) {\n\n\t\t\tAssertions.notNull(newSymbolicName, \"Symbolic name is required.\");\n\t\t\treturn new Details(this.direction, newSymbolicName, this.types, this.length, this.properties,\n\t\t\t\t\tthis.innerPredicate);\n\t\t}\n\n\t\tDetails with(Properties newProperties) {\n\n\t\t\treturn new Details(this.direction, this.symbolicName, this.types, this.length, newProperties,\n\t\t\t\t\tthis.innerPredicate);\n\t\t}\n\n\t\tDetails unbounded() {\n\n\t\t\treturn new Details(this.direction, this.symbolicName, this.types, RelationshipLength.unbounded(),\n\t\t\t\t\tthis.properties, this.innerPredicate);\n\t\t}\n\n\t\tDetails inverse() {\n\n\t\t\tif (this.direction == Direction.UNI) {\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\treturn new Details((this.direction == Direction.LTR) ? Direction.RTL : Direction.LTR, null, this.types,\n\t\t\t\t\tthis.length, this.properties, this.innerPredicate);\n\t\t}\n\n\t\tDetails where(Expression predicate) {\n\t\t\treturn new Details(this.direction, this.symbolicName, this.types, this.length, this.properties,\n\t\t\t\t\tWhere.from(predicate));\n\t\t}\n\n\t\tDetails min(Integer minimum) {\n\n\t\t\tif (minimum == null && (this.length == null || this.length.getMinimum() == null)) {\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t\tRelationshipLength newLength = Optional.ofNullable(this.length)\n\t\t\t\t.map(l -> RelationshipLength.of(minimum, l.getMaximum()))\n\t\t\t\t.orElseGet(() -> RelationshipLength.of(minimum, null));\n\n\t\t\treturn new Details(this.direction, this.symbolicName, this.types, newLength, this.properties,\n\t\t\t\t\tthis.innerPredicate);\n\t\t}\n\n\t\tDetails max(Integer maximum) {\n\n\t\t\tif (maximum == null && (this.length == null || this.length.getMaximum() == null)) {\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t\tRelationshipLength newLength = Optional.ofNullable(this.length)\n\t\t\t\t.map(l -> RelationshipLength.of(l.getMinimum(), maximum))\n\t\t\t\t.orElseGet(() -> RelationshipLength.of(null, maximum));\n\n\t\t\treturn new Details(this.direction, this.symbolicName, this.types, newLength, this.properties,\n\t\t\t\t\tthis.innerPredicate);\n\t\t}\n\n\t\t/**\n\t\t * {@return the direction of the relationship}\n\t\t */\n\t\t@API(status = INTERNAL)\n\t\tpublic Direction getDirection() {\n\t\t\treturn this.direction;\n\t\t}\n\n\t\tOptional<SymbolicName> getSymbolicName() {\n\t\t\treturn Optional.ofNullable(this.symbolicName);\n\t\t}\n\n\t\tSymbolicName getRequiredSymbolicName() {\n\n\t\t\tSymbolicName requiredSymbolicName = this.symbolicName;\n\t\t\tif (requiredSymbolicName == null) {\n\t\t\t\tsynchronized (this) {\n\t\t\t\t\trequiredSymbolicName = this.symbolicName;\n\t\t\t\t\tif (requiredSymbolicName == null) {\n\t\t\t\t\t\tthis.symbolicName = SymbolicName.unresolved();\n\t\t\t\t\t\trequiredSymbolicName = this.symbolicName;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn requiredSymbolicName;\n\t\t}\n\n\t\t/**\n\t\t * {@return the relationship types being matched}\n\t\t */\n\t\t@API(status = INTERNAL)\n\t\tpublic List<String> getTypes() {\n\t\t\treturn (this.types == null) ? List.of() : List.copyOf(this.types.getValues());\n\t\t}\n\n\t\t/**\n\t\t * {@return the properties of this relationship}\n\t\t */\n\t\t@API(status = INTERNAL)\n\t\tpublic Properties getProperties() {\n\t\t\treturn this.properties;\n\t\t}\n\n\t\t@Override\n\t\tpublic void accept(Visitor visitor) {\n\n\t\t\tvisitor.enter(this);\n\t\t\tVisitable.visitIfNotNull(this.symbolicName, visitor);\n\t\t\tVisitable.visitIfNotNull(this.types, visitor);\n\t\t\tVisitable.visitIfNotNull(this.length, visitor);\n\t\t\tVisitable.visitIfNotNull(this.properties, visitor);\n\t\t\tVisitable.visitIfNotNull(this.innerPredicate, visitor);\n\t\t\tvisitor.leave(this);\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn RendererBridge.render(this);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/RelationshipBase.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Map;\nimport java.util.Optional;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.RelationshipPatternCondition;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * This is the base class for all relationships. It can be used with generics, specifying\n * valid start and end nodes. This is useful when using it as a base class for a static\n * metamodel.\n *\n * @param <S> the type at the start of the relationship\n * @param <E> the type at the pointy end of the relationship\n * @param <SELF> the type of the persistent relationship itself\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = STABLE, since = \"2021.1.0\")\npublic abstract class RelationshipBase<S extends NodeBase<?>, E extends NodeBase<?>, SELF extends RelationshipBase<S, E, SELF>>\n\t\textends AbstractPropertyContainer implements Relationship {\n\n\tfinal Node left;\n\n\tfinal Node right;\n\n\tfinal Details details;\n\n\tfinal QuantifiedPathPattern.Quantifier quantifier;\n\n\t// ------------------------------------------------------------------------\n\t// Public API to be used by the static metamodel.\n\t// Non-final methods are ok to be overwritten.\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Always creates a relationship from start to end (left to right).\n\t * @param start start node\n\t * @param end end node\n\t * @param type type of the relationship\n\t * @param additionalTypes additional types to add to the relationship\n\t */\n\tprotected RelationshipBase(S start, String type, E end, String... additionalTypes) {\n\n\t\tthis(null, start, Direction.LTR, null, end, mergeTypesIfNecessary(type, additionalTypes));\n\t}\n\n\t/**\n\t * Always creates a relationship from start to end (left to right).\n\t * @param symbolicName an optional symbolic name\n\t * @param start start node\n\t * @param properties the properties for the relationship\n\t * @param end end node\n\t * @param type type of the relationship\n\t * @param additionalTypes additional types to be added to the relationship, only\n\t * meaningful when the object is used for querying, when used in a {@code CREATE} or\n\t * {@code MERGE} clause the runtime will throw an exception.\n\t */\n\tprotected RelationshipBase(SymbolicName symbolicName, Node start, String type, Properties properties, Node end,\n\t\t\tString... additionalTypes) {\n\n\t\tthis(symbolicName, start, Direction.LTR, properties, null, end, mergeTypesIfNecessary(type, additionalTypes));\n\t}\n\n\t/**\n\t * Always creates a relationship from start to end (left to right).\n\t * @param symbolicName an optional symbolic name\n\t * @param start start node\n\t * @param properties the properties for the relationship\n\t * @param end end node\n\t * @param type type of the relationship\n\t */\n\tprotected RelationshipBase(SymbolicName symbolicName, String type, Node start, Properties properties, Node end) {\n\t\tthis(symbolicName, start, Direction.LTR, properties, null, end, type);\n\t}\n\n\tRelationshipBase(SymbolicName symbolicName, Node left, Direction direction,\n\t\t\tQuantifiedPathPattern.Quantifier quantifier, Node right, String... types) {\n\n\t\tthis(symbolicName, left, direction, null, quantifier, right, types);\n\t}\n\n\tRelationshipBase(SymbolicName symbolicName, Node left, Direction direction, Properties properties,\n\t\t\tQuantifiedPathPattern.Quantifier quantifier, Node right, String... types) {\n\n\t\tthis(left, Details.create(direction, symbolicName, types).with(properties), quantifier, right);\n\t}\n\n\tRelationshipBase(Node left, Details details, QuantifiedPathPattern.Quantifier quantifier, Node right) {\n\n\t\tAssertions.notNull(left, \"Left node is required.\");\n\t\tAssertions.notNull(details, \"Details are required.\");\n\t\tAssertions.notNull(right, \"Right node is required.\");\n\n\t\tthis.left = left;\n\t\tthis.right = right;\n\t\tthis.details = details;\n\t\tthis.quantifier = quantifier;\n\t}\n\n\tprivate static String[] mergeTypesIfNecessary(String type, String... additionalTypes) {\n\n\t\tif (additionalTypes != null && additionalTypes.length > 0) {\n\t\t\tString[] result = new String[1 + additionalTypes.length];\n\t\t\tresult[0] = type;\n\t\t\tSystem.arraycopy(additionalTypes, 0, result, 1, additionalTypes.length);\n\t\t\treturn result;\n\t\t}\n\t\treturn new String[] { type };\n\t}\n\n\t@Override\n\tpublic final SELF named(String newSymbolicName) {\n\n\t\tAssertions.hasText(newSymbolicName, \"Symbolic name is required.\");\n\t\treturn named(SymbolicName.of(newSymbolicName));\n\t}\n\n\t/**\n\t * This method needs to be implemented to provide new, type safe instances of this\n\t * relationship.\n\t * @param newSymbolicName the new symbolic name.\n\t * @return a new relationship\n\t */\n\t@Override\n\tpublic abstract SELF named(SymbolicName newSymbolicName);\n\n\t@Override\n\tpublic final SELF withProperties(Object... keysAndValues) {\n\n\t\tMapExpression newProperties = null;\n\t\tif (keysAndValues != null && keysAndValues.length != 0) {\n\t\t\tnewProperties = MapExpression.create(false, keysAndValues);\n\t\t}\n\t\treturn withProperties(newProperties);\n\t}\n\n\t@Override\n\tpublic final SELF withProperties(Map<String, Object> newProperties) {\n\n\t\treturn withProperties(MapExpression.create(newProperties));\n\t}\n\n\t/**\n\t * This method needs to be implemented to provide new, type safe instances of this\n\t * relationship.\n\t * @param newProperties the new properties (can be {@literal null} to remove exiting\n\t * properties).\n\t * @return a new relationship\n\t */\n\t@Override\n\tpublic abstract SELF withProperties(MapExpression newProperties);\n\n\t@Override\n\tpublic final Node getLeft() {\n\t\treturn this.left;\n\t}\n\n\t@Override\n\tpublic final Node getRight() {\n\t\treturn this.right;\n\t}\n\n\t@Override\n\tpublic final QuantifiedPathPattern.Quantifier getQuantifier() {\n\t\treturn this.quantifier;\n\t}\n\n\t@Override\n\tpublic final Details getDetails() {\n\t\treturn this.details;\n\t}\n\n\t@Override\n\tpublic final Relationship unbounded() {\n\n\t\treturn new InternalRelationshipImpl(this.left, this.details.unbounded(), this.quantifier, this.right);\n\t}\n\n\t@Override\n\tpublic final Relationship min(Integer minimum) {\n\n\t\treturn new InternalRelationshipImpl(this.left, this.details.min(minimum), this.quantifier, this.right);\n\t}\n\n\t@Override\n\tpublic final Relationship max(Integer maximum) {\n\n\t\treturn new InternalRelationshipImpl(this.left, this.details.max(maximum), this.quantifier, this.right);\n\t}\n\n\t@Override\n\tpublic final Relationship length(Integer minimum, Integer maximum) {\n\n\t\treturn new InternalRelationshipImpl(this.left, this.details.min(minimum).max(maximum), this.quantifier,\n\t\t\t\tthis.right);\n\t}\n\n\t@Override\n\tpublic final Relationship inverse() {\n\n\t\treturn new InternalRelationshipImpl(this.right, this.details.inverse(), this.quantifier, this.left);\n\t}\n\n\t@Override\n\tpublic final Optional<SymbolicName> getSymbolicName() {\n\t\treturn this.details.getSymbolicName();\n\t}\n\n\t@Override\n\tpublic final SymbolicName getRequiredSymbolicName() {\n\t\treturn this.details.getRequiredSymbolicName();\n\t}\n\n\t@Override\n\tpublic final RelationshipChain relationshipTo(Node other, String... types) {\n\t\treturn RelationshipChain.create(this).add(this.right.relationshipTo(other, types));\n\t}\n\n\t// ------------------------------------------------------------------------\n\t// Internal API.\n\t// ------------------------------------------------------------------------\n\n\t@Override\n\tpublic final RelationshipChain relationshipFrom(Node other, String... types) {\n\t\treturn RelationshipChain.create(this).add(this.right.relationshipFrom(other, types));\n\t}\n\n\t@Override\n\tpublic final RelationshipChain relationshipBetween(Node other, String... types) {\n\t\treturn RelationshipChain.create(this).add(this.right.relationshipBetween(other, types));\n\t}\n\n\t@Override\n\tpublic final Condition asCondition() {\n\t\treturn RelationshipPatternCondition.of(this);\n\t}\n\n\t@Override\n\tpublic final void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\n\t\tthis.left.accept(visitor);\n\t\tthis.details.accept(visitor);\n\t\tVisitable.visitIfNotNull(this.quantifier, visitor);\n\t\tthis.right.accept(visitor);\n\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n\t@Override\n\tpublic Relationship where(Expression predicate) {\n\t\tif (predicate == null) {\n\t\t\treturn this;\n\t\t}\n\t\treturn new InternalRelationshipImpl(this.left, this.details.where(predicate), this.quantifier, this.right);\n\t}\n\n\t@Override\n\tpublic RelationshipPattern quantifyRelationship(QuantifiedPathPattern.Quantifier newQuantifier) {\n\t\tif (newQuantifier == null) {\n\t\t\treturn this;\n\t\t}\n\n\t\treturn new InternalRelationshipImpl(this.left, this.details, newQuantifier, this.right);\n\t}\n\n\t@Override\n\tpublic QuantifiedPathPattern quantify(QuantifiedPathPattern.Quantifier newQuantifier) {\n\n\t\treturn QuantifiedPathPattern.of(this, newQuantifier);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/RelationshipChain.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.RelationshipPatternCondition;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Represents a chain of relationships. The chain is meant to be in order and the right\n * node of an element is related to the left node of the next element.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class RelationshipChain implements RelationshipPattern, ExposesPatternLengthAccessors<RelationshipChain> {\n\n\tprivate final LinkedList<Relationship> relationships;\n\n\tprivate RelationshipChain(Relationship firstElement) {\n\t\tthis.relationships = new LinkedList<>();\n\t\tthis.relationships.add(firstElement);\n\t}\n\n\tprivate RelationshipChain(List<Relationship> firstElements, Relationship lastElement) {\n\t\tthis.relationships = new LinkedList<>(firstElements);\n\t\tthis.relationships.add(lastElement);\n\t}\n\n\tprivate RelationshipChain(List<Relationship> elements) {\n\t\tthis.relationships = new LinkedList<>(elements);\n\t}\n\n\tstatic RelationshipChain create(Relationship firstElement) {\n\n\t\treturn new RelationshipChain(firstElement);\n\t}\n\n\tRelationshipChain add(Relationship element) {\n\n\t\tAssertions.notNull(element, \"Elements of a relationship chain must not be null.\");\n\t\treturn new RelationshipChain(this.relationships, element);\n\t}\n\n\tRelationshipChain replaceLast(Relationship element) {\n\n\t\tAssertions.notNull(element, \"Elements of a relationship chain must not be null.\");\n\t\tRelationshipChain newChain = new RelationshipChain(this.relationships);\n\t\tnewChain.relationships.removeLast();\n\t\tnewChain.relationships.add(element);\n\t\treturn newChain;\n\t}\n\n\t@Override\n\tpublic RelationshipChain relationshipTo(Node other, String... types) {\n\t\treturn this.add(this.relationships.getLast().getRight().relationshipTo(other, types));\n\t}\n\n\t@Override\n\tpublic RelationshipChain relationshipFrom(Node other, String... types) {\n\t\treturn this.add(this.relationships.getLast().getRight().relationshipFrom(other, types));\n\t}\n\n\t@Override\n\tpublic RelationshipChain relationshipBetween(Node other, String... types) {\n\t\treturn this.add(this.relationships.getLast().getRight().relationshipBetween(other, types));\n\t}\n\n\t/**\n\t * Replaces the last element of this chains with a copy of the relationship with the\n\t * new symbolic name.\n\t * @param newSymbolicName the new symbolic name to use\n\t * @return a new chain\n\t */\n\t@Override\n\tpublic RelationshipChain named(String newSymbolicName) {\n\n\t\tRelationship lastElement = this.relationships.getLast();\n\t\treturn this.replaceLast(lastElement.named(newSymbolicName));\n\t}\n\n\t/**\n\t * Replaces the last element of this chains with a copy of the relationship with the\n\t * new symbolic name.\n\t * @param newSymbolicName the new symbolic name to use\n\t * @return a new chain\n\t * @since 2021.1.1\n\t */\n\t@Override\n\tpublic RelationshipChain named(SymbolicName newSymbolicName) {\n\n\t\tRelationship lastElement = this.relationships.getLast();\n\t\treturn this.replaceLast(lastElement.named(newSymbolicName));\n\t}\n\n\t@Override\n\tpublic RelationshipChain where(Expression predicate) {\n\n\t\tif (predicate == null) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar lastElement = this.relationships.getLast();\n\t\treturn this.replaceLast((Relationship) lastElement.where(predicate));\n\t}\n\n\t@Override\n\tpublic RelationshipPattern quantifyRelationship(QuantifiedPathPattern.Quantifier quantifier) {\n\n\t\tif (quantifier == null) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar lastElement = this.relationships.getLast();\n\t\treturn this.replaceLast((Relationship) lastElement.quantifyRelationship(quantifier));\n\t}\n\n\t@Override\n\tpublic QuantifiedPathPattern quantify(QuantifiedPathPattern.Quantifier newQuantifier) {\n\n\t\treturn QuantifiedPathPattern.of(this, newQuantifier);\n\t}\n\n\t/**\n\t * Changes the length of the last element of this chain to an unbounded pattern.\n\t * @return a new chain\n\t * @since 1.1.1\n\t */\n\t@Override\n\tpublic RelationshipChain unbounded() {\n\n\t\tRelationship lastElement = this.relationships.getLast();\n\t\treturn this.replaceLast(lastElement.unbounded());\n\t}\n\n\t/**\n\t * Changes the length of the last element of this chain to a new minimum length.\n\t * @param minimum the new minimum\n\t * @return a new chain\n\t */\n\t@Override\n\tpublic RelationshipChain min(Integer minimum) {\n\n\t\tRelationship lastElement = this.relationships.getLast();\n\t\treturn this.replaceLast(lastElement.min(minimum));\n\t}\n\n\t/**\n\t * Changes the length of the last element of this chain to a new maximum length.\n\t * @param maximum the new maximum\n\t * @return a new chain\n\t */\n\t@Override\n\tpublic RelationshipChain max(Integer maximum) {\n\n\t\tRelationship lastElement = this.relationships.getLast();\n\t\treturn this.replaceLast(lastElement.max(maximum));\n\t}\n\n\t/**\n\t * Changes the length of the last element of this chain.\n\t * @param minimum the new minimum\n\t * @param maximum the new maximum\n\t * @return a new chain\n\t */\n\t@Override\n\tpublic RelationshipChain length(Integer minimum, Integer maximum) {\n\n\t\tRelationship lastElement = this.relationships.getLast();\n\t\treturn this.replaceLast(lastElement.length(minimum, maximum));\n\t}\n\n\t/**\n\t * Adds properties to the last element of this chain.\n\t * @param newProperties the new properties (can be {@literal null} to remove exiting\n\t * properties).\n\t * @return a new chain\n\t */\n\tpublic RelationshipChain properties(MapExpression newProperties) {\n\n\t\tRelationship lastElement = this.relationships.getLast();\n\t\treturn this.replaceLast(lastElement.withProperties(newProperties));\n\t}\n\n\t/**\n\t * Adds properties to the last element of this chain.\n\t * @param keysAndValues a list of key and values. Must be an even number, with\n\t * alternating {@link String} and {@link Expression}.\n\t * @return a new chain\n\t */\n\tpublic RelationshipChain properties(Object... keysAndValues) {\n\n\t\tRelationship lastElement = this.relationships.getLast();\n\t\treturn this.replaceLast(lastElement.withProperties(keysAndValues));\n\t}\n\n\t@Override\n\tpublic Condition asCondition() {\n\t\treturn RelationshipPatternCondition.of(this);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\n\t\tNode lastNode = null;\n\t\tfor (Relationship relationship : this.relationships) {\n\n\t\t\tvisitor.enter(relationship);\n\t\t\trelationship.getLeft().accept(visitor);\n\t\t\trelationship.getDetails().accept(visitor);\n\t\t\tVisitable.visitIfNotNull(relationship.getQuantifier(), visitor);\n\t\t\tvisitor.leave(relationship);\n\n\t\t\tlastNode = relationship.getRight();\n\t\t}\n\n\t\tVisitable.visitIfNotNull(lastNode, visitor);\n\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/RelationshipPattern.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A shared, public interface for {@link Relationship relationships} and\n * {@link RelationshipChain chains of relationships}. This interface reassembles the\n * <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/RelationshipPattern.html\">RelationshipPattern</a>.\n * <p>\n * This interface can be used synonymous with the concept of a <a href=\n * \"https://neo4j.com/docs/cypher-manual/4.0/clauses/where/#query-where-patterns\">Path\n * Pattern</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface RelationshipPattern extends PatternElement, ExposesRelationships<RelationshipChain> {\n\n\t/**\n\t * Turns the pattern into a named chain of relationships.\n\t * @param name the name to be used.\n\t * @return a named relationship that can be chained with more relationship\n\t * definitions.\n\t */\n\t@CheckReturnValue\n\tExposesRelationships<RelationshipChain> named(String name);\n\n\t/**\n\t * Turns the pattern into a named chain of relationships.\n\t * @param name the name to be used.\n\t * @return a named relationship that can be chained with more relationship\n\t * definitions.\n\t */\n\t@CheckReturnValue\n\tExposesRelationships<RelationshipChain> named(SymbolicName name);\n\n\t/**\n\t * Transform this pattern into a condition. All names of the patterns must be known\n\t * upfront in the final statement, as PatternExpressions are not allowed to introduce\n\t * new variables.\n\t * @return a condition based on this pattern.\n\t * @since 2021.0.0\n\t */\n\tCondition asCondition();\n\n\t/**\n\t * Quantifies the relationship.\n\t * @param quantifier the quantifier to use\n\t * @return a quantified relationship\n\t * @since 2023.9.0\n\t */\n\tdefault PatternElement quantifyRelationship(QuantifiedPathPattern.Quantifier quantifier) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t/**\n\t * Quantifies the pattern.\n\t * @param quantifier the quantifier to use\n\t * @return a quantified path pattern\n\t * @since 2023.9.0\n\t */\n\tdefault PatternElement quantify(QuantifiedPathPattern.Quantifier quantifier) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Remove.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Remove.html\">Remove</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Remove extends AbstractClause implements UpdatingClause {\n\n\tprivate final ExpressionList setItems;\n\n\tRemove(ExpressionList setItems) {\n\t\tthis.setItems = setItems;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.setItems.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/RendererBridge.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Dialect;\nimport org.neo4j.cypherdsl.core.renderer.GeneralizedRenderer;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\n/**\n * A bridge to the renderer as a single entry point from core to the renderer\n * infrastructure.\n *\n * @author Michael J. Simons\n * @since 2023.1.0\n */\nfinal class RendererBridge {\n\n\tprivate static final Configuration CONFIGURATION = Configuration.newConfig()\n\t\t.withDialect(Dialect.NEO4J_5_DEFAULT_CYPHER)\n\t\t.alwaysEscapeNames(false)\n\t\t.build();\n\n\tprivate RendererBridge() {\n\t}\n\n\tstatic String render(Visitable visitable) {\n\t\tString name;\n\t\tClass<? extends Visitable> clazz = visitable.getClass();\n\t\tif (clazz.isAnonymousClass()) {\n\t\t\tname = clazz.getName();\n\t\t}\n\t\telse {\n\t\t\tname = clazz.getSimpleName();\n\t\t}\n\t\treturn \"%s{cypher=%s}\".formatted(name,\n\t\t\t\tRenderer.getRenderer(CONFIGURATION, GeneralizedRenderer.class).render(visitable));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ResultStatement.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A statement that returns items from the graph. The shape of those items can be pretty\n * much anything: A list of records containing only properties, or nodes with properties\n * mixed with relationships and so on. The only guarantee given is that the query will\n * return some data when executed.\n *\n * @author Michael J. Simons\n * @since 2021.2.1\n */\n@API(status = STABLE, since = \"2021.2.1\")\npublic interface ResultStatement extends Statement {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Return.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.DefaultStatementBuilder.OrderBuilder;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.Distinct;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Return.html\">Return</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Return implements Clause {\n\n\tprivate final Distinct distinct;\n\n\tprivate final ReturnBody body;\n\n\tprivate final boolean raw;\n\n\tprivate Return(boolean raw, boolean distinct, ExpressionList returnItems, Order order, Skip skip, Limit limit) {\n\t\tthis.distinct = (!raw && distinct) ? Distinct.INSTANCE : null;\n\t\tthis.body = new ReturnBody(returnItems, order, skip, limit);\n\t\tthis.raw = raw;\n\t}\n\n\tstatic Return create(boolean raw, boolean distinct, List<Expression> returnList, OrderBuilder orderBuilder) {\n\n\t\tif (returnList.isEmpty()) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (raw) {\n\t\t\tString message = \"A raw return must consist of exactly one raw expression.\";\n\t\t\tAssertions.isTrue(returnList.size() == 1, message);\n\t\t\tExpression firstExpression = returnList.get(0);\n\t\t\tAssertions.isTrue(firstExpression instanceof RawLiteral\n\t\t\t\t\t|| firstExpression instanceof AliasedExpression ae && ae.getDelegate() instanceof RawLiteral,\n\t\t\t\t\tmessage);\n\t\t}\n\n\t\tExpressionList returnItems = new ExpressionList(returnList);\n\t\treturn new Return(raw, distinct, returnItems, orderBuilder.buildOrder().orElse(null), orderBuilder.getSkip(),\n\t\t\t\torderBuilder.getLimit());\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tVisitable.visitIfNotNull(this.distinct, visitor);\n\t\tthis.body.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t/**\n\t * {@return true if this clause has been created with proper, literal Cypher in place}\n\t */\n\t@API(status = INTERNAL)\n\tpublic boolean isRaw() {\n\t\treturn this.raw;\n\t}\n\n\tDistinct getDistinct() {\n\t\treturn this.distinct;\n\t}\n\n\tReturnBody getBody() {\n\t\treturn this.body;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ReturnBody.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * The container or \"body\" for return items, order and optional skip and things. See\n * <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/ReturnBody.html\">ReturnBody</a>\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class ReturnBody implements Visitable {\n\n\tprivate final ExpressionList returnItems;\n\n\tprivate final Order order;\n\n\tprivate final Skip skip;\n\n\tprivate final Limit limit;\n\n\tReturnBody(ExpressionList returnItems, Order order, Skip skip, Limit limit) {\n\t\tthis.returnItems = returnItems;\n\t\tthis.order = order;\n\t\tthis.skip = skip;\n\t\tthis.limit = limit;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.returnItems.accept(visitor);\n\t\tVisitable.visitIfNotNull(this.order, visitor);\n\t\tVisitable.visitIfNotNull(this.skip, visitor);\n\t\tVisitable.visitIfNotNull(this.limit, visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@API(status = INTERNAL)\n\tList<Expression> getReturnItems() {\n\t\treturn this.returnItems.getChildren();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Set.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Set.html\">Set</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Set extends AbstractClause implements UpdatingClause {\n\n\tprivate final ExpressionList setItems;\n\n\tSet(ExpressionList setItems) {\n\t\tthis.setItems = setItems;\n\t}\n\n\t/**\n\t * Creates a {@literal SET} clause based on the given updates. No runtime checks are\n\t * whether those expressions are actually updates. Please be mindful here.\n\t * @param update the update to apply\n\t * @param more additional updates\n\t * @return a {@link Set} clause\n\t * @since 2023.4.0\n\t */\n\tstatic Set set(Expression update, Expression... more) {\n\n\t\tif (more == null || more.length == 0) {\n\t\t\treturn new Set(new ExpressionList(List.of(update)));\n\t\t}\n\n\t\tList<Expression> finalExpressionList = new ArrayList<>();\n\t\tfinalExpressionList.add(update);\n\t\tCollections.addAll(finalExpressionList, more);\n\n\t\treturn new Set(new ExpressionList(finalExpressionList));\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.setItems.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/SinglePartQuery.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Statement.SingleQuery;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/SinglePartQuery.html\">SinglePartQuery</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = INTERNAL, since = \"1.0\")\nclass SinglePartQuery extends AbstractStatement implements SingleQuery {\n\n\tprivate final List<Visitable> precedingClauses;\n\n\tprivate SinglePartQuery(List<Visitable> precedingClauses) {\n\n\t\tthis.precedingClauses = new ArrayList<>(precedingClauses);\n\t}\n\n\tstatic SinglePartQuery create(List<Visitable> precedingClauses, Clause returnOrFinish) {\n\n\t\tif (precedingClauses.isEmpty() || precedingClauses.get(precedingClauses.size() - 1) instanceof Match) {\n\t\t\tAssertions.notNull(returnOrFinish, \"A returning or finishing clause is required.\");\n\t\t}\n\n\t\tif (returnOrFinish == null) {\n\t\t\tif (precedingClauses.get(precedingClauses.size() - 1) instanceof ResultStatement) {\n\t\t\t\treturn new SinglePartQueryAsResultStatementWrapper(precedingClauses);\n\t\t\t}\n\t\t\treturn new SinglePartQuery(precedingClauses);\n\t\t}\n\t\telse {\n\t\t\treturn new SinglePartQueryWithFinishingClause(precedingClauses, returnOrFinish);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.precedingClauses.forEach(c -> c.accept(visitor));\n\t\tvisitor.leave(this);\n\t}\n\n\tstatic final class SinglePartQueryAsResultStatementWrapper extends SinglePartQuery implements ResultStatement {\n\n\t\tprivate SinglePartQueryAsResultStatementWrapper(List<Visitable> precedingClauses) {\n\t\t\tsuper(precedingClauses);\n\t\t}\n\n\t}\n\n\tstatic final class SinglePartQueryWithFinishingClause extends SinglePartQuery implements ResultStatement {\n\n\t\tprivate final Clause finishingClause;\n\n\t\tprivate SinglePartQueryWithFinishingClause(List<Visitable> precedingClauses, Clause finishingClause) {\n\t\t\tsuper(precedingClauses);\n\n\t\t\tthis.finishingClause = finishingClause;\n\t\t}\n\n\t\t@Override\n\t\tpublic void accept(Visitor visitor) {\n\t\t\tvisitor.enter(this);\n\t\t\tsuper.precedingClauses.forEach(c -> c.accept(visitor));\n\t\t\tthis.finishingClause.accept(visitor);\n\t\t\tvisitor.leave(this);\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn RendererBridge.render(this);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Skip.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Representation of the {@code SKIP} clause.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Skip implements Visitable {\n\n\tprivate final Expression expression;\n\n\tprivate Skip(Expression expression) {\n\t\tthis.expression = expression;\n\t}\n\n\tstatic Skip create(Expression expression) {\n\n\t\tAssertions.notNull(expression, \"Cannot skip a value of null.\");\n\n\t\treturn new Skip(expression);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.expression.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/SortItem.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Optional;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A sort item can be used in an {@code ORDER BY} clause and changes the order of the\n * items being returned from a query.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class SortItem implements Visitable {\n\n\tprivate final Expression expression;\n\n\tprivate final Direction direction;\n\n\tprivate SortItem(Expression expression, Direction direction) {\n\t\tthis.expression = expression;\n\t\tthis.direction = direction;\n\t}\n\n\tstatic SortItem create(Expression expression, Direction direction) {\n\n\t\tAssertions.notNull(expression, \"Expression to sort must not be null.\");\n\t\treturn new SortItem(expression, Optional.ofNullable(direction).orElse(SortItem.Direction.UNDEFINED));\n\t}\n\n\t/**\n\t * Creates a new sort item from {@literal this} instance, setting the sort direction\n\t * to ascending.\n\t * @return a new sort item.\n\t */\n\tpublic SortItem ascending() {\n\t\treturn new SortItem(this.expression, Direction.ASC);\n\t}\n\n\t/**\n\t * Creates a new sort item from {@literal this} instance, setting the sort direction\n\t * to descending.\n\t * @return a new sort item.\n\t */\n\tpublic SortItem descending() {\n\t\treturn new SortItem(this.expression, Direction.DESC);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tExpressions.nameOrExpression(this.expression).accept(visitor);\n\n\t\tif (this.direction != Direction.UNDEFINED) {\n\t\t\tthis.direction.accept(visitor);\n\t\t}\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n\t/**\n\t * Sort direction.\n\t *\n\t * @since 1.0\n\t */\n\t@API(status = STABLE)\n\tpublic enum Direction implements Visitable {\n\n\t\t/** Undefined direction. */\n\t\tUNDEFINED(\"\"),\n\t\t/** Ascending order. */\n\t\tASC(\"ASC\"),\n\t\t/** Descending order. */\n\t\tDESC(\"DESC\");\n\n\t\tprivate final String symbol;\n\n\t\tDirection(String symbol) {\n\t\t\tthis.symbol = symbol;\n\t\t}\n\n\t\t/**\n\t\t * {@return the database internal symbol for a direction}\n\t\t */\n\t\tpublic String getSymbol() {\n\t\t\treturn this.symbol;\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn RendererBridge.render(this);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Statement.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.StatementBuilder.OngoingStandaloneCallWithoutArguments;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.internal.LoadCSV;\nimport org.neo4j.cypherdsl.core.internal.ProcedureName;\nimport org.neo4j.cypherdsl.core.internal.UsingPeriodicCommit;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Shall be the common interfaces for queries that we support.\n * <p>\n * For reference see: <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Cypher.html\">Cypher</a>.\n * We have skipped the intermediate \"Query\" structure so a statement in the context of\n * this generator is either a {@link RegularQuery} or a {@code StandaloneCall}.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface Statement extends Visitable {\n\n\t/**\n\t * {@return a new statement builder}\n\t */\n\tstatic StatementBuilder builder() {\n\n\t\treturn new DefaultStatementBuilder();\n\t}\n\n\t/**\n\t * Creates a statement based on a list of {@link Clause clauses}. It is your task to\n\t * provide a sanity check of the clauses. The builder will use the clauses \"as is\",\n\t * neither change their order nor their type.\n\t * @param clauses a list of clauses, must not be null\n\t * @return a statement\n\t * @since 2021.3.0\n\t */\n\tstatic Statement of(List<Clause> clauses) {\n\n\t\tAssertions.notNull(clauses, \"Clauses must not be null.\");\n\t\treturn new ClausesBasedStatement(clauses, null);\n\t}\n\n\t/**\n\t * Creates a statement based on a list of {@link Clause clauses} and prepends it with\n\t * {@literal USING PERIODIC COMMIT}. It is your task to provide a sanity check of the\n\t * clauses. The builder will use the clauses \"as is\", neither change their order nor\n\t * their type.\n\t * <p>\n\t * The {@literal USING PERIODIC HINT} is only valid right before the\n\t * {@literal LOAD CSV clause}.\n\t * @param batchSize the batch size to pass to {@literal PERIODIC COMMIT}.\n\t * @param clauses a list of clauses, must not be null\n\t * @return a statement\n\t * @since 2021.3.0\n\t */\n\t@API(status = STABLE, since = \"2021.3.0\")\n\tstatic Statement usingPeriodic(Integer batchSize, List<Clause> clauses) {\n\n\t\tAssertions.notNull(clauses, \"Clauses must not be null.\");\n\t\tAssertions.isTrue(!clauses.isEmpty(), \"Clauses must not be empty.\");\n\t\tAssertions.isInstanceOf(LoadCSV.class, clauses.get(0), \"First clause must be a LOAD CSV clause.\");\n\t\treturn new ClausesBasedStatement(clauses, new UsingPeriodicCommit(batchSize));\n\t}\n\n\t/**\n\t * Returns an entry point into a statement that starts with a call to stored *\n\t * procedure.\n\t * @param namespaceAndProcedure the fully qualified name of a stored procedure. Each\n\t * part can be given as a separate String, but a fully qualified String is ok as well.\n\t * @return an entry point into a statement that starts with a call to stored procedure\n\t */\n\tstatic OngoingStandaloneCallWithoutArguments call(String... namespaceAndProcedure) {\n\n\t\treturn new DefaultStatementBuilder.StandaloneCallBuilder(ProcedureName.from(namespaceAndProcedure));\n\t}\n\n\t/**\n\t * Analyzes the statement and provides access to the resolved properties, their\n\t * (potential) owners and the context in which they have been resolved. Identifiable\n\t * expressions may be retrieved via\n\t * {@link StatementCatalog#getIdentifiableExpressions()}.\n\t * @return an immutable object representing properties resolved in a statement\n\t * together with their context and owner\n\t * @since 2023.1.0\n\t */\n\tStatementCatalog getCatalog();\n\n\t/**\n\t * This method uses the default renderer to create a String representation of this\n\t * statement. The generated Cypher will use escaped literals and correct placeholders\n\t * like {@code $param} for parameters. The placeholders for parameters can be\n\t * retrieved via {@link StatementCatalog#getParameterNames}. Bounded values for\n\t * parameters can be retrieved via {@link StatementCatalog#getParameters()}.\n\t * <p>\n\t * This method is thread safe.\n\t * @return a valid Cypher statement\n\t * @since 2021.0.0\n\t */\n\tString getCypher();\n\n\t/**\n\t * {@return the context of this statement, allowing access to parameter names etc}\n\t */\n\t@API(status = INTERNAL, since = \"2021.0.0\")\n\tStatementContext getContext();\n\n\t/**\n\t * Some constants may be rendered as parameters.\n\t * @return true if literal parameters hav\n\t */\n\tboolean isRenderConstantsAsParameters();\n\n\t/**\n\t * Use this method to configure whether some constant values should be rendered as\n\t * parameters or as literals before the first call to\n\t * {@link StatementCatalog#getParameters()} or {@link Statement#getCypher()}.\n\t * <p>\n\t * Renderers are free to chose to ignore this.\n\t * @param renderConstantsAsParameters set to true to render constants as parameters\n\t * (when using {@link #getCypher()}.\n\t */\n\tvoid setRenderConstantsAsParameters(boolean renderConstantsAsParameters);\n\n\t/**\n\t * {@return true if this statement can be assured to return something}\n\t */\n\tdefault boolean doesReturnOrYield() {\n\t\treturn this instanceof ResultStatement || this instanceof UnionQueryImpl;\n\t}\n\n\t/**\n\t * Represents {@code RegularQuery}.\n\t *\n\t * @since 1.0\n\t */\n\tinterface RegularQuery extends Statement {\n\n\t}\n\n\t/**\n\t * Represents a {@code SingleQuery}.\n\t *\n\t * @since 1.0\n\t */\n\tinterface SingleQuery extends RegularQuery {\n\n\t}\n\n\t/**\n\t * Represents a {@code UnionQuery}.\n\t *\n\t * @since 2023.0.0\n\t */\n\tsealed interface UnionQuery extends RegularQuery permits UnionQueryImpl {\n\n\t}\n\n\t/**\n\t * Represents a {@code USE} statement, utilizing a composite graph call. A statement\n\t * utilizing composite databases might use an {@code EXPLAIN} clause but cannot be\n\t * profiled (as of Neo4j 5.3).\n\t *\n\t * @since 2023.0.0\n\t */\n\tsealed interface UseStatement extends Statement permits DecoratedQuery {\n\n\t\t/**\n\t\t * {@return a statement decorated with <code>EXPLAIN</code>}\n\t\t */\n\t\tdefault Statement explain() {\n\t\t\treturn DecoratedQuery.explain(this);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/StatementBuilder.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Collection;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.annotations.CheckReturnValue;\nimport org.neo4j.cypherdsl.core.internal.RelationshipPatternCondition;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * The statement builder is the union of several other builders that all expose various\n * clauses.\n *\n * @author Michael J. Simons\n * @author Gerrit Meier\n * @author Andreas Berger\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic interface StatementBuilder extends ExposesMatch, ExposesCreate, ExposesMerge, ExposesUnwind, ExposesReturning,\n\t\tExposesFinish, ExposesSubqueryCall, ExposesWith {\n\n\t/**\n\t * An ongoing update statement that can be used to chain more update statements or add\n\t * a with or return clause.\n\t *\n\t * @since 1.0\n\t */\n\tinterface OngoingUpdate extends BuildableStatement<Statement>, ExposesCreate, ExposesMerge, ExposesDelete,\n\t\t\tExposesReturning, ExposesFinish, ExposesWith, ExposesSet, ExposesForeach {\n\n\t}\n\n\t/**\n\t * An ongoing update statement that can be used to chain more updating statements,\n\t * define actions on a merge or add a with or return clause.\n\t *\n\t * @since 2021.0.0\n\t */\n\tinterface OngoingMerge extends OngoingUpdate, ExposesMergeAction, ExposesSetAndRemove {\n\n\t}\n\n\t/**\n\t * A shared marker interface for things that can be turned into a subquery to be used\n\t * inside the WHERE clause.\n\t *\n\t * @since 2020.1.2\n\t */\n\tinterface ExposesExistentialSubqueryCall {\n\n\t\t/**\n\t\t * This can be used against a 4.x database to turn this ongoing match statement\n\t\t * into a condition to be used in an existential subquery.\n\t\t * @return an existential subquery.\n\t\t * @neo4j.version 4.0.0\n\t\t */\n\t\t@Neo4jVersion(minimum = \"4.0.0\")\n\t\tCondition asCondition();\n\n\t}\n\n\t/**\n\t * A match that exposes {@code returning} and {@code where} methods to add required\n\t * information. While the where clause is optional, a returning clause needs to be\n\t * specified before the statement can be built.\n\t *\n\t * @since 1.0\n\t */\n\tinterface OngoingReadingWithoutWhere extends OngoingReading, ExposesHints,\n\t\t\tExposesWhere<StatementBuilder.OngoingReadingWithWhere>, ExposesMatch, ExposesExistentialSubqueryCall {\n\n\t}\n\n\t/**\n\t * A match that has a non-empty {@code where}-part. THe returning clause is still\n\t * open.\n\t *\n\t * @since 1.0\n\t */\n\tinterface OngoingReadingWithWhere extends OngoingReading, ExposesMatch,\n\t\t\tExposesLogicalOperators<OngoingReadingWithWhere>, ExposesExistentialSubqueryCall {\n\n\t}\n\n\t/**\n\t * A match that exposes {@code returning} and for which it is not decided whether the\n\t * optional where part has been used or note.\n\t *\n\t * @since 1.0\n\t */\n\tinterface OngoingReading extends ExposesReturning, ExposesFinish, ExposesWith, ExposesUpdatingClause, ExposesUnwind,\n\t\t\tExposesCreate, ExposesMatch, ExposesCall<OngoingInQueryCallWithoutArguments>, ExposesSubqueryCall {\n\n\t}\n\n\t/**\n\t * Builder part for unwinding.\n\t *\n\t * @since 1.0\n\t */\n\tinterface OngoingUnwind {\n\n\t\t/**\n\t\t * Adds an {@code AS} part that allows to define an alias for the iterable being\n\t\t * unwound.\n\t\t * @param variable the alias name\n\t\t * @return a normal, ongoing read.\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingReading as(String variable);\n\n\t\t/**\n\t\t * Reuse an existing symbolic name.\n\t\t * @param variable a symbolic name\n\t\t * @return a normal, ongoing read.\n\t\t * @since 2021.0.2\n\t\t */\n\t\t@CheckReturnValue\n\t\tdefault OngoingReading as(SymbolicName variable) {\n\t\t\treturn as(variable.getValue());\n\t\t}\n\n\t}\n\n\t/**\n\t * A match that knows what to return and which is ready to be build.\n\t *\n\t * @since 1.0\n\t */\n\tinterface OngoingReadingAndReturn extends TerminalExposesOrderBy, TerminalExposesSkip, TerminalExposesLimit,\n\t\t\tBuildableStatement<ResultStatement> {\n\n\t\t/**\n\t\t * Returns the set of identifiable expressions in the {@literal RETURN} clause,\n\t\t * the final statement might have a different set.\n\t\t * @return the set of identifiable expressions in the {@literal RETURN} clause\n\t\t * @since 2021.3.2\n\t\t */\n\t\tCollection<Expression> getIdentifiableExpressions();\n\n\t}\n\n\t/**\n\t * A match that knows what to pipe to the next part of a multipart query.\n\t *\n\t * @since 1.0\n\t */\n\tinterface OrderableOngoingReadingAndWithWithoutWhere extends OrderableOngoingReadingAndWith {\n\n\t\t/**\n\t\t * Adds a where clause to this match.\n\t\t * @param condition the new condition, must not be {@literal null}\n\t\t * @return a match restricted by a where clause with no return items yet.\n\t\t */\n\t\t@CheckReturnValue\n\t\tOrderableOngoingReadingAndWithWithWhere where(Condition condition);\n\n\t\t/**\n\t\t * Adds a where clause based on a path pattern to this match. See <a href=\n\t\t * \"https://neo4j.com/docs/cypher-manual/4.0/clauses/where/#query-where-patterns\">Using\n\t\t * path patterns in WHERE</a>.\n\t\t * @param pathPattern the path pattern to add to the where clause. This path\n\t\t * pattern must not be {@literal null} and must not introduce new variables not\n\t\t * available in the match.\n\t\t * @return a match restricted by a where clause with no return items yet.\n\t\t * @since 1.0.1\n\t\t */\n\t\t@CheckReturnValue\n\t\tdefault OrderableOngoingReadingAndWithWithWhere where(RelationshipPattern pathPattern) {\n\n\t\t\tAssertions.notNull(pathPattern, \"The path pattern must not be null.\");\n\t\t\treturn this.where(RelationshipPatternCondition.of(pathPattern));\n\t\t}\n\n\t}\n\n\t/**\n\t * Represents a reading statement ending in a combination of {@code WITH} and\n\t * {@code WHERE} clauses.\n\t *\n\t * @since 1.0\n\t * @see OrderableOngoingReadingAndWith\n\t * @see ExposesLogicalOperators\n\t */\n\tinterface OrderableOngoingReadingAndWithWithWhere\n\t\t\textends OrderableOngoingReadingAndWith, ExposesLogicalOperators<OrderableOngoingReadingAndWithWithWhere> {\n\n\t}\n\n\t/**\n\t * Represents a reading statement ending in a with clause, potentially already having\n\t * an order and not exposing order methods.\n\t *\n\t * @since 1.0\n\t */\n\tinterface OngoingReadingAndWith extends OngoingReading, ExposesMatch, ExposesLoadCSV {\n\n\t}\n\n\t/**\n\t * Represents a reading statement ending in a {@code WITH} clause.\n\t *\n\t * @since 1.0\n\t * @see OngoingReadingAndWith\n\t */\n\tinterface OrderableOngoingReadingAndWith extends ExposesOrderBy, ExposesSkip, ExposesLimit, OngoingReadingAndWith {\n\n\t\t/**\n\t\t * Returns the set of identifiable expressions in the {@literal WITH} clause. The\n\t\t * final statement might have a different set.\n\t\t * @return the set of identifiable expressions in the {@literal WITH} clause\n\t\t * @since 2021.3.2\n\t\t */\n\t\tCollection<Expression> getIdentifiableExpressions();\n\n\t}\n\n\t/**\n\t * Combines the capabilities of skip, limit and adds additional expressions to the\n\t * order-by items.\n\t *\n\t * @since 1.0\n\t */\n\tinterface OngoingMatchAndReturnWithOrder\n\t\t\textends TerminalExposesSkip, TerminalExposesLimit, BuildableStatement<ResultStatement> {\n\n\t\t/**\n\t\t * Adds another expression to the list of order items.\n\t\t * @param expression the expression that is added with an {@literal AND}\n\t\t * @return a new order specifying step.\n\t\t */\n\t\t@CheckReturnValue\n\t\tTerminalOngoingOrderDefinition and(Expression expression);\n\n\t}\n\n\t/**\n\t * An intermediate step while defining the order of a result set. This definitional\n\t * will eventually return a buildable statement and thus is terminal.\n\t *\n\t * @since 1.0\n\t */\n\tinterface TerminalOngoingOrderDefinition\n\t\t\textends TerminalExposesSkip, TerminalExposesLimit, BuildableStatement<ResultStatement> {\n\n\t\t/**\n\t\t * Specifies descending order and jumps back to defining the match and return\n\t\t * statement.\n\t\t * @return the ongoing definition of a match\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingMatchAndReturnWithOrder descending();\n\n\t\t/**\n\t\t * Specifies ascending order and jumps back to defining the match and return\n\t\t * statement.\n\t\t * @return the ongoing definition of a match\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingMatchAndReturnWithOrder ascending();\n\n\t}\n\n\t/**\n\t * Combines the capabilities of skip, limit and adds additional expressions to the\n\t * order-by items.\n\t *\n\t * @since 1.0\n\t */\n\tinterface OngoingReadingAndWithWithWhereAndOrder extends ExposesSkip, ExposesLimit, OngoingReadingAndWith {\n\n\t\t/**\n\t\t * Adds another expression to the list of order items.\n\t\t * @param expression the expression that is added with an {@literal AND}\n\t\t * @return a new order specifying step.\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingOrderDefinition and(Expression expression);\n\n\t}\n\n\t/**\n\t * An intermediate step while defining the order of a with clause.\n\t *\n\t * @since 1.0\n\t */\n\tinterface OngoingOrderDefinition extends ExposesSkip, ExposesLimit {\n\n\t\t/**\n\t\t * Specifies descending order and jumps back to defining the match and return\n\t\t * statement.\n\t\t * @return the ongoing definition of a match\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingReadingAndWithWithWhereAndOrder descending();\n\n\t\t/**\n\t\t * Specifies ascending order and jumps back to defining the match and return\n\t\t * statement.\n\t\t * @return the ongoing definition of a match\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingReadingAndWithWithWhereAndOrder ascending();\n\n\t}\n\n\t/**\n\t * A statement that has all information required to be build and exposes a build\n\t * method.\n\t *\n\t * @param <T> the type of the statement that is returned\n\t * @since 1.0\n\t */\n\tinterface BuildableStatement<T extends Statement> {\n\n\t\t/**\n\t\t * {@return the statement ready to be used, i.e. in a renderer}\n\t\t */\n\t\tT build();\n\n\t\t/**\n\t\t * Returns a statement decorated with a {@code EXPLAIN} clause.\n\t\t * @return a decorated statement\n\t\t * @since 2020.1.2\n\t\t */\n\t\tdefault Statement explain() {\n\n\t\t\treturn DecoratedQuery.explain(build());\n\t\t}\n\n\t\t/**\n\t\t * Returns a statement decorated with a {@code PROFILE} clause.\n\t\t * @return a decorated statement\n\t\t * @since 2020.1.2\n\t\t */\n\t\tdefault Statement profile() {\n\n\t\t\treturn DecoratedQuery.profile(build());\n\t\t}\n\n\t}\n\n\t/**\n\t * A step that exposes several methods to specify ordering. This is a terminal\n\t * operation just before a statement is buildable.\n\t *\n\t * @since 1.0\n\t */\n\tinterface TerminalExposesOrderBy {\n\n\t\t/**\n\t\t * Order the result set by one or more {@link SortItem sort items}. Those can be\n\t\t * retrieved for all expression with {@link Cypher#sort(Expression)} or directly\n\t\t * from properties.\n\t\t * @param sortItem one or more sort items\n\t\t * @return a build step that still offers methods for defining skip and limit\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingMatchAndReturnWithOrder orderBy(SortItem... sortItem);\n\n\t\t/**\n\t\t * Order the result set by one or more {@link SortItem sort items}. Those can be\n\t\t * retrieved for all expression with {@link Cypher#sort(Expression)} or directly\n\t\t * from properties.\n\t\t * @param sortItem one or more sort items\n\t\t * @return a build step that still offers methods for defining skip and limit\n\t\t * @since 2021.2.2\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingMatchAndReturnWithOrder orderBy(Collection<SortItem> sortItem);\n\n\t\t/**\n\t\t * Order the result set by an expression.\n\t\t * @param expression the expression to order by\n\t\t * @return a step that allows for adding more expression or fine-tuning the sort\n\t\t * direction of the last expression\n\t\t */\n\t\t@CheckReturnValue\n\t\tTerminalOngoingOrderDefinition orderBy(Expression expression);\n\n\t}\n\n\t/**\n\t * A step that exposes the {@link #skip(Number)} method.\n\t *\n\t * @since 1.0\n\t */\n\tinterface TerminalExposesSkip {\n\n\t\t/**\n\t\t * Adds a skip clause, skipping the given number of records.\n\t\t * @param number how many records to skip. If this is null, then no records are\n\t\t * skipped.\n\t\t * @return a step that only allows the limit of records to be specified.\n\t\t */\n\t\t@CheckReturnValue\n\t\tTerminalExposesLimit skip(Number number);\n\n\t\t/**\n\t\t * Adds a skip clause.\n\t\t * @param expression the expression to skip by\n\t\t * @return a step that only allows the limit of records to be specified.\n\t\t * @since 2021.0.0\n\t\t */\n\t\t@CheckReturnValue\n\t\tTerminalExposesLimit skip(Expression expression);\n\n\t}\n\n\t/**\n\t * A step that exposes the {@link #limit(Number)} method.\n\t *\n\t * @since 1.0\n\t */\n\tinterface TerminalExposesLimit extends BuildableStatement<ResultStatement> {\n\n\t\t/**\n\t\t * Limits the number of returned records.\n\t\t * @param number how many records to return. If this is null, all the records are\n\t\t * returned.\n\t\t * @return a buildable match statement.\n\t\t */\n\t\t@CheckReturnValue\n\t\tBuildableStatement<ResultStatement> limit(Number number);\n\n\t\t/**\n\t\t * Limits the number of returned records.\n\t\t * @param expression how many records to return. If this is null, all the records\n\t\t * are returned.\n\t\t * @return a buildable match statement.\n\t\t * @since 2021.0.0\n\t\t */\n\t\t@CheckReturnValue\n\t\tBuildableStatement<ResultStatement> limit(Expression expression);\n\n\t}\n\n\t/**\n\t * Terminal operation that only allows access to {@link BuildableStatement}. A marker\n\t * interface to clarify the intention instead of just exposing the\n\t * {@code BuildableStatement}.\n\t *\n\t * @since 2024.3.0\n\t */\n\tinterface Terminal extends BuildableStatement<Statement> {\n\n\t}\n\n\t/**\n\t * See {@link TerminalExposesOrderBy}, but on a with clause.\n\t *\n\t * @since 1.0\n\t */\n\tinterface ExposesOrderBy {\n\n\t\t/**\n\t\t * Order the result set by one or more {@link SortItem sort items}. Those can be\n\t\t * retrieved for all expression with {@link Cypher#sort(Expression)} or directly\n\t\t * from properties.\n\t\t * @param sortItem one or more sort items\n\t\t * @return a build step that still offers methods for defining skip and limit\n\t\t */\n\t\t@CheckReturnValue\n\t\tOrderableOngoingReadingAndWithWithWhere orderBy(SortItem... sortItem);\n\n\t\t/**\n\t\t * Order the result set by one or more {@link SortItem sort items}. Those can be\n\t\t * retrieved for all expression with {@link Cypher#sort(Expression)} or directly\n\t\t * from properties.\n\t\t * @param sortItem one or more sort items\n\t\t * @return a build step that still offers methods for defining skip and limit\n\t\t * @since 2021.2.2\n\t\t */\n\t\t@CheckReturnValue\n\t\tOrderableOngoingReadingAndWithWithWhere orderBy(Collection<SortItem> sortItem);\n\n\t\t/**\n\t\t * Order the result set by an expression.\n\t\t * @param expression the expression to order by\n\t\t * @return a step that allows for adding more expression or fine-tuning the sort\n\t\t * direction of the last expression\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingOrderDefinition orderBy(Expression expression);\n\n\t}\n\n\t/**\n\t * The union type of an ongoing reading with a WITH and a SKIP clause.\n\t *\n\t * @since 2021.0.0\n\t */\n\tinterface OngoingReadingAndWithWithSkip extends OngoingReadingAndWith, ExposesLimit {\n\n\t}\n\n\t/**\n\t * A step that exposes the {@link #skip(Number)} method.\n\t *\n\t * @since 1.0\n\t */\n\tinterface ExposesSkip {\n\n\t\t/**\n\t\t * Adds a skip clause, skipping the given number of records.\n\t\t * @param number how many records to skip. If this is null, then no records are\n\t\t * skipped.\n\t\t * @return a step that only allows the limit of records to be specified.\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingReadingAndWithWithSkip skip(Number number);\n\n\t\t/**\n\t\t * Adds a skip clause.\n\t\t * @param expression how many records to skip. If this is null, then no records\n\t\t * are skipped.\n\t\t * @return a step that only allows the limit of records to be specified.\n\t\t * @since 2021.0.0\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingReadingAndWithWithSkip skip(Expression expression);\n\n\t}\n\n\t/**\n\t * A step that exposes the {@link #limit(Number)} method.\n\t *\n\t * @since 1.0\n\t */\n\tinterface ExposesLimit {\n\n\t\t/**\n\t\t * Limits the number of returned records.\n\t\t * @param number how many records to return. If this is null, all the records are\n\t\t * returned.\n\t\t * @return a buildable match statement.\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingReadingAndWith limit(Number number);\n\n\t\t/**\n\t\t * Limits the number of returned records.\n\t\t * @param expression how many records to return. If this is null, all the records\n\t\t * are returned.\n\t\t * @return a buildable match statement.\n\t\t * @since 2021.0.0\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingReadingAndWith limit(Expression expression);\n\n\t}\n\n\t/**\n\t * Steps for building a {@link Foreach} clause.\n\t *\n\t * @since 2023.4.0\n\t */\n\tinterface ExposesForeach {\n\n\t\t/**\n\t\t * Starts defining a {@link Foreach} clause.\n\t\t * @param variable the variable to use in the iterator\n\t\t * @return a step for selecting the source of iteration\n\t\t * @since 2023.4.0\n\t\t */\n\t\tForeachSourceStep foreach(SymbolicName variable);\n\n\t}\n\n\t/**\n\t * Initial step of defining a {@link Foreach FOREACH-clause}.\n\t *\n\t * @since 2023.4.0\n\t */\n\tsealed interface ForeachSourceStep permits DefaultStatementBuilder.ForeachBuilder {\n\n\t\t/**\n\t\t * Defines the source to be iterated by {@code FOREACH}. Must evaluate to\n\t\t * something iterable, for example something like {@link Cypher#nodes(NamedPath)}\n\t\t * for\n\t\t * @param list the expression to iterate on\n\t\t * @return the next step.\n\t\t */\n\t\tForeachUpdateStep in(Expression list);\n\n\t}\n\n\t/**\n\t * Second step of defining a {@link Foreach FOREACH-clause} in which the updating\n\t * clause is defined.\n\t *\n\t * @since 2023.4.0\n\t */\n\tsealed interface ForeachUpdateStep permits DefaultStatementBuilder.ForeachBuilder {\n\n\t\t/**\n\t\t * Defines the updating clause that to will be applied to every item in the source\n\t\t * expression.\n\t\t * @param updatingClauses the updating clauses to apply\n\t\t * @return the final {@link Foreach} clause\n\t\t */\n\t\tOngoingUpdate apply(UpdatingClause... updatingClauses);\n\n\t}\n\n\t/**\n\t * A step providing all the supported updating clauses (DELETE, SET).\n\t *\n\t * @since 1.0\n\t */\n\tinterface ExposesUpdatingClause extends ExposesDelete, ExposesMerge, ExposesSetAndRemove, ExposesForeach {\n\n\t}\n\n\t/**\n\t * A step that exposes only the {@code DELETE} clause.\n\t *\n\t * @since 1.0\n\t */\n\tinterface ExposesDelete {\n\n\t\t/**\n\t\t * Renders a {@code DELETE} clause targeting the given variables. NO checks are\n\t\t * done whether they have been matched previously.\n\t\t * @param variables variables indicating the things to delete.\n\t\t * @return a match with a {@literal DELETE} clause that can be build now\n\t\t */\n\t\t@CheckReturnValue\n\t\tdefault OngoingUpdate delete(String... variables) {\n\t\t\treturn delete(Expressions.createSymbolicNames(variables));\n\t\t}\n\n\t\t/**\n\t\t * Renders a {@code DELETE} clause targeting the given variables. NO checks are\n\t\t * done whether they have been matched previously.\n\t\t * @param variables variables indicating the things to delete.\n\t\t * @return a match with a {@literal DELETE} clause that can be build now\n\t\t */\n\t\t@CheckReturnValue\n\t\tdefault OngoingUpdate delete(Named... variables) {\n\t\t\treturn delete(Expressions.createSymbolicNames(variables));\n\t\t}\n\n\t\t/**\n\t\t * Creates a delete step with one or more expressions to be deleted.\n\t\t * @param expressions the expressions to be deleted.\n\t\t * @return a match with a {@literal DELETE} clause that can be build now\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingUpdate delete(Expression... expressions);\n\n\t\t/**\n\t\t * Creates a delete step with one or more expressions to be deleted.\n\t\t * @param expressions the expressions to be deleted.\n\t\t * @return a match with a {@literal DELETE} clause that can be build now\n\t\t * @since 2021.2.2\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingUpdate delete(Collection<? extends Expression> expressions);\n\n\t\t/**\n\t\t * Renders a {@code DETACH DELETE} clause targeting the given variables. NO checks\n\t\t * are done whether they have been matched previously.\n\t\t * @param variables variables indicating the things to delete.\n\t\t * @return a match with a {@literal DETACH DELETE} clause that can be build now\n\t\t */\n\t\t@CheckReturnValue\n\t\tdefault OngoingUpdate detachDelete(String... variables) {\n\t\t\treturn detachDelete(Expressions.createSymbolicNames(variables));\n\t\t}\n\n\t\t/**\n\t\t * Renders a {@code DETACH DELETE} clause targeting the given variables. NO checks\n\t\t * are done whether they have been matched previously.\n\t\t * @param variables variables indicating the things to delete.\n\t\t * @return a match with a {@literal DETACH DELETE} clause that can be build now\n\t\t */\n\t\t@CheckReturnValue\n\t\tdefault OngoingUpdate detachDelete(Named... variables) {\n\t\t\treturn detachDelete(Expressions.createSymbolicNames(variables));\n\t\t}\n\n\t\t/**\n\t\t * Starts building a delete step that will use {@code DETACH} to remove\n\t\t * relationships.\n\t\t * @param expressions the expressions to be deleted.\n\t\t * @return a match with {@literal DETACH DELETE} clause that can be build now\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingUpdate detachDelete(Expression... expressions);\n\n\t\t/**\n\t\t * Starts building a delete step that will use {@code DETACH} to remove\n\t\t * relationships.\n\t\t * @param expressions the expressions to be deleted.\n\t\t * @return a match with {@literal DETACH DELETE} clause that can be build now\n\t\t * @since 2021.2.2\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingUpdate detachDelete(Collection<? extends Expression> expressions);\n\n\t}\n\n\t/**\n\t * Set part of a statement.\n\t *\n\t * @since 1.0\n\t */\n\tinterface ExposesSet {\n\n\t\t/**\n\t\t * Adds a {@code SET} clause to the statement. The list of expressions must be\n\t\t * even, each pair will be turned into SET operation.\n\t\t * @param expressions the list of expressions to use in a set clause.\n\t\t * @return an ongoing match and update\n\t\t */\n\t\t@CheckReturnValue\n\t\tBuildableMatchAndUpdate set(Expression... expressions);\n\n\t\t/**\n\t\t * Adds a {@code SET} clause to the statement. The list of expressions must be\n\t\t * even, each pair will be turned into SET operation.\n\t\t * @param expressions the list of expressions to use in a set clause.\n\t\t * @return an ongoing match and update\n\t\t * @since 2021.2.2\n\t\t */\n\t\t@CheckReturnValue\n\t\tBuildableMatchAndUpdate set(Collection<? extends Expression> expressions);\n\n\t\t/**\n\t\t * Adds a {@code SET} clause to the statement, modifying the given named thing\n\t\t * with an expression.\n\t\t * @param variable the named thing to modify\n\t\t * @param expression the modifying expression\n\t\t * @return an ongoing match and update\n\t\t */\n\t\t@CheckReturnValue\n\t\tdefault BuildableMatchAndUpdate set(Named variable, Expression expression) {\n\t\t\treturn set(variable.getRequiredSymbolicName(), expression);\n\t\t}\n\n\t\t/**\n\t\t * Creates a {@code +=} operation. The left hand side must resolve to a container\n\t\t * (either a node or a relationship) of properties and the right hand side must be\n\t\t * a map of new or updated properties\n\t\t * @param target the target container that should be modified\n\t\t * @param properties the new properties\n\t\t * @return an ongoing match and update\n\t\t * @since 2020.1.5\n\t\t */\n\t\t@CheckReturnValue\n\t\tBuildableMatchAndUpdate mutate(Expression target, Expression properties);\n\n\t\t/**\n\t\t * Creates a {@code +=} operation. The left hand side must resolve to a container\n\t\t * (either a node or a relationship) of properties and the right hand side must be\n\t\t * a map of new or updated properties\n\t\t * @param variable the named thing to modify\n\t\t * @param properties the new properties\n\t\t * @return an ongoing match and update\n\t\t * @since 2020.1.5\n\t\t */\n\t\t@CheckReturnValue\n\t\tdefault BuildableMatchAndUpdate mutate(Named variable, Expression properties) {\n\t\t\treturn mutate(variable.getRequiredSymbolicName(), properties);\n\t\t}\n\n\t}\n\n\t/**\n\t * Exposes node mutations.\n\t *\n\t * @param <R> the type of the next step\n\t * @since 2023.5.0\n\t */\n\tinterface ExposesSetLabel<R> {\n\n\t\t/**\n\t\t * Creates {@code SET} clause for setting the given labels to a node.\n\t\t * @param node the node whose labels are to be changed\n\t\t * @param labels the labels to be set\n\t\t * @return a match with a SET clause that can be build now\n\t\t */\n\t\t@CheckReturnValue\n\t\tR set(Node node, String... labels);\n\n\t\t/**\n\t\t * Creates {@code SET} clause for setting the given labels to a node.\n\t\t * @param node the node whose labels are to be changed\n\t\t * @param labels the labels to be set\n\t\t * @return a match with a SET clause that can be build now\n\t\t * @since 2021.2.2\n\t\t */\n\t\t@CheckReturnValue\n\t\tR set(Node node, Collection<String> labels);\n\n\t\t/**\n\t\t * Creates {@code SET} clause for setting the given labels to a node.\n\t\t * @param node the node whose labels are to be changed\n\t\t * @param labels the labels to be set\n\t\t * @return a match with a SET clause that can be build now\n\t\t * @since 2025.1.0\n\t\t */\n\t\t@CheckReturnValue\n\t\tR set(Node node, Labels labels);\n\n\t}\n\n\t/**\n\t * A step that exposes the set clause.\n\t *\n\t * @since 1.0\n\t */\n\tinterface ExposesSetAndRemove extends ExposesSet, ExposesSetLabel<BuildableMatchAndUpdate> {\n\n\t\t/**\n\t\t * Creates {@code SET} clause for removing the given labels from a node.\n\t\t * @param node the node whose labels are to be changed\n\t\t * @param labels the labels to be removed\n\t\t * @return a match with a REMOVE clause that can be build now\n\t\t */\n\t\t@CheckReturnValue\n\t\tBuildableMatchAndUpdate remove(Node node, String... labels);\n\n\t\t/**\n\t\t * Creates {@code SET} clause for removing the given labels from a node.\n\t\t * @param node the node whose labels are to be changed\n\t\t * @param labels the labels to be removed\n\t\t * @return a match with a REMOVE clause that can be build now\n\t\t * @since 2021.2.2\n\t\t */\n\t\t@CheckReturnValue\n\t\tBuildableMatchAndUpdate remove(Node node, Collection<String> labels);\n\n\t\t/**\n\t\t * Creates {@code SET} clause for removing the given labels from a node.\n\t\t * @param node the node whose labels are to be changed\n\t\t * @param labels the labels to be removed\n\t\t * @return a match with a REMOVE clause that can be build now\n\t\t * @since 2025.1.0\n\t\t */\n\t\t@CheckReturnValue\n\t\tBuildableMatchAndUpdate remove(Node node, Labels labels);\n\n\t\t/**\n\t\t * Creates {@code SET} clause for removing the enumerated properties.\n\t\t * @param properties the properties to be removed\n\t\t * @return a match with a REMOVE clause that can be build now\n\t\t */\n\t\t@CheckReturnValue\n\t\tBuildableMatchAndUpdate remove(Property... properties);\n\n\t\t/**\n\t\t * Creates {@code SET} clause for removing the enumerated properties.\n\t\t * @param properties the properties to be removed\n\t\t * @return a match with a REMOVE clause that can be build now\n\t\t * @since 2021.2.2\n\t\t */\n\t\t@CheckReturnValue\n\t\tBuildableMatchAndUpdate remove(Collection<Property> properties);\n\n\t}\n\n\t/**\n\t * After a MATCH..UPDATE chain has been established, a RETURN can be added, a pipeline\n\t * with WITH can be started or more mutating steps can be added.\n\t *\n\t * @since 1.0\n\t */\n\tinterface OngoingMatchAndUpdate\n\t\t\textends ExposesReturning, ExposesFinish, ExposesWith, ExposesUpdatingClause, ExposesCreate {\n\n\t}\n\n\t/**\n\t * A buildable ongoing MATCH and UPDATE.\n\t *\n\t * @since 2021.0.0\n\t */\n\tinterface BuildableMatchAndUpdate extends OngoingMatchAndUpdate, BuildableStatement<Statement> {\n\n\t}\n\n\t/**\n\t * Provides a way to specify an action that happens after a {@code MERGE} clause.\n\t *\n\t * @since 2020.1.2\n\t */\n\tinterface ExposesMergeAction {\n\n\t\t/**\n\t\t * This allows to specify the action that should happen when the merge clause lead\n\t\t * to the creation of a new pattern.\n\t\t * @return an ongoing definition of a merge action.\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingMergeAction onCreate();\n\n\t\t/**\n\t\t * This allows to specify the action that should happen when the pattern of the\n\t\t * merge clause already existed and matched.\n\t\t * @return an ongoing definition of a merge action.\n\t\t */\n\t\t@CheckReturnValue\n\t\tOngoingMergeAction onMatch();\n\n\t}\n\n\t/**\n\t * An interface combining a buildable MATCH and UPDATE with the possibility to add\n\t * actions after a MERGE clause.\n\t *\n\t * @since 2021.0.0\n\t */\n\tinterface BuildableOngoingMergeAction extends BuildableMatchAndUpdate, ExposesMergeAction {\n\n\t}\n\n\t/**\n\t * A variant of {@link ExposesSet} that allows for further chaining of actions.\n\t *\n\t * @since 2020.1.2\n\t */\n\tinterface OngoingMergeAction extends ExposesSetLabel<BuildableOngoingMergeAction> {\n\n\t\t/**\n\t\t * Adds a {@code SET} clause to the statement. The list of expressions must be\n\t\t * even, each pair will be turned into SET operation.\n\t\t * @param expressions the list of expressions to use in a set clause.\n\t\t * @return an ongoing match and update\n\t\t */\n\t\t@CheckReturnValue\n\t\tBuildableOngoingMergeAction set(Expression... expressions);\n\n\t\t/**\n\t\t * Adds a {@code SET} clause to the statement. The list of expressions must be\n\t\t * even, each pair will be turned into SET operation.\n\t\t * @param expressions the list of expressions to use in a set clause.\n\t\t * @return an ongoing match and update\n\t\t * @since 2021.2.2\n\t\t */\n\t\t@CheckReturnValue\n\t\tBuildableOngoingMergeAction set(Collection<? extends Expression> expressions);\n\n\t\t/**\n\t\t * Adds a {@code SET} clause to the statement, modifying the given named thing\n\t\t * with an expression.\n\t\t * @param variable the named thing to modify\n\t\t * @param expression the modifying expression\n\t\t * @return an ongoing match and update\n\t\t */\n\t\t@CheckReturnValue\n\t\tdefault BuildableOngoingMergeAction set(Named variable, Expression expression) {\n\t\t\treturn set(variable.getRequiredSymbolicName(), expression);\n\t\t}\n\n\t\t/**\n\t\t * Creates a {@code +=} operation. The left hand side must resolve to a container\n\t\t * (either a node or a relationship) of properties and the right hand side must be\n\t\t * a map of new or updated properties\n\t\t * @param target the target container that should be modified\n\t\t * @param properties the new properties\n\t\t * @return an ongoing match and update\n\t\t * @since 2020.1.5\n\t\t */\n\t\t@CheckReturnValue\n\t\tBuildableOngoingMergeAction mutate(Expression target, Expression properties);\n\n\t\t/**\n\t\t * Creates a {@code +=} operation. The left hand side must resolve to a container\n\t\t * (either a node or a relationship) of properties and the right hand side must be\n\t\t * a map of new or updated properties\n\t\t * @param variable the named thing to modify\n\t\t * @param properties the new properties\n\t\t * @return an ongoing match and update\n\t\t * @since 2020.1.5\n\t\t */\n\t\t@CheckReturnValue\n\t\tdefault BuildableOngoingMergeAction mutate(Named variable, Expression properties) {\n\t\t\treturn mutate(variable.getRequiredSymbolicName(), properties);\n\t\t}\n\n\t}\n\n\t/**\n\t * A trait for an ongoing standalone call to expose all of its results via an\n\t * asterisk.\n\t *\n\t * @since 2022.8.3\n\t */\n\tinterface ExposesYieldStar {\n\n\t\t/**\n\t\t * Mostly a helper method to indicate the overload as\n\t\t * {@link org.neo4j.cypherdsl.core.ExposesCall.ExposesYield} uses vargs for all\n\t\t * overloads, and that would not work nicely without arguments on this one here.\n\t\t *\n\t\t * Allows to use a {@literal *} in this standalone call.\n\t\t * @param asterisk the actual * ;)\n\t\t * @return the ongoing standalone call to be configured.\n\t\t * @since 2022.8.0\n\t\t */\n\t\tOngoingStandaloneCallWithReturnFields yield(Asterisk asterisk);\n\n\t\t/**\n\t\t * Convenience method to yield all items of this standalone call.\n\t\t * @return the ongoing standalone call to be configured.\n\t\t * @since 2022.8.0\n\t\t */\n\t\tdefault OngoingStandaloneCallWithReturnFields yieldStar() {\n\t\t\treturn this.yield(Cypher.asterisk());\n\t\t}\n\n\t}\n\n\t/**\n\t * The union of a buildable statement and call exposing new arguments and yields.\n\t */\n\tinterface OngoingStandaloneCallWithoutArguments extends StatementBuilder.BuildableStatement<Statement>,\n\t\t\tExposesCall.ExposesWithArgs<OngoingStandaloneCallWithArguments>,\n\t\t\tExposesCall.ExposesYield<OngoingStandaloneCallWithReturnFields>, ExposesCall.AsFunction, ExposesYieldStar {\n\n\t\t/**\n\t\t * Turn this call into a void call to continue with querying.\n\t\t * @return the call, continue with a normal query from here.\n\t\t * @since 2022.4.0\n\t\t */\n\t\tVoidCall withoutResults();\n\n\t}\n\n\t/**\n\t * The union of a buildable statement and call exposing yields.\n\t */\n\tinterface OngoingStandaloneCallWithArguments extends StatementBuilder.BuildableStatement<Statement>,\n\t\t\tExposesCall.ExposesYield<OngoingStandaloneCallWithReturnFields>, ExposesCall.AsFunction, ExposesYieldStar {\n\n\t\t/**\n\t\t * Turn this call into a void call to continue with querying.\n\t\t * @return the call, continue with a normal query from here.\n\t\t * @since 2022.4.0\n\t\t */\n\t\tVoidCall withoutResults();\n\n\t}\n\n\t/**\n\t * A buildable statement exposing where and return clauses.\n\t */\n\tsealed interface OngoingStandaloneCallWithReturnFields extends StatementBuilder.BuildableStatement<Statement>,\n\t\t\tExposesMatch, ExposesWhere<StatementBuilder.OngoingReadingWithWhere>, ExposesReturning, ExposesFinish,\n\t\t\tExposesWith, ExposesSubqueryCall, ExposesAndThen<OngoingStandaloneCallWithReturnFields, Statement>\n\t\t\tpermits DefaultStatementBuilder.YieldingStandaloneCallBuilder {\n\n\t}\n\n\t/**\n\t * The union of an in-query call exposing new arguments and yields.\n\t */\n\tinterface OngoingInQueryCallWithoutArguments extends ExposesCall.ExposesWithArgs<OngoingInQueryCallWithArguments>,\n\t\t\tExposesCall.ExposesYield<OngoingInQueryCallWithReturnFields> {\n\n\t\t/**\n\t\t * Turn this call into a void call to continue with querying.\n\t\t * @return the call, continue with a normal query from here.\n\t\t * @since 2022.4.0\n\t\t */\n\t\tVoidCall withoutResults();\n\n\t}\n\n\t/**\n\t * The union of an in-query call exposing yields.\n\t */\n\tinterface OngoingInQueryCallWithArguments extends ExposesCall.ExposesYield<OngoingInQueryCallWithReturnFields> {\n\n\t\t/**\n\t\t * Turn this call into a void call to continue with querying.\n\t\t * @return the call, continue with a normal query from here.\n\t\t * @since 2022.4.0\n\t\t */\n\t\tVoidCall withoutResults();\n\n\t}\n\n\t/**\n\t * The result of a call to a stored procedure not having any results. It is possible\n\t * to continue with \"normal\" querying after the execution of such a procedure.\n\t *\n\t * @since 2022.4.0\n\t */\n\tinterface VoidCall extends OngoingReading {\n\n\t}\n\n\t/**\n\t * An in-query call exposing where and return clauses.\n\t */\n\tinterface OngoingInQueryCallWithReturnFields\n\t\t\textends ExposesMatch, ExposesWhere<StatementBuilder.OngoingReadingWithWhere>, ExposesReturning,\n\t\t\tExposesFinish, ExposesWith, ExposesSubqueryCall, ExposesForeach {\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/StatementCatalog.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.TreeSet;\nimport java.util.stream.Collectors;\n\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\n\n/**\n * The statement catalog gives an overview about relevant items in a statement. These\n * items include tokens (labels and relationship types), the resolved properties for given\n * sets of these tokens (those sets reassembling concrete entities, think Nodes with one\n * or more labels or relationships with a concrete type) as well as conditions in which\n * the properties have been used. This structural analysis can be used to predict how\n * graph elements are accessed, or they can be used to make sure certain conditions are\n * contained within a statement.\n * <p>\n * Finally, the list of identifiable elements at the end of a statement (aka after a\n * {@code RETURN} clause) is contained in the catalog.\n * <p>\n * In addition, this interface provides the namespace for all elements that are\n * represented as non-AST elements as part of a catalog, such as the {@link Property\n * properties} and {@link PropertyFilter property conditions}.\n * <p>\n * Any instance of a {@link StatementCatalog catalog} and its contents can be safely\n * assumed to be immutable.\n *\n * @author Michael J. Simons\n * @since 2023.1.0\n */\npublic sealed interface StatementCatalog permits StatementCatalogBuildingVisitor.DefaultStatementCatalog {\n\n\t/**\n\t * Convenience method to create node label tokens.\n\t * @param label the label to be used\n\t * @return a new label token\n\t */\n\tstatic Token label(String label) {\n\t\treturn Token.label(label);\n\t}\n\n\t/**\n\t * Convenience method to create relationship type tokens.\n\t * @param type the type to be used\n\t * @return a new relationship type token\n\t */\n\tstatic Token type(String type) {\n\t\treturn Token.type(type);\n\t}\n\n\t/**\n\t * Convenience method to create a new property without a specific owner.\n\t * @param name the name of the property\n\t * @return a new property\n\t */\n\tstatic Property property(String name) {\n\t\treturn new Property(name);\n\t}\n\n\t/**\n\t * Convenience method to create a new property with a defined owner.\n\t * @param owner the set of tokens defining the owner\n\t * @param name the name of the property\n\t * @return a new property\n\t */\n\tstatic Property property(Set<Token> owner, String name) {\n\t\treturn new Property(owner, name);\n\t}\n\n\t/**\n\t * Returns a collection of all tokens used in the analyzed statement.\n\t * @return a collection of all tokens used\n\t */\n\tCollection<Token> getAllTokens();\n\n\t/**\n\t * Returns a collection of all node labels used in the analyzed statement.\n\t * @return a collection of all labels used\n\t */\n\tdefault Collection<Token> getNodeLabels() {\n\t\treturn getAllTokens().stream()\n\t\t\t.filter(token -> token.type() == Token.Type.NODE_LABEL)\n\t\t\t.collect(Collectors.toUnmodifiableSet());\n\t}\n\n\t/**\n\t * Returns a collection of all relationship types used in the analyzed statement.\n\t * @return a collection of all types used\n\t */\n\tdefault Collection<Token> getRelationshipTypes() {\n\t\treturn getAllTokens().stream()\n\t\t\t.filter(token -> token.type() == Token.Type.RELATIONSHIP_TYPE)\n\t\t\t.collect(Collectors.toUnmodifiableSet());\n\t}\n\n\t/**\n\t * This method can be used with any token returned from {@link #getNodeLabels()} to\n\t * retrieve relationships that have a node with the given token as start node.\n\t * Alternative, use {@link StatementCatalog#label(String)} to build labels to query\n\t * this method.\n\t * @param label the label to retrieve outgoing relations for\n\t * @return a set of tokens describing relations\n\t * @since 2023.3.0\n\t */\n\tCollection<Token> getOutgoingRelations(Token label);\n\n\t/**\n\t * This method can be used with any token returned from\n\t * {@link #getRelationshipTypes()} to retrieve target nodes of that relationship.\n\t * Alternative, use {@link StatementCatalog#type(String)} to build types to query this\n\t * method.\n\t * @param type the type of relationship to retrieve target nodes\n\t * @return a set of tokens describing labels\n\t * @since 2023.3.0\n\t */\n\tCollection<Token> getTargetNodes(Token type);\n\n\t/**\n\t * This method can be used with any token returned from {@link #getNodeLabels()} to\n\t * retrieve relationships that have a node with the given token as end node.\n\t * Alternative, use {@link StatementCatalog#label(String)} to build labels to query\n\t * this method.\n\t * @param label the label to retrieve incoming relations for\n\t * @return a set of tokens describing relations\n\t * @since 2023.3.0\n\t */\n\tCollection<Token> getIncomingRelations(Token label);\n\n\t/**\n\t * This method can be used with any token returned from\n\t * {@link #getRelationshipTypes()} to retrieve source nodes of that relationship.\n\t * Alternative, use {@link StatementCatalog#type(String)} to build types to query this\n\t * method.\n\t * @param type the type of relationship to retrieve source nodes\n\t * @return a set of tokens describing labels\n\t * @since 2023.3.0\n\t */\n\tCollection<Token> getSourceNodes(Token type);\n\n\t/**\n\t * This method can be used with any token returned from {@link #getNodeLabels()} to\n\t * retrieve relationships that are connected to nodes with the given token.\n\t * Alternative, use {@link StatementCatalog#label(String)} to build labels to query\n\t * this method.\n\t * @param label the label to retrieve relations for\n\t * @return a set of tokens describing relations\n\t * @since 2023.3.0\n\t */\n\tCollection<Token> getUndirectedRelations(Token label);\n\n\t/**\n\t * Returns a collection of all properties resolved in the analyzed statement.\n\t * @return a collection of all properties resolved\n\t */\n\tCollection<Property> getProperties();\n\n\t/**\n\t * Returns a collection all filters resolved in the analyzed statement.\n\t * @return a map of all filters.\n\t */\n\tdefault Collection<Filter> getAllFilters() {\n\t\tSet<Filter> result = new HashSet<>(this.getAllLabelFilters());\n\t\tthis.getAllPropertyFilters().forEach((p, f) -> result.addAll(f));\n\t\treturn result;\n\t}\n\n\t/**\n\t * Returns a collection of all filters that checked for the existence of labels.\n\t * @return a collection of all label filters\n\t */\n\tCollection<LabelFilter> getAllLabelFilters();\n\n\t/**\n\t * Returns a map that contains all properties that have been used in a comparing\n\t * condition as keys and a set of all comparisons they appeared in.\n\t * @return a map of all properties used in comparisons\n\t */\n\tMap<Property, Collection<PropertyFilter>> getAllPropertyFilters();\n\n\t/**\n\t * Returns a collection of all filters applied on a specific property.\n\t * @param property the property for which filter should be retrieved\n\t * @return a collection of all conditions involving properties resolved in the\n\t * statement\n\t */\n\tdefault Collection<PropertyFilter> getFilters(Property property) {\n\t\treturn getAllPropertyFilters().get(property);\n\t}\n\n\t/**\n\t * Returns a collection of all expressions that are identifiable expression in a\n\t * non-void (or non-unit) Cypher statement. These expressions might refer to\n\t * properties, but can be of course function calls, existential sub-queries and the\n\t * like.\n\t * @return a collection of identifiable expressions.\n\t */\n\tCollection<Expression> getIdentifiableExpressions();\n\n\t/**\n\t * After a statement has been build, all parameters that have been added to the\n\t * statement can be retrieved through this method. The result will only contain\n\t * parameters with a defined value. If you are interested in all parameter names, use\n\t * {@link #getParameterNames()}.\n\t * <p>\n\t * The map can be used for example as an argument with various methods on the Neo4j\n\t * Java Driver that allow the execution of parameterized queries.\n\t * @return a map of all parameters with a bound value.\n\t * @since 2023.2.0\n\t */\n\tMap<String, Object> getParameters();\n\n\t/**\n\t * After the statement has been build, this method returns a list of all parameter\n\t * names used, regardless whether a value was bound to the parameter o not.\n\t * @return a set of parameter names being used.\n\t * @since 2023.2.0\n\t */\n\tCollection<String> getParameterNames();\n\n\t/**\n\t * A statement can be configured to use generated names (see\n\t * {@link Configuration#isUseGeneratedNames()}). This method returns the used\n\t * remapping table.\n\t * @return a map of renamed parameters when\n\t * {@link Configuration#isUseGeneratedNames()} would be set to {@literal true}\n\t */\n\tMap<String, String> getRenamedParameters();\n\n\t/**\n\t * Returns a collection of all literals used in a statement.\n\t * @return a collection of all literals used in a statement\n\t * @since 2023.4.0\n\t */\n\t@SuppressWarnings(\"squid:S1452\") // Generic items, this is exactly what we want here\n\tCollection<Literal<?>> getLiterals();\n\n\t/**\n\t * Enum for the clause in which a comparison was made.\n\t */\n\tenum Clause {\n\n\t\t/**\n\t\t * The comparison was used in a {@code MATCH} clause.\n\t\t */\n\t\tMATCH,\n\t\t/**\n\t\t * The comparison was used in a {@code CREATE} clause.\n\t\t */\n\t\tCREATE,\n\t\t/**\n\t\t * The comparison was used in a {@code MERGE} clause.\n\t\t */\n\t\tMERGE,\n\t\t/**\n\t\t * The comparison was used in a {@code DELETE} clause.\n\t\t */\n\t\tDELETE,\n\t\t/**\n\t\t * The comparison was used in a {@code WITH} clause. The {@code WITH} clause is\n\t\t * different to the {@code WHERE} clause as here \"WHERE simply filters the\n\t\t * results.\" (quoting from <a href=\n\t\t * \"https://neo4j.com/docs/cypher-manual/current/clauses/where/\">where</a>).\n\t\t */\n\t\tWITH,\n\t\t/**\n\t\t * Used in case the analysis could not determine a clause.\n\t\t */\n\t\tUNKNOWN\n\n\t}\n\n\t/**\n\t * This interface represents all kinds of filters in a query such as <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/clauses/where/#filter-on-node-label\">filters\n\t * on labels</a> and <a href=\n\t * \"https://neo4j.com/docs/cypher-manual/current/clauses/where/#filter-on-node-property\">filters\n\t * on properties</a>.\n\t */\n\tsealed interface Filter permits LabelFilter, PropertyFilter {\n\n\t}\n\n\t/**\n\t * A token can either describe a node label or a relationship type.\n\t *\n\t * @param type the type of this token\n\t * @param value the concrete value\n\t */\n\trecord Token(Type type, String value) implements Comparable<Token> {\n\n\t\t/**\n\t\t * Turns a specific {@link NodeLabel label} into a more abstract token.\n\t\t * @param label a label, must not be {@literal null}.\n\t\t * @return a token\n\t\t */\n\t\tpublic static Token label(NodeLabel label) {\n\t\t\treturn new Token(Token.Type.NODE_LABEL,\n\t\t\t\t\tObjects.requireNonNull(label, \"Label must not be null.\").getValue());\n\t\t}\n\n\t\t/**\n\t\t * Turns a specific node label into a more abstract token.\n\t\t * @param label a label, must not be {@literal null}.\n\t\t * @return a token\n\t\t */\n\t\tpublic static Token label(String label) {\n\t\t\treturn new Token(Token.Type.NODE_LABEL, Objects.requireNonNull(label, \"Label must not be null.\"));\n\t\t}\n\n\t\t/**\n\t\t * Turns a specific relationship type into a more abstract token.\n\t\t * @param type a string representing a type, must not be {@literal null}.\n\t\t * @return a token\n\t\t */\n\t\tpublic static Token type(String type) {\n\t\t\treturn new Token(Token.Type.RELATIONSHIP_TYPE, Objects.requireNonNull(type, \"Type must not be null.\"));\n\t\t}\n\n\t\t@Override\n\t\tpublic int compareTo(Token o) {\n\t\t\tint result = this.type().compareTo(o.type());\n\t\t\tif (result == 0) {\n\t\t\t\tresult = this.value().compareTo(o.value());\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\t/**\n\t\t * The specific token type.\n\t\t */\n\t\tpublic enum Type {\n\n\t\t\t/**\n\t\t\t * Represents a node label.\n\t\t\t */\n\t\t\tNODE_LABEL,\n\t\t\t/**\n\t\t\t * Represents a relationship type.\n\t\t\t */\n\t\t\tRELATIONSHIP_TYPE\n\n\t\t}\n\t}\n\n\t/**\n\t * A property that has been resolved. In case this property has been resolved for an\n\t * entity, the entity itself will be defined by its set of tokens. Tokens are\n\t * guaranteed to be sorted and will be of the same type.\n\t *\n\t * @param name the name of the resolved property\n\t * @param owningToken zero or many owning tokens for a property\n\t */\n\trecord Property(Set<Token> owningToken, String name) {\n\n\t\t/**\n\t\t * Creates a new property without an owner.\n\t\t * @param name the name of the resolved property\n\t\t */\n\t\tpublic Property(String name) {\n\t\t\tthis(Set.of(), name);\n\t\t}\n\n\t\t/**\n\t\t * Creates a new property with a single owning token.\n\t\t * @param owningToken the owning token\n\t\t * @param name the name of the resolved property\n\t\t */\n\t\tpublic Property(Token owningToken, String name) {\n\t\t\tthis(Set.of(owningToken), name);\n\t\t}\n\n\t\t/**\n\t\t * The constructor enforces the use of unmodifiable sets and unique types accross\n\t\t * tokens.\n\t\t * @param name the name of the resolved property\n\t\t * @param owningToken zero or many owning tokens for a property\n\t\t */\n\t\tpublic Property {\n\t\t\tif (owningToken.stream().map(Token::type).distinct().count() > 1) {\n\t\t\t\tthrow new IllegalArgumentException(\"Owning tokens are of multiple types\");\n\t\t\t}\n\t\t\towningToken = Collections.unmodifiableSet(new TreeSet<>(owningToken));\n\t\t}\n\n\t\t/**\n\t\t * {@return an optional, owning type}\n\t\t */\n\t\tpublic Optional<Token.Type> owningType() {\n\t\t\treturn this.owningToken.stream().map(Token::type).distinct().findFirst();\n\t\t}\n\t}\n\n\t/**\n\t * This type represents a filter on nodes requiring one or more labels.\n\t *\n\t * @param symbolicName the symbolic name used when creating the filter\n\t * @param value the set of tokens that made up this filter\n\t */\n\trecord LabelFilter(String symbolicName, Set<Token> value) implements Filter {\n\n\t\t/**\n\t\t * Makes sure the values are stored in an unmutable fashion.\n\t\t * @param symbolicName the symbolic name used when creating the filter\n\t\t * @param value the set of tokens that made up this filter\n\t\t */\n\t\tpublic LabelFilter {\n\t\t\tvalue = Set.copyOf(value);\n\t\t}\n\t}\n\n\t/**\n\t * This type encapsulates a comparison in which a property of a node or relationship\n\t * was used. The property may appear on the left hand side or right hand side or even\n\t * on both side of the comparison (think being used in a function on both sides with\n\t * different arguments). The {@code clause} attribute will specify the context in\n\t * which the comparison was made.\n\t * <p>\n\t * The expressions used in the comparison are provided as Cypher-DSL AST expressions.\n\t * They can be freely visited or rendered into Cypher via the\n\t * {@link org.neo4j.cypherdsl.core.renderer.GeneralizedRenderer} like this:\n\t *\n\t * <pre>{@code\n\t *     var cypher = Renderer.getRenderer(Configuration.prettyPrinting(), GeneralizedRenderer.class)\n\t *          .render(comparison.left());\n\t * }</pre>\n\t *\n\t * @param clause the clause in which the comparison was used\n\t * @param left the left hand side of the comparison\n\t * @param operator the operator used\n\t * @param right the right hand side of the comparison\n\t * @param parameterNames the parameter names used in this comparison\n\t * @param parameters parameters with defined values used in this comparison\n\t */\n\trecord PropertyFilter(Clause clause, Expression left, Operator operator, Expression right,\n\t\t\tSet<String> parameterNames, Map<String, Object> parameters) implements Filter {\n\n\t\t/**\n\t\t * The constructor enforces the use of unmodifiable sets.\n\t\t * @param clause the clause in which the comparison was used\n\t\t * @param left the left hand side of the comparison\n\t\t * @param operator the operator used\n\t\t * @param right the right hand side of the comparison\n\t\t * @param parameterNames the parameter names used in this comparison\n\t\t * @param parameters parameters with defined values used in this comparison\n\t\t */\n\t\tpublic PropertyFilter {\n\t\t\tparameterNames = Set.copyOf(parameterNames);\n\t\t\tparameters = Collections.unmodifiableMap(new HashMap<>(parameters));\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/StatementCatalogBuildingVisitor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayDeque;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Deque;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.TreeSet;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicReference;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\nimport org.neo4j.cypherdsl.build.annotations.RegisterForReflection;\nimport org.neo4j.cypherdsl.core.ParameterCollectingVisitor.ParameterInformation;\nimport org.neo4j.cypherdsl.core.StatementCatalog.Clause;\nimport org.neo4j.cypherdsl.core.StatementCatalog.PropertyFilter;\nimport org.neo4j.cypherdsl.core.StatementCatalog.Token;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.Namespace;\nimport org.neo4j.cypherdsl.core.internal.ReflectiveVisitor;\nimport org.neo4j.cypherdsl.core.internal.ScopingStrategy;\n\n/**\n * This visitor creates a {@link StatementCatalog statement catalog}. It is not thread\n * safe and must not be used multiple times. Please create a new instance on each\n * invocation.\n *\n * @author Michael J. Simons\n * @since 2023.1.0\n */\n@RegisterForReflection\n@SuppressWarnings({ \"unused\", \"squid:S1172\" })\nclass StatementCatalogBuildingVisitor extends ReflectiveVisitor {\n\n\t/**\n\t * Constant class name for skipping compounds, not inclined to make this type public.\n\t */\n\tprivate static final String TYPE_OF_COMPOUND_CONDITION = \"org.neo4j.cypherdsl.core.CompoundCondition\";\n\n\t/**\n\t * Current clause the visitor is in.\n\t */\n\tprivate final AtomicReference<Clause> currentClause = new AtomicReference<>(Clause.UNKNOWN);\n\n\t/**\n\t * The current pattern element visited.\n\t */\n\tprivate final Deque<PatternElement> currentPatternElement = new ArrayDeque<>();\n\n\tprivate final Set<Token> tokens = new LinkedHashSet<>();\n\n\tprivate final Set<StatementCatalog.Property> properties = new LinkedHashSet<>();\n\n\tprivate final Set<StatementCatalog.LabelFilter> labelFilters = new LinkedHashSet<>();\n\n\tprivate final Map<StatementCatalog.Property, Set<PropertyFilter>> propertyFilters = new LinkedHashMap<>();\n\n\t/**\n\t * Scoped lookup tables from symbolic name to pattern elements (nodes or\n\t * relationships).\n\t */\n\tprivate final Deque<Map<SymbolicName, PatternElement>> patternLookup = new ArrayDeque<>();\n\n\t/**\n\t * A stack of conditions (keeping track of the latest entered).\n\t */\n\tprivate final Deque<org.neo4j.cypherdsl.core.Condition> currentConditions = new ArrayDeque<>();\n\n\tprivate final AtomicReference<Set<Token>> currentHasLabelCondition = new AtomicReference<>();\n\n\t/**\n\t * Required for resolving parameter names, must be from the same statement that is\n\t * analyzed.\n\t */\n\tprivate final StatementContext statementContext;\n\n\tprivate final boolean renderConstantsAsParameters;\n\n\t/**\n\t * Delegating the hard work to the shared scope strategy in most cases.\n\t */\n\tprivate final ScopingStrategy scopingStrategy;\n\n\tprivate final ParameterCollectingVisitor allParameters;\n\n\tprivate final Map<Node, Set<Token>> currentUndirectedRelations = new HashMap<>();\n\n\tprivate final Map<Node, Set<Token>> currentIncomingRelations = new HashMap<>();\n\n\tprivate final Map<Node, Set<Token>> currentOutgoingRelations = new HashMap<>();\n\n\tprivate final Map<Token, Relationships> relationships = new HashMap<>();\n\n\tprivate final Set<Literal<?>> literals = new LinkedHashSet<>();\n\n\tStatementCatalogBuildingVisitor(StatementContext statementContext, boolean renderConstantsAsParameters) {\n\n\t\tthis.statementContext = statementContext;\n\t\tthis.renderConstantsAsParameters = renderConstantsAsParameters;\n\t\tthis.scopingStrategy = ScopingStrategy.create(\n\t\t\t\tList.of((cause, imports) -> this.patternLookup.push(createNewScope(imports))),\n\t\t\t\tList.of((cause, exports) -> importIntoCurrentScope(exports)));\n\t\tthis.patternLookup.push(new HashMap<>());\n\n\t\tthis.allParameters = new ParameterCollectingVisitor(statementContext, renderConstantsAsParameters);\n\t}\n\n\tprivate static void copyIdentifiableElements(Collection<IdentifiableElement> elements,\n\t\t\tMap<SymbolicName, PatternElement> source, Map<SymbolicName, PatternElement> target) {\n\t\tfor (IdentifiableElement e : elements) {\n\t\t\tif (e instanceof SymbolicName s && source.containsKey(s)) {\n\t\t\t\ttarget.put(s, source.get(s));\n\t\t\t}\n\t\t\telse if (e instanceof Named n && e instanceof PatternElement p) {\n\t\t\t\ttarget.put(n.getRequiredSymbolicName(), p);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static Set<Token> getAllLabels(Node node) {\n\t\tSet<Token> result = new TreeSet<>();\n\t\tif (node.getLabels().isEmpty()) {\n\t\t\tnode.accept(segment -> {\n\t\t\t\tif (segment instanceof Labels l) {\n\t\t\t\t\tl.getStaticValues().stream().map(Token::label).forEach(result::add);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\tnode.getLabels().stream().map(NodeLabel::getValue).map(Token::label).forEach(result::add);\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate Map<SymbolicName, PatternElement> createNewScope(Collection<IdentifiableElement> imports) {\n\t\taddRelationsInCurrentScope();\n\n\t\tMap<SymbolicName, PatternElement> currentScope = this.patternLookup.isEmpty() ? Collections.emptyMap()\n\t\t\t\t: this.patternLookup.peek();\n\t\tMap<SymbolicName, PatternElement> newScope = new HashMap<>();\n\t\tcopyIdentifiableElements(imports, currentScope, newScope);\n\n\t\treturn newScope;\n\t}\n\n\tprivate void importIntoCurrentScope(Collection<IdentifiableElement> exports) {\n\n\t\tMap<SymbolicName, PatternElement> previousScope = this.patternLookup.pop();\n\t\tMap<SymbolicName, PatternElement> currentScope = this.patternLookup.isEmpty() ? new HashMap<>()\n\t\t\t\t: this.patternLookup.peek();\n\t\tcopyIdentifiableElements(exports, previousScope, currentScope);\n\t}\n\n\tStatementCatalog getResult() {\n\n\t\taddRelationsInCurrentScope();\n\t\tvar parameterInformation = this.allParameters.getResult();\n\t\treturn new DefaultStatementCatalog(this.tokens, this.labelFilters, this.properties, this.propertyFilters,\n\t\t\t\tthis.scopingStrategy.getIdentifiables(), parameterInformation, this.relationships, this.literals);\n\t}\n\n\tvoid addRelationsInCurrentScope() {\n\n\t\tfinish(this.currentOutgoingRelations, Relationships::outgoing);\n\t\tfinish(this.currentIncomingRelations, Relationships::incoming);\n\t\tfinish(this.currentUndirectedRelations, Relationships::undirected);\n\t}\n\n\t/**\n\t * Finishes up the relationship's storage (retrieval of actual labels from the nodes).\n\t * @param nodesToRelations the map to process\n\t * @param targetProvider the target where to store the tokens\n\t */\n\tprivate void finish(Map<Node, Set<Token>> nodesToRelations, Function<Relationships, Set<Token>> targetProvider) {\n\t\tnodesToRelations.forEach((k, v) -> {\n\t\t\tvar labels = getAllLabels((Node) k.getSymbolicName().map(this::lookup).orElse(k));\n\t\t\tlabels.forEach(t -> {\n\t\t\t\tvar rels = this.relationships.computeIfAbsent(t, unused -> new Relationships());\n\t\t\t\ttargetProvider.apply(rels).addAll(v);\n\t\t\t});\n\t\t});\n\t\tnodesToRelations.clear();\n\t}\n\n\t@Override\n\tprotected boolean preEnter(Visitable visitable) {\n\t\tthis.scopingStrategy.doEnter(visitable);\n\t\treturn true;\n\t}\n\n\t@Override\n\tprotected void postLeave(Visitable visitable) {\n\t\tthis.scopingStrategy.doLeave(visitable);\n\t}\n\n\tvoid enter(Match match) {\n\t\tthis.currentClause.compareAndSet(Clause.UNKNOWN, Clause.MATCH);\n\t}\n\n\tvoid leave(Match match) {\n\t\tthis.currentClause.compareAndSet(Clause.MATCH, Clause.UNKNOWN);\n\t}\n\n\tvoid enter(Create create) {\n\t\tthis.currentClause.compareAndSet(Clause.UNKNOWN, Clause.CREATE);\n\t}\n\n\tvoid leave(Create create) {\n\t\tthis.currentClause.compareAndSet(Clause.CREATE, Clause.UNKNOWN);\n\t}\n\n\tvoid enter(Merge merge) {\n\t\tthis.currentClause.compareAndSet(Clause.UNKNOWN, Clause.MERGE);\n\t}\n\n\tvoid leave(Merge merge) {\n\t\tthis.currentClause.compareAndSet(Clause.MERGE, Clause.UNKNOWN);\n\t}\n\n\tvoid enter(Delete delete) {\n\t\tthis.currentClause.compareAndSet(Clause.UNKNOWN, Clause.DELETE);\n\t}\n\n\tvoid leave(Delete delete) {\n\t\tthis.currentClause.compareAndSet(Clause.DELETE, Clause.UNKNOWN);\n\t}\n\n\tvoid enter(With with) {\n\t\tthis.currentClause.compareAndSet(Clause.UNKNOWN, Clause.WITH);\n\t}\n\n\tvoid leave(With with) {\n\t\tthis.currentClause.compareAndSet(Clause.WITH, Clause.UNKNOWN);\n\t}\n\n\tvoid enter(Node node) {\n\n\t\tnode.getSymbolicName().ifPresent(s -> store(s, node));\n\t\tthis.currentPatternElement.push(node);\n\t}\n\n\tvoid enter(KeyValueMapEntry mapEntry) {\n\n\t\tvar owner = this.currentPatternElement.peek();\n\t\tif (owner == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tStatementCatalog.Property property;\n\t\tif (owner instanceof Node node) {\n\t\t\tproperty = new StatementCatalog.Property(getAllLabels(node), mapEntry.getKey());\n\t\t}\n\t\telse if (owner instanceof Relationship relationship) {\n\t\t\tproperty = new StatementCatalog.Property(\n\t\t\t\t\trelationship.getDetails().getTypes().stream().map(Token::type).collect(Collectors.toSet()),\n\t\t\t\t\tmapEntry.getKey());\n\t\t}\n\t\telse {\n\t\t\tproperty = null;\n\t\t}\n\n\t\tif (property == null) {\n\t\t\treturn;\n\t\t}\n\t\tthis.properties.add(property);\n\n\t\tExpression left;\n\t\tif (((PropertyContainer) owner).getSymbolicName().isPresent()) {\n\t\t\tleft = ((PropertyContainer) owner).property(mapEntry.getKey());\n\t\t}\n\t\telse {\n\t\t\tleft = PropertyLookup.forName(mapEntry.getKey());\n\t\t}\n\t\tvar parameterInformation = extractParameters(mapEntry.getValue());\n\t\tthis.propertyFilters.computeIfAbsent(property, ignored -> new HashSet<>())\n\t\t\t.add(new PropertyFilter(this.currentClause.get(), left, Operator.EQUALITY, mapEntry.getValue(),\n\t\t\t\t\tparameterInformation.names, parameterInformation.values));\n\t}\n\n\tvoid leave(Node node) {\n\t\tthis.currentPatternElement.removeFirstOccurrence(node);\n\t}\n\n\tvoid enter(Relationship relationship) {\n\n\t\trelationship.getSymbolicName().ifPresent(s -> store(s, relationship));\n\t\tthis.currentPatternElement.push(relationship);\n\t\tvar types = relationship.getDetails().getTypes().stream().map(Token::type).toList();\n\t\tthis.tokens.addAll(types);\n\n\t\tstoreRelations(relationship.getLeft(), relationship.getRight(), types,\n\t\t\t\trelationship.getDetails().getDirection());\n\t}\n\n\t/**\n\t * Stores the source and target of this relationships in incoming/outgoing and\n\t * undirected lists for processing after leaving the scope / statement (when all\n\t * labels are known).\n\t * @param left left hand side of the relation\n\t * @param right right hand side of the relation\n\t * @param types types of the relation\n\t * @param direction direction of the relation\n\t */\n\tprivate void storeRelations(Node left, Node right, List<Token> types, Relationship.Direction direction) {\n\n\t\tfinal Function<Node, Set<Token>> targetSupplier = unused -> new HashSet<>();\n\t\tswitch (direction) {\n\t\t\tcase UNI -> {\n\t\t\t\tthis.currentUndirectedRelations.computeIfAbsent(left, targetSupplier).addAll(types);\n\t\t\t\tthis.currentUndirectedRelations.computeIfAbsent(right, targetSupplier).addAll(types);\n\t\t\t}\n\t\t\tcase LTR -> {\n\t\t\t\tthis.currentOutgoingRelations.computeIfAbsent(left, targetSupplier).addAll(types);\n\t\t\t\tthis.currentIncomingRelations.computeIfAbsent(right, targetSupplier).addAll(types);\n\t\t\t}\n\t\t\tcase RTL -> {\n\t\t\t\tthis.currentIncomingRelations.computeIfAbsent(left, targetSupplier).addAll(types);\n\t\t\t\tthis.currentOutgoingRelations.computeIfAbsent(right, targetSupplier).addAll(types);\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid leave(Relationship relationship) {\n\t\tthis.currentPatternElement.removeFirstOccurrence(relationship);\n\t}\n\n\tvoid enter(org.neo4j.cypherdsl.core.Property property) {\n\n\t\tif (property.getNames().size() != 1) {\n\t\t\treturn;\n\t\t}\n\t\tvar lookup = property.getNames().get(0);\n\t\tif (lookup.isDynamicLookup()) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!(property.getContainerReference() instanceof SymbolicName s)) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar propertyName = new AtomicReference<String>();\n\t\tlookup.accept(segment -> {\n\t\t\tif (segment instanceof SymbolicName name) {\n\t\t\t\tpropertyName.compareAndSet(null, name.getValue());\n\t\t\t}\n\t\t});\n\n\t\tStatementCatalog.Property newProperty;\n\t\tvar patternElement = lookup(s);\n\t\tif (patternElement instanceof Node node) {\n\t\t\tnewProperty = new StatementCatalog.Property(getAllLabels(node), propertyName.get());\n\t\t}\n\t\telse if (patternElement instanceof Relationship relationship) {\n\t\t\tnewProperty = new StatementCatalog.Property(\n\t\t\t\t\trelationship.getDetails().getTypes().stream().map(Token::type).collect(Collectors.toSet()),\n\t\t\t\t\tpropertyName.get());\n\t\t}\n\t\telse {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.properties.add(newProperty);\n\t\tif (inCurrentCondition(property)) {\n\t\t\tthis.propertyFilters.computeIfAbsent(newProperty, ignored -> new HashSet<>())\n\t\t\t\t.add(extractPropertyCondition(newProperty, this.currentConditions.peek()));\n\t\t}\n\t}\n\n\tvoid enter(Parameter<?> parameter) {\n\t\tthis.allParameters.enter(parameter);\n\t}\n\n\tprivate boolean inCurrentCondition(org.neo4j.cypherdsl.core.Property property) {\n\t\tvar currentCondition = this.currentConditions.peek();\n\n\t\tif (currentCondition == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar result = new AtomicBoolean();\n\t\tcurrentCondition.accept(segment -> {\n\t\t\tif (segment == property) {\n\t\t\t\tresult.compareAndSet(false, true);\n\t\t\t}\n\t\t});\n\t\treturn result.get();\n\t}\n\n\tprivate PropertyFilter extractPropertyCondition(StatementCatalog.Property property,\n\t\t\torg.neo4j.cypherdsl.core.Condition condition) {\n\n\t\tvar left = new AtomicReference<Expression>();\n\t\tvar op = new AtomicReference<Operator>();\n\t\tvar right = new AtomicReference<Expression>();\n\t\tcondition.accept(new Visitor() {\n\t\t\tint cnt;\n\n\t\t\t@Override\n\t\t\tpublic void enter(Visitable segment) {\n\t\t\t\tif (++this.cnt != 2) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (segment instanceof Operator operator) {\n\t\t\t\t\top.compareAndSet(null, operator);\n\t\t\t\t}\n\t\t\t\telse if (segment instanceof Expression expression && !left.compareAndSet(null, expression)) {\n\t\t\t\t\tright.compareAndSet(null, expression);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void leave(Visitable segment) {\n\t\t\t\t--this.cnt;\n\t\t\t}\n\t\t});\n\t\tvar parameterInformation = extractParameters(left.get(), right.get());\n\t\treturn new PropertyFilter(this.currentClause.get(), left.get(), op.get(), right.get(),\n\t\t\t\tparameterInformation.names, parameterInformation.values);\n\t}\n\n\tvoid enter(NodeLabel label) {\n\t\tthis.tokens.add(new Token(Token.Type.NODE_LABEL, label.getValue()));\n\t\tvar currentCondition = this.currentConditions.peek();\n\t\tif (currentCondition instanceof HasLabelCondition hasLabelCondition) {\n\t\t\tthis.currentHasLabelCondition.get().add(Token.label(label));\n\t\t}\n\t}\n\n\tvoid enter(Labels labels) {\n\t\tlabels.getStaticValues().forEach(label -> this.tokens.add(StatementCatalog.Token.label(label)));\n\t\tthis.extractParametersFromLabels(labels, null);\n\t}\n\n\t@SuppressWarnings(\"squid:S3776\")\n\tvoid extractParametersFromLabels(Labels l, Labels.Type parent) {\n\t\tif (l == null) {\n\t\t\treturn;\n\t\t}\n\t\tvar current = l.getType();\n\t\textractParametersFromLabels(l.getLhs(), current);\n\t\tif (l.getValue() != null) {\n\t\t\tl.getValue().forEach(v -> v.accept(this));\n\t\t}\n\t\textractParametersFromLabels(l.getRhs(), current);\n\t}\n\n\tPatternElement lookup(SymbolicName s) {\n\t\tif (this.patternLookup.isEmpty()) {\n\t\t\tthrow new IllegalStateException(\"Invalid scope\");\n\t\t}\n\t\treturn this.patternLookup.peek().get(s);\n\t}\n\n\tvoid enter(org.neo4j.cypherdsl.core.Condition condition) {\n\t\tif (TYPE_OF_COMPOUND_CONDITION.equals(condition.getClass().getName())) {\n\t\t\treturn;\n\t\t}\n\t\tthis.currentConditions.push(condition);\n\t\tif (condition instanceof HasLabelCondition) {\n\t\t\tthis.currentHasLabelCondition.compareAndSet(null, new TreeSet<>());\n\t\t}\n\t}\n\n\tvoid enter(Literal<?> literal) {\n\t\tif (literal instanceof Asterisk || literal instanceof PeriodLiteral || literal instanceof RawLiteral.RawElement\n\t\t\t\t|| literal == LiteralBase.BLANK || literal == ListOperator.DOTS || literal instanceof Namespace) {\n\t\t\treturn;\n\t\t}\n\t\tthis.literals.add(literal);\n\t}\n\n\tvoid leave(org.neo4j.cypherdsl.core.Condition condition) {\n\t\tif (TYPE_OF_COMPOUND_CONDITION.equals(condition.getClass().getName())) {\n\t\t\treturn;\n\t\t}\n\t\tthis.currentConditions.pop();\n\n\t\tvar setOfRequiredTokens = this.currentHasLabelCondition.getAndSet(null);\n\t\tif (condition instanceof HasLabelCondition hasLabelCondition && setOfRequiredTokens != null) {\n\t\t\tAtomicReference<String> symbolicName = new AtomicReference<>();\n\t\t\thasLabelCondition.accept(segment -> {\n\t\t\t\tif (segment instanceof SymbolicName s) {\n\t\t\t\t\tsymbolicName.compareAndSet(null, s.getValue());\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.labelFilters.add(new StatementCatalog.LabelFilter(symbolicName.get(), setOfRequiredTokens));\n\t\t}\n\t}\n\n\tvoid store(SymbolicName s, PatternElement patternElement) {\n\t\tif (this.patternLookup.isEmpty()) {\n\t\t\tthrow new IllegalStateException(\"Invalid scope\");\n\t\t}\n\t\tvar currentScope = this.patternLookup.peek();\n\t\t// Don't overwrite in same scope or when imported,\n\t\t// size == 1 catering for with clauses on top level\n\t\tif (currentScope.containsKey(s)\n\t\t\t\t&& (this.scopingStrategy.getCurrentImports().contains(s) || this.patternLookup.size() == 1)) {\n\t\t\treturn;\n\t\t}\n\t\tcurrentScope.put(s, patternElement);\n\t}\n\n\tprivate ParameterInformation extractParameters(Expression... expressions) {\n\n\t\tvar parameterCollectingVisitor = new ParameterCollectingVisitor(this.statementContext,\n\t\t\t\tthis.renderConstantsAsParameters);\n\t\tfor (Expression expression : expressions) {\n\t\t\tif (expression == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\texpression.accept(parameterCollectingVisitor);\n\t\t}\n\t\treturn parameterCollectingVisitor.getResult();\n\t}\n\n\t/**\n\t * A holder for the relationship types connected to node labels.\n\t *\n\t * @param outgoing outgoing types\n\t * @param incoming incoming types\n\t * @param undirected undirected connections\n\t */\n\trecord Relationships(Set<Token> outgoing, Set<Token> incoming, Set<Token> undirected) {\n\n\t\tRelationships() {\n\t\t\tthis(new HashSet<>(), new HashSet<>(), new HashSet<>());\n\t\t}\n\n\t\tstatic Relationships empty() {\n\t\t\treturn new Relationships(Set.of(), Set.of(), Set.of());\n\t\t}\n\n\t\tRelationships copy() {\n\t\t\treturn new Relationships(Set.copyOf(this.outgoing), Set.copyOf(this.incoming), Set.copyOf(this.undirected));\n\t\t}\n\t}\n\n\tstatic final class DefaultStatementCatalog implements StatementCatalog {\n\n\t\tprivate final Set<Token> tokens;\n\n\t\tprivate final Set<Property> properties;\n\n\t\tprivate final Collection<LabelFilter> labelFilters;\n\n\t\tprivate final Map<Property, Collection<PropertyFilter>> propertyFilters;\n\n\t\tprivate final Set<Expression> identifiableExpressions;\n\n\t\tprivate final ParameterInformation parameterInformation;\n\n\t\tprivate final Map<Token, Relationships> relationships;\n\n\t\tprivate final Set<Literal<?>> literals;\n\n\t\t@SuppressWarnings(\"squid:S107\") // Totally fine with that number of args.\n\t\tDefaultStatementCatalog(Set<Token> tokens, Set<LabelFilter> labelFilters, Set<Property> properties,\n\t\t\t\tMap<Property, Set<PropertyFilter>> propertyFilters, Collection<Expression> identifiableExpressions,\n\t\t\t\tParameterInformation parameterInformation, Map<Token, Relationships> relationships,\n\t\t\t\tSet<Literal<?>> literals) {\n\t\t\tthis.tokens = Collections.unmodifiableSet(tokens);\n\t\t\tthis.labelFilters = Collections.unmodifiableSet(labelFilters);\n\n\t\t\tthis.properties = Collections.unmodifiableSet(properties);\n\t\t\tthis.propertyFilters = propertyFilters.entrySet()\n\t\t\t\t.stream()\n\t\t\t\t.collect(Collectors.toUnmodifiableMap(Map.Entry::getKey,\n\t\t\t\t\t\te -> Collections.unmodifiableSet(e.getValue())));\n\n\t\t\tthis.identifiableExpressions = (identifiableExpressions instanceof Set<Expression> s)\n\t\t\t\t\t? Collections.unmodifiableSet(s) : Set.copyOf(identifiableExpressions);\n\t\t\tthis.parameterInformation = parameterInformation;\n\n\t\t\tthis.relationships = relationships.entrySet()\n\t\t\t\t.stream()\n\t\t\t\t.collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, e -> e.getValue().copy()));\n\n\t\t\tthis.literals = Collections.unmodifiableSet(literals);\n\t\t}\n\n\t\t@Override\n\t\tpublic Set<Token> getAllTokens() {\n\t\t\treturn this.tokens;\n\t\t}\n\n\t\t@Override\n\t\tpublic Set<Property> getProperties() {\n\t\t\treturn this.properties;\n\t\t}\n\n\t\t@Override\n\t\tpublic Collection<LabelFilter> getAllLabelFilters() {\n\t\t\treturn this.labelFilters;\n\t\t}\n\n\t\t@Override\n\t\tpublic Map<Property, Collection<PropertyFilter>> getAllPropertyFilters() {\n\t\t\treturn this.propertyFilters;\n\t\t}\n\n\t\t@Override\n\t\tpublic Set<Expression> getIdentifiableExpressions() {\n\t\t\treturn this.identifiableExpressions;\n\t\t}\n\n\t\t@Override\n\t\tpublic Map<String, Object> getParameters() {\n\t\t\treturn this.parameterInformation.values;\n\t\t}\n\n\t\t@Override\n\t\tpublic Collection<String> getParameterNames() {\n\t\t\treturn this.parameterInformation.names;\n\t\t}\n\n\t\t@Override\n\t\tpublic Map<String, String> getRenamedParameters() {\n\t\t\treturn this.parameterInformation.renames;\n\t\t}\n\n\t\t@Override\n\t\tpublic Collection<Token> getOutgoingRelations(Token label) {\n\n\t\t\treturn extractRelations(label, Relationships::outgoing);\n\t\t}\n\n\t\tprivate Collection<Token> extractRelations(Token label, Function<Relationships, Set<Token>> tokenProvider) {\n\t\t\tif (label.type() != Token.Type.NODE_LABEL) {\n\t\t\t\tthrow new IllegalArgumentException(label + \" must be a node label, not a relationship type\");\n\t\t\t}\n\n\t\t\treturn tokenProvider.apply(this.relationships.getOrDefault(label, Relationships.empty()));\n\t\t}\n\n\t\t@Override\n\t\tpublic Collection<Token> getTargetNodes(Token type) {\n\n\t\t\tif (type.type() != Token.Type.RELATIONSHIP_TYPE) {\n\t\t\t\tthrow new IllegalArgumentException(type + \" must be a relationship type, not a node label\");\n\t\t\t}\n\n\t\t\treturn this.relationships.entrySet()\n\t\t\t\t.stream()\n\t\t\t\t.filter(e -> e.getValue().incoming().contains(type))\n\t\t\t\t.map(Map.Entry::getKey)\n\t\t\t\t.collect(Collectors.toSet());\n\t\t}\n\n\t\t@Override\n\t\tpublic Collection<Token> getIncomingRelations(Token label) {\n\n\t\t\treturn extractRelations(label, Relationships::incoming);\n\t\t}\n\n\t\t@Override\n\t\tpublic Collection<Token> getSourceNodes(Token type) {\n\n\t\t\tif (type.type() != Token.Type.RELATIONSHIP_TYPE) {\n\t\t\t\tthrow new IllegalArgumentException(type + \" must be a relationship type, not a node label\");\n\t\t\t}\n\n\t\t\treturn this.relationships.entrySet()\n\t\t\t\t.stream()\n\t\t\t\t.filter(e -> e.getValue().outgoing().contains(type))\n\t\t\t\t.map(Map.Entry::getKey)\n\t\t\t\t.collect(Collectors.toSet());\n\t\t}\n\n\t\t@Override\n\t\tpublic Collection<Token> getUndirectedRelations(Token label) {\n\n\t\t\treturn extractRelations(label, Relationships::undirected);\n\t\t}\n\n\t\t@Override\n\t\tpublic Set<Literal<?>> getLiterals() {\n\t\t\treturn this.literals;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/StatementContext.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.internal.DefaultStatementContext;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Context for while rendering a statement.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\npublic sealed interface StatementContext permits DefaultStatementContext {\n\n\t/**\n\t * Gets or creates the name of a parameter.\n\t * @param parameter the parameter whose name should be retrieved\n\t * @return the name of the parameter or a generated name\n\t */\n\tString getParameterName(Parameter<?> parameter);\n\n\t/**\n\t * Resolves a {@link SymbolicName symbolic name} into a string: A symbolic name can be\n\t * a placeholder without an actual value. In such cases a value is randomly generated\n\t * and will stay constant for that name as long as the statement exists. In case the\n\t * {@code symbolicName} has a constant value it will be returned,\n\t * @param symbolicName the symbolic name to resolve\n\t * @return a value for the given name\n\t * @since 2023.0.3\n\t */\n\tString resolve(SymbolicName symbolicName);\n\n\t/**\n\t * Checks whether a given {@link SymbolicName symbolic name} has been resolved in this\n\t * {@link StatementContext context}.\n\t * @param symbolicName the symbolic name to check\n\t * @return true if the given name has already been resolved in this context\n\t * @since 2023.0.3\n\t */\n\tboolean isResolved(SymbolicName symbolicName);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/StringLiteral.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Locale;\nimport java.util.Optional;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * The string representation of a string literal will be a quoted Cypher string in single\n * tickmarks with escaped reserved characters.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class StringLiteral extends LiteralBase<CharSequence> {\n\n\tprivate static final Pattern RESERVED_CHARS = Pattern.compile(\"([\" + Pattern.quote(\"\\\\'\\\"\") + \"])\");\n\n\tprivate static final String QUOTED_LITERAL_FORMAT = \"'%s'\";\n\n\tStringLiteral(CharSequence content) {\n\t\tsuper(content);\n\t}\n\n\t/**\n\t * Escapes a string so that it can be used as a string literal in both single\n\t * tickmarks ({@literal '}) and quotes ({@literal \"}).\n\t * @param unescapedString the string to escape\n\t * @return an empty optional when the unescaped string is {@literal null}, an escaped\n\t * string otherwise\n\t */\n\tstatic Optional<String> escapeString(CharSequence unescapedString) {\n\n\t\tif (unescapedString == null) {\n\t\t\treturn Optional.empty();\n\t\t}\n\n\t\tfinal StringBuilder buffer = new StringBuilder();\n\t\tMatcher matcher = RESERVED_CHARS.matcher(unescapedString);\n\t\twhile (matcher.find()) {\n\t\t\tmatcher.appendReplacement(buffer, \"\\\\\\\\\\\\\" + matcher.group(1));\n\t\t}\n\t\tmatcher.appendTail(buffer);\n\t\treturn Optional.of(buffer.toString());\n\t}\n\n\t@Override\n\tpublic String asString() {\n\n\t\tfinal Optional<String> escapedContent = escapeString(getContent());\n\t\treturn String.format(Locale.ENGLISH, QUOTED_LITERAL_FORMAT, escapedContent.orElse(\"\"));\n\t}\n\n\t@Override\n\tpublic CharSequence getContent() {\n\t\treturn this.content;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Subquery.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Represents a \"callable\" sub-query. A sub-query can contain statement that returns\n * something (standard statements, union statements and calls to stored procedures,\n * yielding their elements). Sub-queries can be nested.\n *\n * @author Michael J. Simons\n * @neo4j.version 4.0.0\n * @since 2020.1.2\n */\n@API(status = STABLE, since = \"2020.1.2\")\n@Neo4jVersion(minimum = \"4.0.0\")\npublic final class Subquery extends AbstractClause implements Clause {\n\n\tprivate final ImportingWith importingWith;\n\n\tprivate final Statement statement;\n\n\tprivate final RawLiteral rawStatement;\n\n\tprivate Subquery(ImportingWith importingWith, Statement statement) {\n\t\tthis.importingWith = importingWith;\n\t\tthis.statement = statement;\n\t\tthis.rawStatement = null;\n\t}\n\n\tprivate Subquery(RawLiteral rawStatement) {\n\t\tthis.rawStatement = rawStatement;\n\t\tthis.importingWith = null;\n\t\tthis.statement = null;\n\t}\n\n\tstatic Subquery raw(String format, Object... mixedArgs) {\n\t\treturn new Subquery(RawLiteral.create(format, mixedArgs));\n\t}\n\n\t/**\n\t * The {@code statement} can either be a unit sub-query, used to modify the graph.\n\t * Those won't impact the amount of rows returned by the enclosing query. In case it's\n\t * a statement that returns or yields values it must ensure that it does not return\n\t * variables with the same names as variables in the enclosing query.\n\t * @param statement the statement to wrap into a sub-query.\n\t * @param imports the variables imported into the subquery\n\t * @return a sub-query.\n\t */\n\tstatic Subquery call(Statement statement, IdentifiableElement... imports) {\n\t\treturn new Subquery(ImportingWith.of(imports), statement);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tif (this.rawStatement != null) {\n\t\t\tthis.rawStatement.accept(visitor);\n\t\t}\n\t\telse {\n\t\t\tthis.importingWith.accept(visitor);\n\t\t\tthis.statement.accept(visitor);\n\t\t}\n\t\tvisitor.leave(this);\n\t}\n\n\t@API(status = INTERNAL)\n\tInTransactions inTransactionsOf(Integer rows) {\n\t\treturn new InTransactions(this, rows);\n\t}\n\n\t/**\n\t * {@return <code>true</code> if this sub-query yields any items}\n\t */\n\t@API(status = INTERNAL)\n\tpublic boolean doesReturnOrYield() {\n\t\treturn this.statement != null && this.statement.doesReturnOrYield();\n\t}\n\n\t/**\n\t * {@return the importing with clause if any}\n\t */\n\t@API(status = INTERNAL)\n\tpublic With importingWith() {\n\t\tvar imports = (this.importingWith != null) ? this.importingWith.imports() : null;\n\t\tif (imports == null && this.statement instanceof ClausesBasedStatement cbs) {\n\t\t\treturn cbs.getClauses()\n\t\t\t\t.stream()\n\t\t\t\t.findFirst()\n\t\t\t\t.filter(With.class::isInstance)\n\t\t\t\t.map(With.class::cast)\n\t\t\t\t.orElse(null);\n\t\t}\n\t\treturn imports;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/SubqueryExpression.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\n/**\n * A sub-query expression can either be an {@link ExistentialSubquery EXISTS-tential} or a\n * {@link CountExpression COUNT} expression as of Neo4j 5.\n *\n * @author Michael J. Simons\n * @since 2023.0.0\n *\n */\npublic sealed interface SubqueryExpression extends Expression\n\t\tpermits ExistentialSubquery, CountExpression, CollectExpression {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/SubqueryExpressionBuilder.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Something that can build counting sub-queries. Might be used in the future for\n * existential sub-queries, too.\n *\n * @author Michael J. Simons\n * @since 2023.9.0\n */\n@API(status = STABLE, since = \"2023.9.0\")\npublic interface SubqueryExpressionBuilder {\n\n\t/**\n\t * Creates a {@literal COUNT} sub-query expressions from at least one pattern.\n\t * @param requiredPattern one pattern is required\n\t * @param patternElement optional pattern\n\t * @return the immutable {@link CountExpression}\n\t * @since 2023.9.0\n\t */\n\tCountExpression count(PatternElement requiredPattern, PatternElement... patternElement);\n\n\t/**\n\t * Creates a {@literal COUNT} with an inner {@literal UNION} sub-query.\n\t * @param union the union that will be the source of the {@literal COUNT} sub-query\n\t * @return the immutable {@link CountExpression}\n\t * @since 2023.9.0\n\t */\n\tCountExpression count(Statement.UnionQuery union);\n\n\t/**\n\t * Creates a {@literal COLLECT} subquery from a statement, including its filters and\n\t * conditions. The statement must return exactly one column. It must however not\n\t * contain any updates. While it would render syntactically correct Cypher, Neo4j does\n\t * not support updates inside counting sub-queries.\n\t * <p>\n\t * To avoid confusion, shadowing of imported variables is not allowed. An outside\n\t * scope variable is shadowed when a newly introduced variable within the inner scope\n\t * is defined with the same variable.\n\t * @param statement the statement to be passed to {@code COLLECT{}}\n\t * @return a collecting sub-query.\n\t * @since 2023.9.0\n\t */\n\tCollectExpression collect(Statement statement);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/SymbolicName.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\n\nimport org.apiguardian.api.API;\nimport org.apiguardian.api.API.Status;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\nimport org.neo4j.cypherdsl.core.utils.LRUCache;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * A symbolic name to identify nodes, relationships and aliased items.\n * <p>\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/SchemaName.html\">SchemaName</a>\n * <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/SymbolicName.html\">SymbolicName</a>\n * <p>\n * While OpenCypher extends the <a href=\"https://unicode.org/reports/tr31/\">UNICODE\n * IDENTIFIER AND PATTERN SYNTAX</a> with some characters, this DSL uses the same\n * identifier Java itself uses for simplicity and until otherwise needed.\n *\n * @author Michael J. Simons\n * @author Andreas Berger\n * @since 1.0\n */\n@API(status = Status.EXPERIMENTAL, since = \"1.0\")\npublic final class SymbolicName implements Expression, IdentifiableElement {\n\n\tprivate static final Map<String, SymbolicName> CACHE = Collections.synchronizedMap(new LRUCache<>(32));\n\n\tprivate final String value;\n\n\tprivate SymbolicName(String value) {\n\t\tthis.value = value;\n\t}\n\n\tstatic SymbolicName of(String name) {\n\n\t\tAssertions.hasText(name, \"Name must not be empty.\");\n\t\treturn CACHE.computeIfAbsent(name, SymbolicName::new);\n\t}\n\n\tstatic SymbolicName unsafe(String name) {\n\n\t\tAssertions.hasText(name, \"Name must not be empty.\");\n\t\treturn new SymbolicName(name);\n\t}\n\n\tstatic SymbolicName unresolved() {\n\n\t\treturn new SymbolicName(null);\n\t}\n\n\t/**\n\t * {@return the value of this symbolic name}\n\t */\n\t@API(status = INTERNAL)\n\tpublic String getValue() {\n\t\treturn this.value;\n\t}\n\n\t/**\n\t * Creates a new symbolic name by concatenating {@code otherValue} to this names\n\t * value. Returns {@literal this} if {@code otherValue} is empty.\n\t * @param otherValue the value to concat.\n\t * @return a new symbolic name\n\t */\n\tpublic SymbolicName concat(String otherValue) {\n\n\t\tAssertions.notNull(otherValue, \"Value to concat must not be null.\");\n\t\tif (otherValue.isEmpty()) {\n\t\t\treturn this;\n\t\t}\n\t\treturn SymbolicName.of(this.value + otherValue);\n\t}\n\n\t/**\n\t * A list will never be a valid entry for a map projection, so this convenient method\n\t * prevents trying to create one from a list of objects. It will delegate to\n\t * {@link #project(Object...)} with the content of the list.\n\t * @param entries a list of entries for the projection\n\t * @return a map projection.\n\t * @since 2021.0.0\n\t */\n\tpublic MapProjection project(List<Object> entries) {\n\t\treturn project(entries.toArray());\n\t}\n\n\t/**\n\t * Creates a map projection based on this node. The node needs a symbolic name for\n\t * this to work.\n\t * <p>\n\t * Entries of type {@code String} in {@code entries} followed by an {@link Expression}\n\t * will be treated as map keys pointing to the expression in the projection,\n\t * {@code String} entries alone will be treated as property lookups on the node.\n\t * @param entries a list of entries for the projection\n\t * @return a map projection.\n\t * @since 2021.0.0\n\t */\n\tpublic MapProjection project(Object... entries) {\n\t\treturn MapProjection.create(this, entries);\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (this == o) {\n\t\t\treturn true;\n\t\t}\n\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\treturn false;\n\t\t}\n\t\t// Unresolved values are only equal to themselves\n\t\tif (this.value == null) {\n\t\t\treturn false;\n\t\t}\n\t\tSymbolicName that = (SymbolicName) o;\n\t\treturn this.value.equals(that.value);\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn (this.value != null) ? Objects.hash(this.value) : super.hashCode();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn (this.value != null) ? RendererBridge.render(this) : \"Unresolved SymbolicName\";\n\t}\n\n\t@Override\n\tpublic Expression asExpression() {\n\t\treturn this;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/TemporalLiteral.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.time.LocalTime;\nimport java.time.OffsetTime;\nimport java.time.ZonedDateTime;\nimport java.time.format.DateTimeFormatter;\nimport java.time.temporal.TemporalAccessor;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A literal representing a temporal value to be formatted in a way that Neo4j's Cypher\n * understands it.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = STABLE, since = \"2021.1.0\")\npublic final class TemporalLiteral extends LiteralBase<TemporalAccessor> {\n\n\tprivate final String value;\n\n\tTemporalLiteral(TemporalAccessor content) {\n\t\tsuper(content);\n\n\t\tString method;\n\t\tDateTimeFormatter formatter;\n\t\tif (content instanceof LocalDate) {\n\t\t\tmethod = \"date\";\n\t\t\tformatter = DateTimeFormatter.ISO_LOCAL_DATE;\n\t\t}\n\t\telse if (content instanceof LocalDateTime) {\n\t\t\tmethod = \"localdatetime\";\n\t\t\tformatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;\n\t\t}\n\t\telse if (content instanceof ZonedDateTime) {\n\t\t\tmethod = \"datetime\";\n\t\t\tformatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;\n\t\t}\n\t\telse if (content instanceof LocalTime) {\n\t\t\tmethod = \"localtime\";\n\t\t\tformatter = DateTimeFormatter.ISO_LOCAL_TIME;\n\t\t}\n\t\telse if (content instanceof OffsetTime) {\n\t\t\tmethod = \"time\";\n\t\t\tformatter = DateTimeFormatter.ISO_OFFSET_TIME;\n\t\t}\n\t\telse {\n\t\t\tthrow new UnsupportedLiteralException(content);\n\t\t}\n\t\tthis.value = String.format(\"%s('%s')\", method, formatter.format(content));\n\t}\n\n\t@Override\n\tpublic String asString() {\n\t\treturn this.value;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/TreeNode.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayDeque;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Deque;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.NoSuchElementException;\nimport java.util.Queue;\nimport java.util.function.Consumer;\nimport java.util.function.Function;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\n/**\n * A mutable tree structure providing\n * <a href=\"https://en.wikipedia.org/wiki/Breadth-first_search\">Breadth-first search</a>\n * (aka in-level order traversal) and pre-ordered\n * <a href=\"https://en.wikipedia.org/wiki/Depth-first_search\">depth-first search</a>. This\n * class is thread-safe.\n *\n * @param <E> the type of each node value\n * @author Michael J. Simons\n * @since 2023.2.0\n */\n@API(status = API.Status.EXPERIMENTAL, since = \"2023.2.0\")\npublic final class TreeNode<E> {\n\n\tprivate final TreeNode<E> parent;\n\n\tprivate final int level;\n\n\tprivate final List<TreeNode<E>> children;\n\n\tprivate final E value;\n\n\tprivate TreeNode(TreeNode<E> parent, int level, E value) {\n\t\tthis.parent = parent;\n\t\tthis.level = level;\n\t\tthis.value = value;\n\t\tthis.children = new ArrayList<>();\n\t}\n\n\t/**\n\t * Creates a tree from a {@link Statement}. This allows to visit all elements of\n\t * statement without implementing custom {@link Visitor visitors.} The root of the\n\t * returned tree will always be the statement.\n\t * @param statement the statement that should be represented as a tree\n\t * @return a tree with the statement as root\n\t */\n\tpublic static TreeNode<Visitable> from(Statement statement) {\n\t\tvar visitor = new TreeBuildingVisitor();\n\t\tstatement.accept(visitor);\n\t\treturn visitor.root;\n\t}\n\n\t/**\n\t * Creates a new tree, starting at the root.\n\t * @param value the actual value\n\t * @param <E> the type of the value\n\t * @return the new node\n\t */\n\tstatic <E> TreeNode<E> root(E value) {\n\t\treturn new TreeNode<>(null, 0, value);\n\t}\n\n\t/**\n\t * Appends a value to this node and thus creating a new child node. This node will be\n\t * modified and keeps track of the child node.\n\t * @param childValue the value of the new child node\n\t * @return the new child (this node will be the parent of the new node)\n\t */\n\tTreeNode<E> append(E childValue) {\n\t\tvar newChild = new TreeNode<>(this, this.level + 1, childValue);\n\t\tthis.children.add(newChild);\n\t\treturn newChild;\n\t}\n\n\t/**\n\t * {@return <code>true</code> if this is the root node}\n\t */\n\tpublic boolean isRoot() {\n\t\treturn this.parent == null;\n\t}\n\n\t/**\n\t * Returns the level or the height in this tree in which {@code 0} is the level of the\n\t * root node.\n\t * @return the level or the height in this tree\n\t */\n\tpublic int getLevel() {\n\t\treturn this.level;\n\t}\n\n\t/**\n\t * {@return the parent of this node or <code>null</code> if this is a root node}\n\t */\n\tpublic TreeNode<E> getParent() {\n\t\treturn this.parent;\n\t}\n\n\t/**\n\t * {@return an immutable collection of this nodes children}\n\t */\n\tpublic Collection<TreeNode<E>> getChildren() {\n\t\treturn List.copyOf(this.children);\n\t}\n\n\t/**\n\t * {@return the value of this node}\n\t */\n\tpublic E getValue() {\n\t\treturn this.value;\n\t}\n\n\t/**\n\t * {@return a breadth-first iterator of this node and it's children}\n\t */\n\tpublic Iterator<TreeNode<E>> breadthFirst() {\n\t\treturn new BreadthFirstIterator<>(this);\n\t}\n\n\t/**\n\t * {@return a depth-first, pre-ordered iterator of this node and it's children}\n\t */\n\tpublic Iterator<TreeNode<E>> preOrder() {\n\t\treturn new PreOrderIterator<>(this);\n\t}\n\n\t/**\n\t * Creates an ASCII representation of this node and its children.\n\t * @param target the target to which to print this tree to\n\t * @param toString how to format nodes if this type\n\t */\n\tpublic void printTo(Consumer<CharSequence> target, Function<TreeNode<E>, String> toString) {\n\t\tthis.printTo0(target, toString, this, \"\", true);\n\t}\n\n\tprivate void printTo0(Consumer<CharSequence> target, Function<TreeNode<E>, String> toString, TreeNode<E> node,\n\t\t\tString prefix, boolean isTail) {\n\n\t\tvar localValue = toString.apply(node);\n\t\tvar connector = isTail ? \"└── \" : \"├── \";\n\t\tif (this == node) {\n\t\t\tconnector = \"\";\n\t\t}\n\t\ttarget.accept(prefix + connector + localValue + \"\\n\");\n\n\t\tvar newPrefix = prefix + (isTail ? \" \".repeat(connector.length()) : \"│   \");\n\t\tfor (int i = 0; i < node.children.size(); ++i) {\n\t\t\tvar child = node.children.get(i);\n\t\t\tprintTo0(target, toString, child, newPrefix, i + 1 == node.getChildren().size());\n\t\t}\n\t}\n\n\tprivate static final class TreeBuildingVisitor implements Visitor {\n\n\t\tfinal Deque<TreeNode<Visitable>> nodes = new ArrayDeque<>();\n\n\t\tTreeNode<Visitable> root;\n\n\t\t@Override\n\t\tpublic void enter(Visitable segment) {\n\t\t\tvar currentParent = this.nodes.peek();\n\t\t\tif (currentParent == null) {\n\t\t\t\tcurrentParent = TreeNode.root(segment);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tcurrentParent = currentParent.append(segment);\n\t\t\t}\n\n\t\t\tthis.nodes.push(currentParent);\n\t\t}\n\n\t\t@Override\n\t\tpublic void leave(Visitable segment) {\n\t\t\tthis.root = this.nodes.pop();\n\t\t}\n\n\t}\n\n\tprivate static final class BreadthFirstIterator<E> implements Iterator<TreeNode<E>> {\n\n\t\tprivate final Queue<TreeNode<E>> queue;\n\n\t\tBreadthFirstIterator(TreeNode<E> root) {\n\t\t\tthis.queue = new ArrayDeque<>();\n\t\t\tthis.queue.add(root);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean hasNext() {\n\t\t\treturn !this.queue.isEmpty();\n\t\t}\n\n\t\t@Override\n\t\tpublic TreeNode<E> next() {\n\t\t\tif (this.queue.isEmpty()) {\n\t\t\t\tthrow new NoSuchElementException();\n\t\t\t}\n\t\t\tvar n = this.queue.remove();\n\t\t\tthis.queue.addAll(n.children);\n\t\t\treturn n;\n\t\t}\n\n\t}\n\n\tprivate static final class PreOrderIterator<E> implements Iterator<TreeNode<E>> {\n\n\t\tprivate final Deque<Iterator<TreeNode<E>>> stack;\n\n\t\tPreOrderIterator(TreeNode<E> root) {\n\t\t\tthis.stack = new ArrayDeque<>();\n\t\t\tthis.stack.push(List.of(root).iterator());\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean hasNext() {\n\t\t\treturn !this.stack.isEmpty() && this.stack.peek().hasNext();\n\t\t}\n\n\t\t@Override\n\t\tpublic TreeNode<E> next() {\n\t\t\tif (this.stack.isEmpty()) {\n\t\t\t\tthrow new NoSuchElementException();\n\t\t\t}\n\t\t\tvar nodesUpNext = this.stack.peek();\n\t\t\tvar currentNode = nodesUpNext.next();\n\n\t\t\tif (!nodesUpNext.hasNext()) {\n\t\t\t\tthis.stack.pop();\n\t\t\t}\n\n\t\t\tif (!currentNode.children.isEmpty()) {\n\t\t\t\tthis.stack.push(currentNode.children.iterator());\n\t\t\t}\n\n\t\t\treturn currentNode;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/UnionPart.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Represents a part of a union.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class UnionPart implements Visitable {\n\n\tprivate final boolean all;\n\n\tprivate final Statement query;\n\n\tUnionPart(boolean all, Statement query) {\n\t\tthis.all = all;\n\t\tthis.query = query;\n\t}\n\n\t/**\n\t * {@return <code>true</code>, if an <code>ALL</code> keyword should be rendered}\n\t */\n\t@API(status = INTERNAL)\n\tpublic boolean isAll() {\n\t\treturn this.all;\n\t}\n\n\tStatement getQuery() {\n\t\treturn this.query;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.query.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/UnionQueryImpl.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.utils.Assertions;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Implementation of a {@code UNION} query.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = INTERNAL, since = \"1.0\")\nfinal class UnionQueryImpl extends AbstractStatement implements Statement.UnionQuery {\n\n\tprivate final boolean all;\n\n\tprivate final Statement firstQuery;\n\n\tprivate final List<UnionPart> additionalQueries;\n\n\tprivate UnionQueryImpl(boolean all, Statement firstQuery, List<UnionPart> additionalQueries) {\n\t\tthis.all = all;\n\t\tthis.firstQuery = firstQuery;\n\t\tthis.additionalQueries = additionalQueries;\n\t}\n\n\t@SuppressWarnings(\"squid:S6416\") // This is about the assertion, Sonar suddenly things\n\t\t\t\t\t\t\t\t\t\t// this is an issue: Idk. We want the exception.\n\tstatic UnionQueryImpl create(boolean unionAll, List<Statement> queries) {\n\n\t\tAssertions.isTrue(queries != null && queries.size() >= 2, \"At least two queries are needed.\");\n\n\t\t@SuppressWarnings(\"squid:S2259\") // Really, we asserted it\n\t\tList<UnionPart> unionParts = queries.stream().skip(1).map(q -> new UnionPart(unionAll, q)).toList();\n\t\treturn new UnionQueryImpl(unionAll, queries.get(0), unionParts);\n\t}\n\n\t/**\n\t * Creates a new union query by appending more parts.\n\t * @param newAdditionalQueries more additional queries\n\t * @return a new union query\n\t */\n\tUnionQueryImpl addAdditionalQueries(List<Statement> newAdditionalQueries) {\n\n\t\tList<Statement> queries = new ArrayList<>();\n\t\tqueries.add(this.firstQuery);\n\t\tqueries.addAll(this.additionalQueries.stream().map(UnionPart::getQuery).toList());\n\t\tqueries.addAll(newAdditionalQueries);\n\n\t\treturn create(this.isAll(), queries);\n\t}\n\n\tboolean isAll() {\n\t\treturn this.all;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.firstQuery.accept(visitor);\n\t\tthis.additionalQueries.forEach(q -> q.accept(visitor));\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Unwind.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Unwind.html\">Unwind</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Unwind extends AbstractClause implements ReadingClause {\n\n\tprivate final Expression expressionToUnwind;\n\n\tUnwind(Expression expressionToUnwind, String variable) {\n\n\t\tthis.expressionToUnwind = ((expressionToUnwind instanceof Aliased aliased) ? aliased.asName()\n\t\t\t\t: expressionToUnwind)\n\t\t\t.as(variable);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.expressionToUnwind.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/UpdatingClause.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\n/**\n * Representation of any writing aka updating clause.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\npublic interface UpdatingClause extends Clause {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Use.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\n/**\n * The {@literal USE} clause can be prepended to statements or be used in a\n * {@literal CALL} subquery. It is meant to select composite databases or constituents\n * thereof.\n *\n * @author Michael J. Simons\n * @since 2023.0.0\n */\npublic sealed interface Use extends Clause permits UseClauseImpl {\n\n\t/**\n\t * {@return <code>true</code> if this instance requires dynamic graph lookups}\n\t */\n\tboolean dynamic();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/UseClauseImpl.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.SchemaNamesBridge;\n\n/**\n * The factory methods are on the concrete class, as they should not be exposed to the\n * outside via the interface.\n *\n * @param target the target of the {@code USE} clause\n * @param dynamic {@code true} if dynamic graph lookups are to be used\n * @author Michael J. Simons\n * @since 2023.0.0\n */\nrecord UseClauseImpl(Expression target, boolean dynamic) implements Use {\n\n\tstatic Use of(String target) {\n\t\tvar components = target.split(\"\\\\.\");\n\t\tExpression targetExpression;\n\t\tif (components.length == 1) {\n\t\t\ttargetExpression = Cypher.raw(SchemaNamesBridge.sanitize(components[0], false).orElseThrow());\n\t\t}\n\t\telse {\n\t\t\ttargetExpression = Cypher.raw(SchemaNamesBridge.sanitize(components[0], false)\n\t\t\t\t.flatMap(composite -> SchemaNamesBridge.sanitize(components[1], false).map(v -> composite + \".\" + v))\n\t\t\t\t.orElseThrow());\n\t\t}\n\n\t\treturn new UseClauseImpl(targetExpression, false);\n\t}\n\n\tstatic Use of(Expression target) {\n\t\treturn new UseClauseImpl(target,\n\t\t\t\t!(target instanceof FunctionInvocation fi) || !\"graph.byName\".equals(fi.getFunctionName()));\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.target.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/Where.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Roughly corresponding to <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/Match.html#Where\">Where</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class Where implements Visitable {\n\n\tprivate final Condition condition;\n\n\tWhere(Condition condition) {\n\t\tthis.condition = condition;\n\t}\n\n\t/**\n\t * Creates a new {@literal WHERE}.\n\t * @param optionalWhere an optional expression that must be usable\n\t * {@link Expression#asCondition() \"as condition\"}.\n\t * @return a {@literal WHERE} expression or null when {@code optionalWhere} has been\n\t * {@literal NULL}\n\t * @since 2022.0.0\n\t */\n\tpublic static Where from(Expression optionalWhere) {\n\t\treturn (optionalWhere != null) ? new Where(optionalWhere.asCondition()) : null;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\n\t\tthis.condition.accept(visitor);\n\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/With.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.EnterResult;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.Distinct;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/With.html\">With</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic final class With implements Visitable, Clause {\n\n\tprivate final Distinct distinct;\n\n\tprivate final ReturnBody body;\n\n\tprivate final Where where;\n\n\tWith(Return returnClause, Where where) {\n\t\tthis.distinct = returnClause.getDistinct();\n\t\tthis.body = returnClause.getBody();\n\t\tthis.where = where;\n\t}\n\n\tWith(boolean distinct, ExpressionList returnItems, Order order, Skip skip, Limit limit, Where where) {\n\t\tthis.distinct = distinct ? Distinct.INSTANCE : null;\n\t\tthis.body = new ReturnBody(returnItems, order, skip, limit);\n\t\tthis.where = where;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tif (visitor.enterWithResult(this) == EnterResult.CONTINUE) {\n\t\t\tVisitable.visitIfNotNull(this.distinct, visitor);\n\t\t\tthis.body.accept(visitor);\n\t\t\tVisitable.visitIfNotNull(this.where, visitor);\n\t\t}\n\t\tvisitor.leave(this);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn RendererBridge.render(this);\n\t}\n\n\t@API(status = INTERNAL)\n\tpublic List<Expression> getItems() {\n\t\treturn this.body.getReturnItems();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/annotations/CheckReturnValue.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.annotations;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport org.apiguardian.api.API;\n\n/**\n * Simple version of the JSR 305 annotation that allows detecting accidentally omitted\n * calls to\n * {@link org.neo4j.cypherdsl.core.Cypher#match(org.neo4j.cypherdsl.core.PatternElement...)}\n * ()} and the likes in IntelliJ.\n * <p>\n * This annotation is {@link org.apiguardian.api.API.Status#INTERNAL}. Clients should not\n * rely on its presence.\n *\n * @author Lukas Eder\n * @author Michael J. Simons\n * @see <a href=\n * \"https://github.com/jOOQ/jOOQ/issues/11718\">https://github.com/jOOQ/jOOQ/issues/11718</a>\n * @see <a href=\n * \"https://youtrack.jetbrains.com/issue/IDEA-265263\">https://youtrack.jetbrains.com/issue/IDEA-265263</a>\n */\n@Documented\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.CLASS)\n@API(status = API.Status.INTERNAL, since = \"2021.1.1\")\npublic @interface CheckReturnValue {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/annotations/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Annotations for describing contracts.\n */\npackage org.neo4j.cypherdsl.core.annotations;\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ast/EnterResult.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.ast;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Result of entering a {@link Visitable}. Visitables are not required to check the result\n * and can enter their child elements nevertheless.\n *\n * @author Michael J. Simons\n * @since 2022.3.0\n */\n@API(status = STABLE, since = \"2022.3.0\")\npublic enum EnterResult {\n\n\t/**\n\t * Continue with all child elements.\n\t */\n\tCONTINUE,\n\n\t/**\n\t * Skip child elements.\n\t */\n\tSKIP_CHILDREN\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ast/ProvidesAffixes.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.ast;\n\nimport java.util.Optional;\n\n/**\n * Additional pre- and suffixes for elements.\n *\n * @author Michael J. Simons\n */\npublic interface ProvidesAffixes {\n\n\t/**\n\t * {@return a prefix for this visitable}\n\t */\n\tdefault Optional<String> getPrefix() {\n\t\treturn Optional.empty();\n\t}\n\n\t/**\n\t * {@return a suffix for this visitable}\n\t */\n\tdefault Optional<String> getSuffix() {\n\t\treturn Optional.empty();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ast/TypedSubtree.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.ast;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * This class helps to group items of the same type on the same level of the tree into a\n * list structure that can be recognized by visitors.\n *\n * @param <T> the children's type\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = INTERNAL, since = \"1.0\")\npublic abstract class TypedSubtree<T extends Visitable> implements Visitable {\n\n\t/**\n\t * The content of this typed subtree.\n\t */\n\tprotected final List<T> children;\n\n\t/**\n\t * Creates a new typed subtree with the given content.\n\t * @param children the content of this subtree.\n\t */\n\t@SafeVarargs\n\t@SuppressWarnings(\"varargs\")\n\tprotected TypedSubtree(T... children) {\n\n\t\tthis.children = Arrays.asList(children);\n\t}\n\n\t/**\n\t * Creates a new typed subtree with the given content.\n\t * @param children the content of this subtree.\n\t */\n\tprotected TypedSubtree(Collection<T> children) {\n\n\t\tthis.children = new ArrayList<>(children);\n\t}\n\n\t@Override\n\tpublic final void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tthis.children.forEach(child -> prepareVisit(child).accept(visitor));\n\t\tvisitor.leave(this);\n\t}\n\n\t/**\n\t * A hook for interfere with the visitation of child elements.\n\t * @param child the current child element\n\t * @return the visitable that has been prepared\n\t */\n\tprotected Visitable prepareVisit(T child) {\n\t\treturn child;\n\t}\n\n\t@API(status = INTERNAL)\n\tprotected List<T> getChildren() {\n\t\treturn this.children;\n\t}\n\n\t@API(status = INTERNAL)\n\tpublic String separator() {\n\t\treturn \", \";\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ast/Visitable.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.ast;\n\n/**\n * Interface for implementations that accepts {@link Visitor visitors}.\n *\n * @author Michael Simons\n * @since 1.0\n * @see Visitor\n */\npublic interface Visitable {\n\n\t/**\n\t * A helper method that presents the {@code visitor} to the {@code visitable} if the\n\t * visitable is not null. Not meant to be overridden.\n\t * @param visitable the visitable to visit if not null\n\t * @param visitor the visitor to use\n\t */\n\tstatic void visitIfNotNull(Visitable visitable, Visitor visitor) {\n\n\t\tif (visitable != null) {\n\t\t\tvisitable.accept(visitor);\n\t\t}\n\t}\n\n\t/**\n\t * Accept a {@link Visitor} visiting this {@link Visitable} and its nested\n\t * {@link Visitable}s if applicable.\n\t * @param visitor the visitor to notify, must not be {@literal null}.\n\t */\n\tdefault void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tvisitor.leave(this);\n\t}\n\n\t/**\n\t * Most {@link Visitable visitables} will render themselves into a Cypher fragment\n\t * preceded with the actual classname. The representation however is not cached - in\n\t * contrast to the ones for full statements. Using {@code toString} is recommended for\n\t * debugging purposes mainly, and not for production use.\n\t * <p>\n\t * The concrete classname has been prepended to help debugging and actually to\n\t * discourage using fragments to build queries without explicitly rendering them,\n\t * either as statement or going through the renderer on purpose.\n\t * @return a string representation of this visitable formatted as\n\t * {@literal Classname{cypher=value}}\n\t */\n\tString toString();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ast/Visitor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.ast;\n\n/**\n * Visitors are used to traverse the complete Cypher-DSL AST.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@FunctionalInterface\npublic interface Visitor {\n\n\t/**\n\t * Enter a {@link Visitable}. Not all visitables will obey to the result\n\t * @param segment the segment to visit.\n\t */\n\tvoid enter(Visitable segment);\n\n\t/**\n\t * A method that is used to pass control to some extent from the visitor to the\n\t * {@link Visitable}. Not all visitables react to this, and we don't give any\n\t * guarantees about which will. This method has been mainly introduced in parallel to\n\t * {@link #enter(Visitable)} so that existing external implementations of\n\t * {@link Visitor visitors} won't break.\n\t * @param segment the segment to visit.\n\t * @return a result indicating whether visitation of child elements should continue or\n\t * not.\n\t * @since 2022.3.0\n\t */\n\tdefault EnterResult enterWithResult(Visitable segment) {\n\t\tenter(segment);\n\t\treturn EnterResult.CONTINUE;\n\t}\n\n\t/**\n\t * Leave a {@link Visitable}.\n\t * @param segment the visited segment.\n\t */\n\tdefault void leave(Visitable segment) {\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ast/VisitorWithResult.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.ast;\n\n/**\n * Sometimes it will be necessary - for example in dialects - to change the flow of\n * elements visited. Some {@link Visitable vistables} will react on\n * {@link Visitor#enterWithResult(Visitable)} and change course (not all, and we don't\n * give any guarantees on any behaviour). This class has been introduced for visitors\n * providing such a behaviour so that an implementation doesn't need to deal with an empty\n * {@link Visitor#enter(Visitable)} method.\n *\n * @author Michael J. Simons\n * @since 2022.3.0\n */\n@SuppressWarnings(\"missing-explicit-ctor\")\npublic abstract class VisitorWithResult implements Visitor {\n\n\t@Override\n\tpublic final void enter(Visitable segment) {\n\t\tenterWithResult(segment);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/ast/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Support for describing an abstract syntax tree.\n */\npackage org.neo4j.cypherdsl.core.ast;\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/CaseElse.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Represents a finalizing `else` expression.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n */\n@API(status = INTERNAL, since = \"1.0\")\npublic final class CaseElse implements Visitable {\n\n\tprivate final Expression elseExpression;\n\n\t/**\n\t * Starts creating the {@literal ELSE} part.\n\t * @param elseExpression finishing else part\n\t */\n\tpublic CaseElse(Expression elseExpression) {\n\t\tthis.elseExpression = elseExpression;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.elseExpression.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/CaseWhenThen.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Represents a pair of `when-then` expressions.\n *\n * @author Gerrit Meier\n * @author Michael J. Simons\n */\n@API(status = INTERNAL, since = \"1.0\")\npublic final class CaseWhenThen implements Visitable {\n\n\tprivate final Expression whenExpression;\n\n\tprivate final Expression thenExpression;\n\n\t/**\n\t * Creates w new instance.\n\t * @param whenExpression intermediate when part\n\t * @param thenExpression the then part to happen after matching when above\n\t */\n\tpublic CaseWhenThen(Expression whenExpression, Expression thenExpression) {\n\n\t\tthis.whenExpression = whenExpression;\n\t\tthis.thenExpression = thenExpression;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tvisitor.enter(this);\n\t\tthis.whenExpression.accept(visitor);\n\t\tvisitor.leave(this);\n\t\tthis.thenExpression.accept(visitor);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/ConstantParameterHolder.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Cypher;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * An internal holder for a constant value that might be rendered as a parameter.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\npublic final class ConstantParameterHolder {\n\n\tprivate final Object value;\n\n\tprivate final String literalValue;\n\n\t/**\n\t * New instance for a reference to a constant parameter. An additional literal for the\n\t * parameter will be generated.\n\t * @param value the value of the constant parameter\n\t */\n\tpublic ConstantParameterHolder(Object value) {\n\t\tthis.value = value;\n\t\tthis.literalValue = Cypher.literalOf(value).asString();\n\t}\n\n\t/**\n\t * {@return the original value}\n\t */\n\tpublic Object getValue() {\n\t\treturn this.value;\n\t}\n\n\t/**\n\t * {@return the value, but as a Cypher literal}\n\t */\n\tpublic String asString() {\n\t\treturn this.literalValue;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/DefaultStatementContext.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Parameter;\nimport org.neo4j.cypherdsl.core.StatementContext;\nimport org.neo4j.cypherdsl.core.SymbolicName;\nimport org.neo4j.cypherdsl.core.utils.Strings;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * The default implementation of the {@link StatementContext}.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\npublic final class DefaultStatementContext implements StatementContext {\n\n\tprivate final AtomicInteger parameterCount = new AtomicInteger();\n\n\tprivate final Map<Parameter<?>, String> parameterNames = new ConcurrentHashMap<>();\n\n\t/**\n\t * Keeps track of unresolved symbolic names.\n\t */\n\tprivate final Map<SymbolicName, String> resolvedSymbolicNames = new ConcurrentHashMap<>();\n\n\t@Override\n\tpublic String getParameterName(Parameter<?> parameter) {\n\n\t\treturn this.parameterNames.computeIfAbsent(parameter,\n\t\t\t\tp -> p.isAnon() ? String.format(\"pcdsl%02d\", this.parameterCount.incrementAndGet()) : p.getName());\n\t}\n\n\t@Override\n\tpublic String resolve(SymbolicName symbolicName) {\n\n\t\treturn this.resolvedSymbolicNames.computeIfAbsent(symbolicName, k -> {\n\t\t\tString value = k.getValue();\n\t\t\tif (Strings.hasText(value)) {\n\t\t\t\treturn SchemaNamesBridge.sanitize(value, false).orElse(value);\n\t\t\t}\n\t\t\treturn String.format(\"%s%03d\", Strings.randomIdentifier(8), this.resolvedSymbolicNames.size());\n\t\t});\n\t}\n\n\t@Override\n\tpublic boolean isResolved(SymbolicName symbolicName) {\n\t\treturn this.resolvedSymbolicNames.containsKey(symbolicName);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/Distinct.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * AST representation of the {@literal DISTINCT} keyword.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = INTERNAL, since = \"1.0\")\npublic enum Distinct implements Visitable {\n\n\t/**\n\t * The single instance of the {@code DISTINCT} keyword.\n\t */\n\tINSTANCE\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/FixedNamesStrategy.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport org.neo4j.cypherdsl.core.AliasedExpression;\nimport org.neo4j.cypherdsl.core.Parameter;\nimport org.neo4j.cypherdsl.core.StatementContext;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n/**\n * A strategy that will always use fixed names for aliased expressions.\n *\n * @author Michael J. Simons\n * @since 2023.2.0\n */\nfinal class FixedNamesStrategy implements NameResolvingStrategy {\n\n\tprivate final StatementContext context;\n\n\tFixedNamesStrategy(StatementContext context) {\n\t\tthis.context = context;\n\t}\n\n\t@Override\n\tpublic String resolve(SymbolicName symbolicName, boolean inEntity, boolean inPropertyLookup) {\n\t\treturn this.context.resolve(symbolicName);\n\t}\n\n\t@Override\n\tpublic String resolve(AliasedExpression aliasedExpression, boolean isNew, boolean inLastReturn) {\n\t\treturn aliasedExpression.getAlias();\n\t}\n\n\t@Override\n\tpublic boolean isResolved(SymbolicName symbolicName) {\n\t\treturn this.context.isResolved(symbolicName);\n\t}\n\n\t@Override\n\tpublic String resolve(Parameter<?> parameter) {\n\t\treturn this.context.getParameterName(parameter);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/GeneratedNamesStrategy.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport java.util.ArrayDeque;\nimport java.util.Collection;\nimport java.util.Deque;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport org.neo4j.cypherdsl.core.AliasedExpression;\nimport org.neo4j.cypherdsl.core.IdentifiableElement;\nimport org.neo4j.cypherdsl.core.Parameter;\nimport org.neo4j.cypherdsl.core.StatementContext;\nimport org.neo4j.cypherdsl.core.SymbolicName;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.renderer.Configuration.GeneratedNames;\n\n/**\n * A strategy that generates unique names per scope for named items in a statement.\n *\n * @author Michael J. Simons\n * @since 2023.2.0\n */\nfinal class GeneratedNamesStrategy implements NameResolvingStrategy {\n\n\t/**\n\t * Unscoped counter for parameters.\n\t */\n\tprivate final AtomicInteger parameterCount = new AtomicInteger(0);\n\n\t/**\n\t * Stack of counters per scope for the variable names.\n\t */\n\tprivate final Deque<AtomicInteger> scopedVariableCount = new ArrayDeque<>();\n\n\t/**\n\t * Scope for the already generated names.\n\t */\n\tprivate final Deque<Map<Key, String>> scopedNameLookup = new ArrayDeque<>();\n\n\t/**\n\t * Used names that are either brought into a child scope or exported into the\n\t * containing scope.\n\t */\n\tprivate final Deque<Set<String>> scopedNamesUsed = new ArrayDeque<>();\n\n\tprivate final StatementContext statementContext;\n\n\tprivate final Set<GeneratedNames> config;\n\n\tGeneratedNamesStrategy(StatementContext statementContext, Set<GeneratedNames> config) {\n\t\tthis.statementContext = statementContext;\n\t\tthis.config = config;\n\t\tthis.enterScope(null, List.of());\n\t}\n\n\t/**\n\t * {@return the lookup table for names in the current scope}\n\t */\n\tMap<Key, String> nameLookup() {\n\t\treturn Objects.requireNonNull(this.scopedNameLookup.peek());\n\t}\n\n\t@Override\n\tpublic void enterScope(Visitable cause, Collection<IdentifiableElement> imports) {\n\n\t\tvar newNameLookup = new HashMap<Key, String>();\n\t\tvar newUsedNames = new HashSet<String>();\n\n\t\tvar outerNameLookup = this.scopedNameLookup.peek();\n\t\tif (outerNameLookup != null) {\n\t\t\tfor (IdentifiableElement anImport : imports) {\n\t\t\t\tvar theKey = Key.of(anImport);\n\t\t\t\tif (outerNameLookup.containsKey(theKey)) {\n\t\t\t\t\tnewNameLookup.put(theKey, outerNameLookup.get(theKey));\n\t\t\t\t}\n\t\t\t}\n\t\t\tnewUsedNames.addAll(outerNameLookup.values());\n\t\t}\n\n\t\tthis.scopedVariableCount.push(new AtomicInteger(0));\n\t\tthis.scopedNameLookup.push(newNameLookup);\n\t\tthis.scopedNamesUsed.push(newUsedNames);\n\t}\n\n\t@Override\n\tpublic void leaveScope(Visitable cause, Collection<IdentifiableElement> exports) {\n\n\t\tthis.scopedVariableCount.pop();\n\t\tvar innerNameLookup = this.scopedNameLookup.pop();\n\t\tthis.scopedNamesUsed.pop();\n\n\t\tvar outerNameLookup = Objects.requireNonNull(this.scopedNameLookup.peek());\n\t\tvar previouslyUsedNames = Objects.requireNonNull(this.scopedNamesUsed.peek());\n\n\t\tfor (IdentifiableElement anExport : exports) {\n\t\t\tvar theKey = Key.of(anExport);\n\t\t\tif (innerNameLookup.containsKey(theKey)) {\n\t\t\t\touterNameLookup.put(theKey, innerNameLookup.get(theKey));\n\t\t\t}\n\t\t\telse if (anExport instanceof AliasedExpression name) {\n\t\t\t\touterNameLookup.put(theKey, name.getAlias());\n\t\t\t}\n\t\t\telse if (anExport instanceof SymbolicName name) {\n\t\t\t\touterNameLookup.put(theKey, name.getValue());\n\t\t\t}\n\t\t}\n\t\tpreviouslyUsedNames.addAll(innerNameLookup.values());\n\t}\n\n\t@Override\n\tpublic String resolve(SymbolicName symbolicName, boolean inEntity, boolean inPropertyLookup) {\n\n\t\tif (inPropertyLookup) {\n\t\t\treturn this.statementContext.resolve(symbolicName);\n\t\t}\n\n\t\t// Maybe it has been used as an alias, so we can't skip early\n\t\tvar theKey = Key.of(symbolicName);\n\t\tvar nameLookup = nameLookup();\n\n\t\tif (!this.config.contains(GeneratedNames.ENTITY_NAMES)\n\t\t\t\t|| (!inEntity && !this.config.contains(GeneratedNames.ALL_ALIASES)\n\t\t\t\t\t\t&& !this.config.contains(GeneratedNames.INTERNAL_ALIASES_ONLY))) {\n\t\t\t// Not using nameLookup.getOrDefault() to not resolve the name early\n\t\t\tif (nameLookup.containsKey(theKey)) {\n\t\t\t\treturn nameLookup.get(theKey);\n\t\t\t}\n\t\t\treturn this.statementContext.resolve(symbolicName);\n\t\t}\n\n\t\treturn nameLookup.computeIfAbsent(theKey, key -> newName());\n\t}\n\n\tprivate String newName() {\n\n\t\tString name;\n\t\tvar namesUsed = Objects.requireNonNull(this.scopedNamesUsed.peek());\n\t\tvar variableCount = Objects.requireNonNull(this.scopedVariableCount.peek());\n\t\tdo {\n\t\t\tname = String.format(\"v%d\", variableCount.getAndIncrement());\n\t\t}\n\t\twhile (namesUsed.contains(name));\n\t\treturn name;\n\t}\n\n\t@Override\n\tpublic String resolve(AliasedExpression aliasedExpression, boolean isNew, boolean inLastReturn) {\n\n\t\tif (!(this.config.contains(GeneratedNames.ALL_ALIASES)\n\t\t\t\t|| (this.config.contains(GeneratedNames.INTERNAL_ALIASES_ONLY) && !inLastReturn))) {\n\t\t\treturn aliasedExpression.getAlias();\n\t\t}\n\n\t\tvar nameLookup = nameLookup();\n\t\tif (this.config.contains(GeneratedNames.REUSE_ALIASES)) {\n\t\t\treturn nameLookup.computeIfAbsent(Key.of(aliasedExpression), key -> newName());\n\t\t}\n\t\telse {\n\t\t\tvar result = newName();\n\t\t\tnameLookup().put(Key.of(aliasedExpression), result);\n\t\t\treturn result;\n\t\t}\n\t}\n\n\t@Override\n\tpublic String resolve(Parameter<?> parameter) {\n\n\t\tif (!this.config.contains(GeneratedNames.PARAMETER_NAMES)) {\n\t\t\treturn this.statementContext.getParameterName(parameter);\n\t\t}\n\n\t\treturn nameLookup().computeIfAbsent(Key.of(parameter), key -> {\n\t\t\tvar p = (Parameter<?>) key.value();\n\t\t\treturn !p.isAnon() ? String.format(\"p%d\", this.parameterCount.getAndIncrement())\n\t\t\t\t\t: this.statementContext.getParameterName(p);\n\t\t});\n\t}\n\n\t@Override\n\tpublic boolean isResolved(SymbolicName symbolicName) {\n\t\treturn this.statementContext.isResolved(symbolicName);\n\t}\n\n\trecord Key(Object value) {\n\n\t\tstatic Key of(Object o) {\n\t\t\tif (o instanceof AliasedExpression aliasedExpression) {\n\t\t\t\treturn new Key(aliasedExpression.asName());\n\t\t\t}\n\t\t\treturn new Key(o);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/HandlerException.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\n/**\n * An exception that is thrown when one of the handlers fails to execute.\n *\n * @author Michael J. Simons\n */\nclass HandlerException extends RuntimeException {\n\n\tprivate static final long serialVersionUID = 1L;\n\n\tHandlerException(Throwable cause) {\n\t\tsuper(cause);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/LoadCSV.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport java.net.URI;\nimport java.util.Objects;\nimport java.util.Optional;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Clause;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * A representation of the {@code LOAD CSV} clause, including it's periodic commit and\n * field terminator configuration. Not meant to be used outside the Cypher-DSL directly.\n * Will be changed without further notice.\n *\n * @author Michael J. Simons\n * @since 2021.2.1\n */\n@API(status = INTERNAL, since = \"2021.2.1\")\npublic final class LoadCSV implements Clause {\n\n\tprivate final URI uri;\n\n\tprivate final boolean withHeaders;\n\n\tprivate final String alias;\n\n\tprivate final String fieldTerminator;\n\n\t/**\n\t * Constructs a new {@link LoadCSV} clause.\n\t * @param uri required uri\n\t * @param withHeaders with or without headers\n\t * @param alias the alias per row\n\t */\n\tpublic LoadCSV(URI uri, boolean withHeaders, String alias) {\n\t\tthis(uri, withHeaders, alias, null);\n\t}\n\n\tprivate LoadCSV(URI uri, boolean withHeaders, String alias, String fieldTerminator) {\n\t\tthis.uri = uri;\n\t\tthis.withHeaders = withHeaders;\n\t\tthis.alias = alias;\n\t\tthis.fieldTerminator = fieldTerminator;\n\t}\n\n\t/**\n\t * {@return the uri of the csv file}\n\t */\n\tpublic URI getUri() {\n\t\treturn this.uri;\n\t}\n\n\t/**\n\t * {@return <code>true</code> if headers are to be evaluated}\n\t */\n\tpublic boolean isWithHeaders() {\n\t\treturn this.withHeaders;\n\t}\n\n\t/**\n\t * {@return the field terminator to use}\n\t */\n\tpublic String getFieldTerminator() {\n\t\treturn this.fieldTerminator;\n\t}\n\n\t/**\n\t * {@return the alias for one row in the csv file}\n\t */\n\tpublic String getAlias() {\n\t\treturn this.alias;\n\t}\n\n\t/**\n\t * Creates a new {@link LoadCSV LOAD CSV clause} with the given field terminator.\n\t * @param newFieldTerminator the new field terminator\n\t * @return a new instance or this instance if the terminator hasn't changed\n\t */\n\tpublic LoadCSV withFieldTerminator(final String newFieldTerminator) {\n\n\t\tString value = Optional.ofNullable(newFieldTerminator).map(String::trim).filter(v -> !v.isEmpty()).orElse(null);\n\n\t\tif (Objects.equals(this.fieldTerminator, value)) {\n\t\t\treturn this;\n\t\t}\n\n\t\treturn new LoadCSV(this.uri, this.withHeaders, this.alias, value);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/NameResolvingStrategy.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport java.util.Collection;\nimport java.util.EnumSet;\nimport java.util.Set;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.AliasedExpression;\nimport org.neo4j.cypherdsl.core.IdentifiableElement;\nimport org.neo4j.cypherdsl.core.Parameter;\nimport org.neo4j.cypherdsl.core.StatementContext;\nimport org.neo4j.cypherdsl.core.SymbolicName;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.renderer.Configuration.GeneratedNames;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * This class acts as facade towards the {@link StatementContext statement context} and\n * can generate variable and parameter names throughout the lifetime of this visitor.\n *\n * @author Michael J. Simons\n */\n@API(status = INTERNAL, since = \"2023.2.0\")\npublic sealed interface NameResolvingStrategy permits FixedNamesStrategy, GeneratedNamesStrategy {\n\n\t/**\n\t * Creates a strategy for using generated names in the given context.\n\t * @param context a statement context\n\t * @param config for which generated names should be used\n\t * @return a new strategy\n\t */\n\tstatic NameResolvingStrategy useGeneratedNames(StatementContext context, Set<GeneratedNames> config) {\n\t\treturn new GeneratedNamesStrategy(context, config);\n\t}\n\n\t/**\n\t * Creates a strategy that uses generated parameter names.\n\t * @param context a statement context\n\t * @return a new strategy\n\t */\n\tstatic NameResolvingStrategy useGeneratedParameterNames(StatementContext context) {\n\t\treturn new GeneratedNamesStrategy(context, EnumSet.of(GeneratedNames.PARAMETER_NAMES));\n\t}\n\n\t/**\n\t * Creates a strategy that uses the given names.\n\t * @param context a statement context\n\t * @return a new strategy\n\t */\n\tstatic NameResolvingStrategy useGivenNames(StatementContext context) {\n\t\treturn new FixedNamesStrategy(context);\n\t}\n\n\t/**\n\t * Resolves a symbolic name.\n\t * @param symbolicName the name to resolve\n\t * @param inEntity {@literal true} if this happens inside an entity\n\t * @param inPropertyLookup {@literal true} if this happens for a property lookup\n\t * @return a value\n\t */\n\tString resolve(SymbolicName symbolicName, boolean inEntity, boolean inPropertyLookup);\n\n\t/**\n\t * Resolves an aliased expression.\n\t * @param isNew true if it's a newly created {@link AliasedExpression}\n\t * @param aliasedExpression the aliased expression to resolve\n\t * @param inLastReturn true if the name is resolved as part of the ultimate\n\t * {@code RETURN} clause of a statement\n\t * @return a value\n\t */\n\tString resolve(AliasedExpression aliasedExpression, boolean isNew, boolean inLastReturn);\n\n\t/**\n\t * Returns {@code true} if the {@code symbolicName} has been resolved.\n\t * @param symbolicName the name that might be already resolved\n\t * @return {@code true} if the {@code symbolicName} has been resolved\n\t */\n\tboolean isResolved(SymbolicName symbolicName);\n\n\t/**\n\t * Resolves a parameter name.\n\t * @param parameter the name to resolv\n\t * @return a value\n\t */\n\tString resolve(Parameter<?> parameter);\n\n\t/**\n\t * A callback used together with a {@link ScopingStrategy} to deal with imports into a\n\t * local scope.\n\t * @param cause the clause that caused the creation of a new scope\n\t * @param imports the imports\n\t */\n\tdefault void enterScope(Visitable cause, Collection<IdentifiableElement> imports) {\n\t}\n\n\t/**\n\t * A callback used together with a {@link ScopingStrategy} to deal with exports when\n\t * leaving a local scope.\n\t * @param cause the clause being left\n\t * @param exports the exports\n\t */\n\tdefault void leaveScope(Visitable cause, Collection<IdentifiableElement> exports) {\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/Namespace.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Literal;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Representation of a namespace (i.e. for procedures) element.\n *\n * @author Michael J. Simons\n * @since 2020.0.1\n */\n@API(status = INTERNAL, since = \"2020.0.1\")\npublic final class Namespace implements Literal<String[]> {\n\n\tprivate final String[] content;\n\n\tNamespace(String[] value) {\n\t\tthis.content = value;\n\t}\n\n\t@Override\n\tpublic String asString() {\n\n\t\treturn String.join(\".\", this.content);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/ProcedureName.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Represents a structured Neo4j procedure name.\n *\n * @author Michael J. Simons\n * @since 2020.0.1\n */\n@API(status = INTERNAL, since = \"2020.0.1\")\npublic final class ProcedureName implements Visitable {\n\n\tprivate final Namespace optionalNamespace;\n\n\tprivate final String value;\n\n\tprivate ProcedureName(String value) {\n\t\tthis(null, value);\n\t}\n\n\tprivate ProcedureName(Namespace namespace, String value) {\n\n\t\tthis.optionalNamespace = namespace;\n\t\tthis.value = value;\n\t}\n\n\t/**\n\t * Creates a new {@link ProcedureName} from an array of names: The last element will\n\t * be the final procedure name, the head items will be concatenated into a proper\n\t * namespace.\n\t * @param namespaceAndProcedure list of names\n\t * @return a new procedure\n\t */\n\tpublic static ProcedureName from(String... namespaceAndProcedure) {\n\t\tif (namespaceAndProcedure.length == 1) {\n\t\t\treturn new ProcedureName(namespaceAndProcedure[0]);\n\t\t}\n\t\telse {\n\t\t\tNamespace namespace = new Namespace(Arrays.copyOf(namespaceAndProcedure, namespaceAndProcedure.length - 1));\n\t\t\treturn new ProcedureName(namespace, namespaceAndProcedure[namespaceAndProcedure.length - 1]);\n\t\t}\n\t}\n\n\t/**\n\t * Creates a new {@link ProcedureName} from a given namespace and name.\n\t * @param namespace optional (nested) namespace\n\t * @param procedure the actual name of the procedure\n\t * @return a new procedure\n\t */\n\tpublic static ProcedureName from(List<String> namespace, String procedure) {\n\t\tif (namespace.isEmpty()) {\n\t\t\treturn new ProcedureName(procedure);\n\t\t}\n\t\telse {\n\t\t\treturn new ProcedureName(new Namespace(namespace.toArray(new String[0])), procedure);\n\t\t}\n\t}\n\n\t/**\n\t * {@return the fully qualified, Cypher name of this procedure}\n\t */\n\tpublic String getQualifiedName() {\n\n\t\tString namespace = \"\";\n\t\tif (this.optionalNamespace != null) {\n\t\t\tnamespace = this.optionalNamespace.asString() + \".\";\n\t\t}\n\t\treturn namespace + this.value;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tVisitable.visitIfNotNull(this.optionalNamespace, visitor);\n\t\tvisitor.leave(this);\n\t}\n\n\t/**\n\t * Use {@link #getQualifiedName()} to retrieve the full name, including the namespace.\n\t * @return the actual name of the procedure, without any namespace.\n\t */\n\tpublic String getValue() {\n\t\treturn this.value;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/ReflectiveVisitor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.Arrays;\nimport java.util.Deque;\nimport java.util.HashMap;\nimport java.util.LinkedHashSet;\nimport java.util.LinkedList;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.EnterResult;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.ast.VisitorWithResult;\nimport org.neo4j.cypherdsl.core.renderer.SchemaEnforcementFailedException;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * This is a convenience class implementing a {@link Visitor} and it takes care of\n * choosing the right methods to dispatch the {@link Visitor#enter(Visitable)} and\n * {@link Visitor#leave(Visitable)} calls to.\n * <p>\n * Classes extending this visitor need to provide corresponding {@code enter} and\n * {@code leave} methods taking exactly one argument of the type of {@link Visitable} they\n * are interested it.\n * <p>\n * The type must be an exact match, this support class doesn't try to find a close match\n * up in the class hierarchy if it doesn't find an exact match.\n *\n * @author Michael J. Simons\n * @author Gerrit Meier\n * @since 1.0\n */\n@API(status = INTERNAL, since = \"1.0\")\npublic abstract class ReflectiveVisitor extends VisitorWithResult {\n\n\t/**\n\t * A shared cache of unbound methods for entering and leaving phases. The key is the\n\t * concrete class of the visitor as well as the hierarchy of the visitable.\n\t */\n\tprivate static final Map<TargetAndPhase, Optional<Method>> VISITING_METHODS_CACHE = new ConcurrentHashMap<>();\n\n\t/**\n\t * If theres any special delegate for a dialect or similar for a given visitable, it\n\t * will be tracked here.\n\t */\n\tprotected final Map<Visitable, Visitor> visitablesAndDelegates = new HashMap<>();\n\n\t/**\n\t * Keeps track of the ASTs current level.\n\t */\n\tprotected Deque<Visitable> currentVisitedElements = new LinkedList<>();\n\n\t@SuppressWarnings(\"PMD.EmptyCatchBlock\")\n\tprivate static Optional<Method> findHandleFor(TargetAndPhase targetAndPhase) {\n\n\t\tClass<?> visitorClass = targetAndPhase.visitorClass;\n\t\tdo { // Loop over the hierarchy of visitors so that we catch overloaded and\n\t\t\t\t// inherited methods.\n\t\t\t\t// the loop goes from concrete to abstract, so that the most concrete\n\t\t\t\t// visitor wins\n\t\t\tfor (Class<?> clazz : targetAndPhase.classHierarchyOfVisitable) {\n\t\t\t\ttry {\n\t\t\t\t\tMethod method = getMethodInPhaseWithActualVisitor(targetAndPhase, visitorClass, clazz);\n\t\t\t\t\treturn Optional.of(method);\n\t\t\t\t}\n\t\t\t\tcatch (NoSuchMethodException ex) {\n\t\t\t\t\t// We don't do anything if the method doesn't exists\n\t\t\t\t\t// Try the next parameter type in the hierarchy or the next visitor\n\t\t\t\t}\n\t\t\t}\n\t\t\tvisitorClass = visitorClass.getSuperclass();\n\t\t}\n\t\twhile (visitorClass != null && visitorClass != ReflectiveVisitor.class);\n\n\t\treturn Optional.empty();\n\t}\n\n\t@SuppressWarnings(\"squid:S3011\") // Very much the point of the whole thing\n\tprivate static Method getMethodInPhaseWithActualVisitor(TargetAndPhase targetAndPhase, Class<?> visitorClass,\n\t\t\tClass<?> clazz) throws NoSuchMethodException {\n\t\tMethod method = visitorClass.getDeclaredMethod(targetAndPhase.phase.methodName, clazz);\n\t\tmethod.setAccessible(true);\n\t\treturn method;\n\t}\n\n\t/**\n\t * This is a hook that is called with the uncasted, raw visitable just before entering\n\t * a visitable.\n\t * <p>\n\t * The hook is called regardless wither a matching {@code enter} is found or not.\n\t * @param visitable the visitable that is passed on to a matching enter after this\n\t * call.\n\t * @return true, when visiting of elements should be stopped until this element is\n\t * left again.\n\t */\n\tprotected abstract boolean preEnter(Visitable visitable);\n\n\t/**\n\t * Returns an indicator whether the visitable can be skipped or must be visited.\n\t * @param visitable the visitable prior to entering it\n\t * @return an indicator whether the visitable can be skipped or must be visited\n\t */\n\tprotected PreEnterResult getPreEnterResult(Visitable visitable) {\n\t\treturn preEnter(visitable) ? PreEnterResult.doEnter() : PreEnterResult.skip();\n\t}\n\n\t/**\n\t * This is a hook that is called with the uncasted, raw visitable just after leaving\n\t * the visitable.\n\t * <p>\n\t * The hook is called regardless wither a matching {@code leave} is found or not.\n\t * @param visitable the visitable that is passed on to a matching leave after this\n\t * call.\n\t */\n\tprotected abstract void postLeave(Visitable visitable);\n\n\t@Override\n\tpublic final EnterResult enterWithResult(Visitable visitable) {\n\n\t\tPreEnterResult preEnterResult = getPreEnterResult(visitable);\n\t\tif (preEnterResult != PreEnterResult.skip()) {\n\t\t\tthis.currentVisitedElements.push(visitable);\n\t\t\tif (preEnterResult.delegate != null) {\n\t\t\t\tthis.visitablesAndDelegates.put(visitable, preEnterResult.delegate);\n\t\t\t\treturn preEnterResult.delegate.enterWithResult(visitable);\n\t\t\t}\n\t\t\telse {\n\t\t\t\texecuteConcreteMethodIn(new TargetAndPhase(this, visitable.getClass(), Phase.ENTER), visitable);\n\t\t\t}\n\t\t}\n\t\treturn EnterResult.CONTINUE;\n\t}\n\n\t@Override\n\tpublic final void leave(Visitable visitable) {\n\n\t\tif (visitable != null && this.currentVisitedElements.peek() == visitable) {\n\t\t\tif (this.visitablesAndDelegates.containsKey(visitable)) {\n\t\t\t\tVisitor delegate = this.visitablesAndDelegates.remove(visitable);\n\t\t\t\tdelegate.leave(visitable);\n\t\t\t}\n\t\t\telse {\n\t\t\t\texecuteConcreteMethodIn(new TargetAndPhase(this, visitable.getClass(), Phase.LEAVE), visitable);\n\t\t\t}\n\t\t\tpostLeave(visitable);\n\t\t\tthis.currentVisitedElements.pop();\n\t\t}\n\t}\n\n\tprivate void executeConcreteMethodIn(TargetAndPhase targetAndPhase, Visitable onVisitable) {\n\t\tOptional<Method> optionalMethod = VISITING_METHODS_CACHE.computeIfAbsent(targetAndPhase,\n\t\t\t\tReflectiveVisitor::findHandleFor);\n\t\toptionalMethod.ifPresent(handle -> {\n\t\t\ttry {\n\t\t\t\thandle.invoke(this, onVisitable);\n\t\t\t}\n\t\t\tcatch (Throwable throwable) {\n\t\t\t\tif (throwable instanceof InvocationTargetException ite\n\t\t\t\t\t\t&& ite.getCause() instanceof SchemaEnforcementFailedException sefe) {\n\t\t\t\t\tthrow sefe;\n\t\t\t\t}\n\t\t\t\tthrow new HandlerException(throwable);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Private enum to specify a visiting phase.\n\t */\n\tprivate enum Phase {\n\n\t\tENTER(\"enter\"), LEAVE(\"leave\");\n\n\t\tfinal String methodName;\n\n\t\tPhase(String methodName) {\n\t\t\tthis.methodName = methodName;\n\t\t}\n\n\t}\n\n\t/**\n\t * This class is an indicator of what should happen after a new visitable has been\n\t * identified.\n\t */\n\tpublic static final class PreEnterResult {\n\n\t\tprivate static final PreEnterResult DO_ENTER = new PreEnterResult(null);\n\n\t\tprivate static final PreEnterResult SKIP = new PreEnterResult(null);\n\n\t\tprivate final Visitor delegate;\n\n\t\tprivate PreEnterResult(Visitor delegate) {\n\t\t\tthis.delegate = delegate;\n\t\t}\n\n\t\t/**\n\t\t * Do enter and treat as usual.\n\t\t * @return the result\n\t\t */\n\t\tpublic static PreEnterResult doEnter() {\n\t\t\treturn DO_ENTER;\n\t\t}\n\n\t\t/**\n\t\t * Skip the element completely.\n\t\t * @return the result\n\t\t */\n\t\tpublic static PreEnterResult skip() {\n\t\t\treturn SKIP;\n\t\t}\n\n\t\t/**\n\t\t * Enter to visit but delegate the visitation.\n\t\t * @param handler the delegate\n\t\t * @return the result\n\t\t */\n\t\tpublic static PreEnterResult delegateTo(Visitor handler) {\n\t\t\treturn new PreEnterResult(handler);\n\t\t}\n\n\t}\n\n\tprivate static class TargetAndPhase {\n\n\t\t/**\n\t\t * The most concrete visitor class. It may be that the handle that is eventually\n\t\t * found will not be called with that class, but with a parent. The attribute here\n\t\t * is just a starting point and later on, a cache key.\n\t\t */\n\t\tprivate final Class<? extends ReflectiveVisitor> visitorClass;\n\n\t\tprivate final Set<Class<?>> classHierarchyOfVisitable;\n\n\t\tprivate final Phase phase;\n\n\t\t<T extends ReflectiveVisitor> TargetAndPhase(T visitor, Class<? extends Visitable> concreteVisitableClass,\n\t\t\t\tPhase phase) {\n\t\t\tthis.visitorClass = visitor.getClass();\n\t\t\tthis.phase = phase;\n\t\t\tthis.classHierarchyOfVisitable = new LinkedHashSet<>();\n\n\t\t\tClass<?> classOfVisitable = concreteVisitableClass;\n\t\t\tdo {\n\t\t\t\tthis.classHierarchyOfVisitable.add(classOfVisitable);\n\t\t\t\t// Add all interfaces apart visitable too.\n\t\t\t\tArrays.stream(classOfVisitable.getInterfaces())\n\t\t\t\t\t.filter(c -> c != Visitable.class)\n\t\t\t\t\t.forEach(this.classHierarchyOfVisitable::add);\n\t\t\t\tclassOfVisitable = classOfVisitable.getSuperclass();\n\t\t\t}\n\t\t\twhile (classOfVisitable != null && classOfVisitable != Object.class);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean equals(Object o) {\n\t\t\tif (this == o) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (!(o instanceof TargetAndPhase)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tTargetAndPhase that = (TargetAndPhase) o;\n\t\t\treturn this.visitorClass.equals(that.visitorClass)\n\t\t\t\t\t&& this.classHierarchyOfVisitable.equals(that.classHierarchyOfVisitable)\n\t\t\t\t\t&& this.phase == that.phase;\n\t\t}\n\n\t\t@Override\n\t\tpublic int hashCode() {\n\t\t\treturn Objects.hash(this.visitorClass, this.classHierarchyOfVisitable, this.phase);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/RelationshipLength.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Expresses the length of a relationship.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = INTERNAL, since = \"1.0\")\npublic final class RelationshipLength implements Visitable {\n\n\tprivate final Integer minimum;\n\n\tprivate final Integer maximum;\n\n\tprivate final boolean unbounded;\n\n\tprivate RelationshipLength(Integer minimum, Integer maximum) {\n\t\tthis.minimum = minimum;\n\t\tthis.maximum = maximum;\n\t\tthis.unbounded = minimum == null && maximum == null;\n\t}\n\n\t/**\n\t * Creates an unbounded {@link RelationshipLength}.\n\t * @return the new length definition\n\t */\n\tpublic static RelationshipLength unbounded() {\n\t\treturn new RelationshipLength(null, null);\n\t}\n\n\t/**\n\t * Creates a {@link RelationshipLength} with given minimum and maximum values.\n\t * @param minimum minimum length\n\t * @param maximum maximum length\n\t * @return the new length definition\n\t */\n\tpublic static RelationshipLength of(Integer minimum, Integer maximum) {\n\t\treturn new RelationshipLength(minimum, maximum);\n\t}\n\n\t/**\n\t * {@return minimum number of hops to match}\n\t */\n\t@API(status = INTERNAL)\n\tpublic Integer getMinimum() {\n\t\treturn this.minimum;\n\t}\n\n\t/**\n\t * {@return maximum number of hops to match}\n\t */\n\t@API(status = INTERNAL)\n\tpublic Integer getMaximum() {\n\t\treturn this.maximum;\n\t}\n\n\t/**\n\t * {@return true if neither minimum nor maximum number of hops are set}\n\t */\n\t@API(status = INTERNAL)\n\tpublic boolean isUnbounded() {\n\t\treturn this.unbounded;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/RelationshipPatternCondition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Condition;\nimport org.neo4j.cypherdsl.core.Operator;\nimport org.neo4j.cypherdsl.core.RelationshipPattern;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Internal wrapper for marking a path pattern as a condition.\n *\n * @author Michael J. Simons\n * @since 1.0.1\n */\n@API(status = INTERNAL, since = \"1.0\")\npublic final class RelationshipPatternCondition implements Condition {\n\n\tprivate final boolean not;\n\n\tprivate final RelationshipPattern pathPattern;\n\n\tprivate RelationshipPatternCondition(boolean not, RelationshipPattern pathPattern) {\n\t\tthis.not = not;\n\t\tthis.pathPattern = pathPattern;\n\t}\n\n\t/**\n\t * Creates a new {@link Condition} matching the given pattern.\n\t * @param pathPattern the pattern to be matched\n\t * @return a new condition\n\t */\n\tpublic static RelationshipPatternCondition of(RelationshipPattern pathPattern) {\n\t\treturn new RelationshipPatternCondition(false, pathPattern);\n\t}\n\n\t/**\n\t * Creates a new {@link Condition} that evaluates to {@literal true} when the pattern\n\t * does not match.\n\t * @param pathPattern the pattern to be matched\n\t * @return a new condition\n\t */\n\tpublic static RelationshipPatternCondition not(RelationshipPattern pathPattern) {\n\t\treturn new RelationshipPatternCondition(true, pathPattern);\n\t}\n\n\t@Override\n\tpublic Condition not() {\n\t\treturn new RelationshipPatternCondition(!this.not, this.pathPattern);\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\n\t\tvisitor.enter(this);\n\t\tif (this.not) {\n\t\t\tOperator.NOT.accept(visitor);\n\t\t}\n\t\tthis.pathPattern.accept(visitor);\n\t\tvisitor.leave(this);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/RelationshipTypes.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * See <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M15/railroad/RelationshipDetail.html#RelationshipTypes\">RelationshipTypes</a>.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = INTERNAL, since = \"1.0\")\npublic final class RelationshipTypes implements Visitable {\n\n\tprivate final List<String> values;\n\n\tprivate RelationshipTypes(List<String> values) {\n\t\tthis.values = values;\n\t}\n\n\t/**\n\t * Creates a new holder for relationship types from a set of raw strings.\n\t * @param types the types to be included in this value holder\n\t * @return a new value holder\n\t */\n\tpublic static RelationshipTypes of(String... types) {\n\n\t\tList<String> listOfTypes = Arrays.stream(types).filter(type -> !(type == null || type.isEmpty())).toList();\n\n\t\treturn new RelationshipTypes(listOfTypes);\n\t}\n\n\t/**\n\t * Returns the list of types. The types are not escaped and must be escaped prior to *\n\t * rendering.\n\t * @return the list of types\n\t */\n\tpublic List<String> getValues() {\n\t\treturn this.values;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"RelationshipTypes{values=\" + this.values + '}';\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/SchemaNamesBridge.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport java.util.Optional;\n\nimport org.neo4j.cypherdsl.support.schema_name.SchemaNames;\n\n/**\n * This is a bridge to {@link SchemaNames}. Having this indirection avoids changing of the\n * bytecode of classes using the sanitizer: When the byte code changes, JaCoCo won't be\n * able to analyze it. Of course, one solution would be shading the sanitizer after the\n * integration tests, but the integration tests are meant to test the modularized Jar file\n * proper.\n *\n * @author Michael J. Simons\n * @since 2023.0.0\n */\npublic final class SchemaNamesBridge {\n\n\tprivate SchemaNamesBridge() {\n\t}\n\n\tpublic static Optional<String> sanitize(String value, boolean enforceQuotes) {\n\t\treturn SchemaNames.sanitize(value, enforceQuotes);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/ScopingStrategy.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport java.util.ArrayDeque;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Deque;\nimport java.util.HashSet;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.function.BiConsumer;\nimport java.util.function.Predicate;\nimport java.util.stream.Collectors;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Aliased;\nimport org.neo4j.cypherdsl.core.AliasedExpression;\nimport org.neo4j.cypherdsl.core.Asterisk;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.ExistentialSubquery;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.Foreach;\nimport org.neo4j.cypherdsl.core.FunctionInvocation;\nimport org.neo4j.cypherdsl.core.IdentifiableElement;\nimport org.neo4j.cypherdsl.core.MapProjection;\nimport org.neo4j.cypherdsl.core.Named;\nimport org.neo4j.cypherdsl.core.Order;\nimport org.neo4j.cypherdsl.core.PatternComprehension;\nimport org.neo4j.cypherdsl.core.PatternElement;\nimport org.neo4j.cypherdsl.core.ProcedureCall;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.Return;\nimport org.neo4j.cypherdsl.core.Statement;\nimport org.neo4j.cypherdsl.core.Subquery;\nimport org.neo4j.cypherdsl.core.SubqueryExpression;\nimport org.neo4j.cypherdsl.core.SymbolicName;\nimport org.neo4j.cypherdsl.core.UnionPart;\nimport org.neo4j.cypherdsl.core.With;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * A strategy to keep track of {@link Named named variables} inside a scope.\n *\n * @author Michael J. Simons\n * @since 2021.3.2\n */\n@API(status = INTERNAL, since = \"2021.3.2\")\npublic final class ScopingStrategy {\n\n\t/**\n\t * Keeps track of named objects that have been already visited.\n\t */\n\tprivate final Deque<Set<IdentifiableElement>> dequeOfVisitedNamed = new ArrayDeque<>();\n\n\t/**\n\t * Some expressions have implicit scopes, we might not clear that after returning from\n\t * inner statements or returns.\n\t */\n\tprivate final Deque<Set<IdentifiableElement>> implicitScope = new ArrayDeque<>();\n\n\tprivate final Deque<Set<String>> currentImports = new ArrayDeque<>();\n\n\tprivate final Deque<Set<String>> definedInSubquery = new ArrayDeque<>();\n\n\tprivate final List<BiConsumer<Visitable, Collection<IdentifiableElement>>> onScopeEntered = new ArrayList<>();\n\n\tprivate final List<BiConsumer<Visitable, Collection<IdentifiableElement>>> onScopeLeft = new ArrayList<>();\n\n\t/**\n\t * A flag if we can skip aliasing. This is currently the case in exactly one scenario:\n\t * A aliased expression passed to a map project. In that case, the alias is already\n\t * defined by the key to use in the projected map, and we cannot define him in `AS\n\t * xxx` fragment.\n\t */\n\tprivate final Deque<Boolean> skipAliasing = new ArrayDeque<>();\n\n\tprivate Set<IdentifiableElement> afterStatement = Collections.emptySet();\n\n\tprivate Visitable previous;\n\n\tprivate boolean inOrder = false;\n\n\tprivate boolean inProperty = false;\n\n\tprivate boolean inSubquery = false;\n\n\tprivate boolean inListFunctionPredicate = false;\n\n\tprivate ScopingStrategy() {\n\t\tthis.dequeOfVisitedNamed.push(new LinkedHashSet<>());\n\t}\n\n\t/**\n\t * {@return an empty scoping strategy, for internal use only}\n\t */\n\tpublic static ScopingStrategy create() {\n\t\treturn new ScopingStrategy();\n\t}\n\n\t/**\n\t * Returns an empty scoping strategy, for internal use only.\n\t * @param onScopeEntered event handlers to be called after entering local or implicit\n\t * scope\n\t * @param onScopeLeft event handlers to b called after leaving local or implicit scope\n\t * @return an empty scoping strategy, for internal use only\n\t */\n\tpublic static ScopingStrategy create(List<BiConsumer<Visitable, Collection<IdentifiableElement>>> onScopeEntered,\n\t\t\tList<BiConsumer<Visitable, Collection<IdentifiableElement>>> onScopeLeft) {\n\t\tvar strategy = create();\n\t\tstrategy.onScopeEntered.addAll(onScopeEntered);\n\t\tstrategy.onScopeLeft.addAll(onScopeLeft);\n\t\treturn strategy;\n\t}\n\n\t/**\n\t * Anything that might import variables from the outside, without using an explicit\n\t * {@code WITH} clause.\n\t * @param visitable the element to be checked whether it implicitly imports named\n\t * elements.\n\t * @return {@literal true} if named elements are imported\n\t */\n\tprivate static boolean hasImplicitScope(Visitable visitable) {\n\t\treturn visitable instanceof SubqueryExpression || visitable instanceof Statement.UnionQuery;\n\t}\n\n\tprivate static Predicate<IdentifiableElement> byHasAName() {\n\t\tPredicate<IdentifiableElement> hasAName = Named.class::isInstance;\n\t\thasAName = hasAName.or(AliasedExpression.class::isInstance);\n\t\thasAName = hasAName.or(SymbolicName.class::isInstance);\n\t\treturn hasAName;\n\t}\n\n\t/**\n\t * Extracts an identifier from an {@link IdentifiableElement identifiable element}.\n\t * @param i the identifiable element\n\t * @return the identifier\n\t */\n\tprivate static String extractIdentifier(IdentifiableElement i) {\n\t\tString value;\n\t\tif (i instanceof Named named) {\n\t\t\tvalue = named.getSymbolicName().map(SymbolicName::getValue).orElse(null);\n\t\t}\n\t\telse if (i instanceof Aliased aliased) {\n\t\t\tvalue = aliased.getAlias();\n\t\t}\n\t\telse if (i instanceof SymbolicName symbolicName) {\n\t\t\tvalue = symbolicName.getValue();\n\t\t}\n\t\telse {\n\t\t\tvalue = null;\n\t\t}\n\t\treturn value;\n\t}\n\n\tprivate static boolean hasLocalScope(Visitable visitable) {\n\t\treturn visitable instanceof PatternComprehension || visitable instanceof Subquery\n\t\t\t\t|| visitable instanceof SubqueryExpression || visitable instanceof Foreach;\n\t}\n\n\t/**\n\t * Called when visiting a {@link Visitable}.\n\t * @param visitable element to be checked for new scope\n\t */\n\tpublic void doEnter(Visitable visitable) {\n\n\t\t// We don't want the identifiable in an order clause to be retained\n\t\tif (visitable instanceof Order) {\n\t\t\tthis.inOrder = true;\n\t\t}\n\n\t\tif (visitable instanceof Property) {\n\t\t\tthis.inProperty = true;\n\t\t}\n\n\t\tif (visitable instanceof Subquery subquery) {\n\t\t\tvar with = subquery.importingWith();\n\n\t\t\tthis.inSubquery = true;\n\t\t\tthis.definedInSubquery.push(new LinkedHashSet<>());\n\n\t\t\tSet<String> imports = new LinkedHashSet<>();\n\t\t\tthis.currentImports.push(imports);\n\t\t\tif (with != null) {\n\t\t\t\twith.getItems()\n\t\t\t\t\t.stream()\n\t\t\t\t\t.filter(IdentifiableElement.class::isInstance)\n\t\t\t\t\t.map(IdentifiableElement.class::cast)\n\t\t\t\t\t.map(ScopingStrategy::extractIdentifier)\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.forEach(imports::add);\n\t\t\t}\n\t\t}\n\n\t\tif (isListFunctionPredicate(visitable)) {\n\t\t\tthis.inListFunctionPredicate = true;\n\t\t}\n\n\t\tif (visitable instanceof MapProjection) {\n\t\t\tthis.skipAliasing.push(true);\n\t\t}\n\t\telse if (visitable instanceof SubqueryExpression) {\n\t\t\tthis.skipAliasing.push(false);\n\t\t}\n\n\t\tboolean notify = false;\n\t\tSet<IdentifiableElement> scopeSeed = this.dequeOfVisitedNamed.isEmpty() ? Collections.emptySet()\n\t\t\t\t: this.dequeOfVisitedNamed.peek();\n\t\tif (hasLocalScope(visitable)) {\n\t\t\tnotify = true;\n\t\t\tthis.dequeOfVisitedNamed.push(new LinkedHashSet<>(scopeSeed));\n\t\t}\n\n\t\tif (hasImplicitScope(visitable)) {\n\t\t\tnotify = true;\n\t\t\tthis.implicitScope.push(new LinkedHashSet<>(scopeSeed));\n\t\t}\n\n\t\tif (notify) {\n\t\t\tscopeSeed.addAll(this.afterStatement);\n\t\t\tvar importsAndScope = new LinkedHashSet<IdentifiableElement>();\n\t\t\tvar current = this.currentImports.peek();\n\t\t\tif (current != null) {\n\t\t\t\tcurrent.stream().map(Cypher::name).forEach(importsAndScope::add);\n\t\t\t}\n\t\t\timportsAndScope.addAll(scopeSeed);\n\t\t\tthis.onScopeEntered.forEach(c -> c.accept(visitable, importsAndScope));\n\t\t}\n\t}\n\n\tpublic boolean isSkipAliasing() {\n\t\treturn Optional.ofNullable(this.skipAliasing.peek()).orElse(false);\n\t}\n\n\t/**\n\t * Returns {@code true} if the named item has been visited in the current scope\n\t * before.\n\t * @param namedItem an item that might have been visited in the current scope\n\t * @return {@code true} if the named item has been visited in the current scope before\n\t */\n\tpublic boolean hasVisitedBefore(Named namedItem) {\n\n\t\tif (!hasScope()) {\n\t\t\treturn false;\n\t\t}\n\n\t\tSet<IdentifiableElement> scope = this.dequeOfVisitedNamed.peek();\n\t\treturn hasVisitedInScope(scope, namedItem);\n\t}\n\n\tprivate boolean isListFunctionPredicate(Visitable visitable) {\n\n\t\treturn visitable instanceof FunctionInvocation fi\n\t\t\t\t&& Set.of(\"all\", \"any\", \"none\", \"single\").contains(fi.getFunctionName().toLowerCase(Locale.ROOT));\n\t}\n\n\t/**\n\t * Called when leaving a {@link Visitable}.\n\t * @param visitable element to be checked for a scope to be closed\n\t */\n\tpublic void doLeave(Visitable visitable) {\n\n\t\tif (!hasScope()) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (visitable instanceof IdentifiableElement identifiableElement && !this.inOrder\n\t\t\t\t&& (!this.inProperty || visitable instanceof Property)) {\n\t\t\tif (identifiableElement instanceof SymbolicName && this.inListFunctionPredicate) {\n\t\t\t\tthis.inListFunctionPredicate = false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.dequeOfVisitedNamed.peek().add(identifiableElement);\n\t\t\t\tif (this.inSubquery) {\n\t\t\t\t\tvar identifier = extractIdentifier(identifiableElement);\n\t\t\t\t\tif (identifier != null) {\n\t\t\t\t\t\tthis.definedInSubquery.peek().add(identifier);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (isListFunctionPredicate(visitable)) {\n\t\t\tthis.inListFunctionPredicate = false;\n\t\t}\n\n\t\tboolean notify = false;\n\t\tif (visitable instanceof Statement) {\n\t\t\tleaveStatement(visitable);\n\t\t}\n\t\telse if (hasLocalScope(visitable)) {\n\t\t\tnotify = true;\n\t\t\tSet<IdentifiableElement> lastVisitedNames = this.dequeOfVisitedNamed.pop();\n\t\t\tif (visitable instanceof ExistentialSubquery) {\n\t\t\t\tthis.afterStatement.retainAll(lastVisitedNames);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tclearPreviouslyVisitedNamed(visitable);\n\t\t}\n\n\t\tif (visitable instanceof Order) {\n\t\t\tthis.inOrder = false;\n\t\t}\n\n\t\tif (visitable instanceof Property) {\n\t\t\tthis.inProperty = false;\n\t\t}\n\t\tif (visitable instanceof Subquery) {\n\t\t\tthis.inSubquery = false;\n\t\t\tthis.currentImports.pop();\n\t\t\tthis.definedInSubquery.pop();\n\t\t}\n\n\t\tif (visitable instanceof MapProjection || visitable instanceof SubqueryExpression) {\n\t\t\tthis.skipAliasing.pop();\n\t\t}\n\n\t\tif (hasImplicitScope(visitable)) {\n\t\t\tnotify = true;\n\t\t\tthis.implicitScope.pop();\n\t\t}\n\n\t\tthis.previous = visitable;\n\n\t\tif (notify) {\n\t\t\tSet<IdentifiableElement> retainedElements = new HashSet<>(this.afterStatement);\n\t\t\tthis.onScopeLeft.forEach(c -> c.accept(visitable, retainedElements));\n\t\t}\n\t}\n\n\tprivate void leaveStatement(Visitable visitable) {\n\n\t\tSet<IdentifiableElement> lastScope = this.dequeOfVisitedNamed.peek();\n\t\t// We keep properties only around when they have been actually returned\n\t\tif (this.previous instanceof UnionPart && this.afterStatement != null) {\n\t\t\tlastScope.stream().filter(i -> !(i instanceof Property)).forEach(this.afterStatement::add);\n\t\t}\n\t\telse if (!(this.previous instanceof Return || this.previous instanceof YieldItems)) {\n\t\t\tthis.afterStatement = lastScope.stream()\n\t\t\t\t.filter(i -> !(i instanceof Property))\n\t\t\t\t.collect(Collectors.toCollection(LinkedHashSet::new));\n\t\t}\n\t\telse {\n\t\t\tthis.afterStatement = new LinkedHashSet<>(lastScope);\n\t\t}\n\n\t\t// A procedure call doesn't change scope.\n\t\tif (visitable instanceof ProcedureCall) {\n\t\t\treturn;\n\t\t}\n\n\t\tlastScope.retainAll(Optional.ofNullable(this.implicitScope.peek()).orElseGet(Set::of));\n\t}\n\n\tprivate boolean hasScope() {\n\t\treturn !this.dequeOfVisitedNamed.isEmpty();\n\t}\n\n\tprivate boolean hasVisitedInScope(Collection<IdentifiableElement> visited, Named needle) {\n\n\t\treturn visited.contains(needle) || needle.getSymbolicName().isPresent() && visited.stream()\n\t\t\t.filter(byHasAName())\n\t\t\t.map(ScopingStrategy::extractIdentifier)\n\t\t\t.filter(Objects::nonNull)\n\t\t\t.anyMatch(identifiedBy(needle));\n\t}\n\n\tprivate Predicate<String> identifiedBy(Named needle) {\n\t\treturn i -> {\n\t\t\tboolean result = i.equals(needle.getRequiredSymbolicName().getValue());\n\t\t\tif (result && this.inSubquery) {\n\t\t\t\tvar imported = Optional.ofNullable(this.currentImports.peek()).orElseGet(Set::of).contains(i);\n\t\t\t\treturn imported || this.definedInSubquery.peek().contains(i);\n\t\t\t}\n\t\t\treturn result;\n\t\t};\n\t}\n\n\tprivate void clearPreviouslyVisitedNamed(Visitable visitable) {\n\n\t\tif (visitable instanceof With with) {\n\t\t\tclearPreviouslyVisitedAfterWith(with);\n\t\t}\n\t\telse if (visitable instanceof Return || visitable instanceof YieldItems) {\n\t\t\tclearPreviouslyVisitedAfterReturnish(visitable);\n\t\t}\n\t}\n\n\tprivate void clearPreviouslyVisitedAfterWith(With with) {\n\n\t\t// We need to clear the named cache after defining a with.\n\t\t// Everything not taken into the next step has to go.\n\t\tSet<IdentifiableElement> retain = new HashSet<>();\n\t\tSet<IdentifiableElement> visitedNamed = this.dequeOfVisitedNamed.peek();\n\t\tif (visitedNamed == null) {\n\t\t\treturn;\n\t\t}\n\t\twith.accept(segment -> {\n\t\t\tif (segment instanceof SymbolicName symbolicName) {\n\t\t\t\tvisitedNamed.stream().filter(element -> {\n\t\t\t\t\tif (element instanceof Named named) {\n\t\t\t\t\t\treturn named.getSymbolicName().filter(s -> s.equals(segment)).isPresent();\n\t\t\t\t\t}\n\t\t\t\t\telse if (element instanceof Aliased aliased) {\n\t\t\t\t\t\treturn aliased.getAlias().equals((symbolicName).getValue());\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\treturn element.equals(segment);\n\t\t\t\t\t}\n\t\t\t\t}).forEach(retain::add);\n\t\t\t}\n\t\t\telse if (segment instanceof Asterisk) {\n\t\t\t\tretain.addAll(visitedNamed);\n\t\t\t}\n\t\t});\n\n\t\tretain.addAll(Optional.ofNullable(this.implicitScope.peek()).orElseGet(Set::of));\n\t\tvisitedNamed.retainAll(retain);\n\t}\n\n\tprivate void clearPreviouslyVisitedAfterReturnish(Visitable returnish) {\n\n\t\t// Everything not returned has to go.\n\t\tSet<IdentifiableElement> retain = new HashSet<>();\n\t\tSet<IdentifiableElement> visitedNamed = this.dequeOfVisitedNamed.peek();\n\t\treturnish.accept(new Visitor() {\n\n\t\t\tint level = 0;\n\n\t\t\tVisitable entranceLevel1;\n\n\t\t\t@Override\n\t\t\tpublic void enter(Visitable segment) {\n\t\t\t\tif (this.entranceLevel1 == null && segment instanceof TypedSubtree) {\n\t\t\t\t\tthis.entranceLevel1 = segment;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (this.entranceLevel1 != null) {\n\t\t\t\t\t++this.level;\n\t\t\t\t}\n\n\t\t\t\t// Only collect things exactly one level into the list of returned items\n\t\t\t\tif (this.level == 1 && segment instanceof IdentifiableElement identifiableElement) {\n\t\t\t\t\tretain.add(identifiableElement);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void leave(Visitable segment) {\n\n\t\t\t\tif (this.entranceLevel1 != null) {\n\t\t\t\t\tthis.level = Math.max(0, this.level - 1);\n\t\t\t\t\tif (segment == this.entranceLevel1) {\n\t\t\t\t\t\tthis.entranceLevel1 = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tretain.addAll(Optional.ofNullable(this.implicitScope.peek()).orElseGet(Set::of));\n\t\tif (visitedNamed != null) {\n\t\t\tvisitedNamed.retainAll(retain);\n\t\t}\n\t}\n\n\t/**\n\t * {@return an unmodifiable collections with identifiable in the current scope}\n\t */\n\tpublic Collection<Expression> getIdentifiables() {\n\n\t\tif (!hasScope()) {\n\t\t\treturn Collections.emptySet();\n\t\t}\n\n\t\tPredicate<IdentifiableElement> allNamedElementsHaveResolvedNames = e -> !(e instanceof Named named)\n\t\t\t\t|| named.getSymbolicName().filter(s -> s.getValue() != null).isPresent();\n\n\t\tSet<IdentifiableElement> items = Optional.ofNullable(this.dequeOfVisitedNamed.peek())\n\t\t\t.filter(scope -> !scope.isEmpty())\n\t\t\t.orElse(this.afterStatement);\n\n\t\treturn items.stream()\n\t\t\t.filter(allNamedElementsHaveResolvedNames)\n\t\t\t.map(IdentifiableElement::asExpression)\n\t\t\t.collect(Collectors.collectingAndThen(Collectors.toCollection(LinkedHashSet::new),\n\t\t\t\t\tCollections::unmodifiableSet));\n\t}\n\n\tpublic PatternElement lookup(Named node) {\n\n\t\tif (!hasScope() || node.getSymbolicName().isEmpty()) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar scope = this.dequeOfVisitedNamed.peek();\n\t\tvar identifiedBy = identifiedBy(node);\n\t\treturn scope.stream().filter(byHasAName()).filter(PatternElement.class::isInstance).filter(i -> {\n\t\t\tvar identifier = extractIdentifier(i);\n\t\t\treturn identifier != null && identifiedBy.test(identifier);\n\t\t}).map(PatternElement.class::cast).findFirst().orElse(null);\n\t}\n\n\t/**\n\t * {@return the set of current imports}\n\t */\n\tpublic Set<SymbolicName> getCurrentImports() {\n\t\treturn Optional.ofNullable(this.currentImports.peek())\n\t\t\t.stream()\n\t\t\t.flatMap(v -> v.stream().map(Cypher::name))\n\t\t\t.collect(Collectors.toSet());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/UsingPeriodicCommit.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Neo4jVersion;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * A visitable representing a {@code USING PERIODIC COMMIT} clause. Not meant to be used\n * outside the Cypher-DSL directly. Will be changed without further notice.\n *\n * @author Michael J. Simons\n * @param rate the rate to be applied\n * @since 2021.2.1\n */\n@API(status = INTERNAL, since = \"2021.2.1\")\n@Neo4jVersion(minimum = \"3.5\", last = \"4.4\")\npublic record UsingPeriodicCommit(Integer rate) implements Visitable {\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/YieldItems.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Items yielded by a stand alone or in query call.\n *\n * @author Michael J. Simons\n * @since 2020.0.1\n */\n@API(status = INTERNAL, since = \"2020.0.1\")\npublic final class YieldItems extends TypedSubtree<Expression> {\n\n\tprivate YieldItems(Expression... children) {\n\t\tsuper(children);\n\t}\n\n\t/**\n\t * Creates a new {@literal YIELD} expressions.\n\t * @param c the elements to yield\n\t * @return the new expression\n\t */\n\tpublic static YieldItems yieldAllOf(Expression... c) {\n\n\t\tif (c == null || c.length == 0) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot yield an empty list of items.\");\n\t\t}\n\n\t\treturn new YieldItems(c);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/internal/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * This is basically the kitchen sink for all classes that must be public but are not\n * actually part of the public API. We will change them at will and don't give any\n * guarantees about them. All classes inside that package are marked as\n * {@link org.apiguardian.api.API.Status#INTERNAL}. The {@code internal} package won't be\n * exported when the Cypher-DSL is run on the module path.\n *\n * @author Michael J. Simons\n */\npackage org.neo4j.cypherdsl.core.internal;\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Contains an internal DSL for creating Cypher. This API is in an experimental status at\n * the moment and might change without further notice.\n * <p>\n * While we have extensive tests in place to check that queries SDN needs are correctly\n * generated, the AST itself is not validated for type errors. That is, one could misuse\n * the DSL here to create an AST that renders to a syntactically correct Cypher statement,\n * that will explode during runtime. For example using wrongly typed expression (an\n * expression referencing a list while a map is needed or something like that).\n * <p>\n * With this in mind, please use this DSL consciously if you find it useful. It won't go\n * away anytime soon, but might change in ways that break your code without further\n * notice.\n *\n * @author Michael J. Simons\n */\npackage org.neo4j.cypherdsl.core;\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/querydsl/CypherContext.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.querydsl;\n\nimport java.util.ArrayList;\nimport java.util.IdentityHashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.querydsl.core.types.Operator;\nimport com.querydsl.core.types.Template;\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.Literal.UnsupportedLiteralException;\nimport org.neo4j.cypherdsl.core.Parameter;\nimport org.neo4j.cypherdsl.core.internal.ConstantParameterHolder;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Context of a Cypher-DSL statement, holding all known expressions and parameters.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\npublic final class CypherContext {\n\n\t@SuppressWarnings(\"FieldCanBeLocal\")\n\tprivate static final String TO_STRING_VALUE_OF_UNSUPPORTED = \"'\" + CypherTemplates.UNSUPPORTED_MARKER + \"'\";\n\n\tprivate final List<Expression> expressions = new ArrayList<>();\n\n\tprivate final Map<Object, Parameter<?>> parameters = new IdentityHashMap<>();\n\n\tpublic void add(Expression expression) {\n\t\tthis.expressions.add(expression);\n\t}\n\n\tpublic Expression[] getExpressions() {\n\t\treturn this.expressions.toArray(new Expression[0]);\n\t}\n\n\tTemplate getTemplate(Operator op) {\n\n\t\tTemplate template = CypherTemplates.DEFAULT.getTemplate(op);\n\t\tif (template != null) {\n\t\t\tfor (Template.Element element : template.getElements()) {\n\t\t\t\tif (TO_STRING_VALUE_OF_UNSUPPORTED.equals(element.toString())) {\n\t\t\t\t\tthrow new UnsupportedOperatorException(op);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn template;\n\t}\n\n\tint getPrecedence(Operator op) {\n\t\treturn CypherTemplates.DEFAULT.getPrecedence(op);\n\t}\n\n\tParameter<?> getOrCreateParameterFor(Object object) {\n\n\t\treturn this.parameters.computeIfAbsent(object, o -> {\n\t\t\tObject value;\n\t\t\ttry {\n\t\t\t\tvalue = new ConstantParameterHolder(o);\n\t\t\t}\n\t\t\tcatch (UnsupportedLiteralException ex) {\n\t\t\t\tvalue = o;\n\t\t\t}\n\t\t\treturn Cypher.anonParameter(value);\n\t\t});\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/querydsl/CypherTemplates.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.querydsl;\n\nimport com.querydsl.core.types.Ops;\nimport com.querydsl.core.types.PathType;\nimport com.querydsl.core.types.Templates;\n\n/**\n * Static holder for Cypher templates for the QueryDSL adapter.\n *\n * @author Michael J. Simons\n */\nfinal class CypherTemplates extends Templates {\n\n\tstatic final String UNSUPPORTED_MARKER = \"__UNSUPPORTED__\";\n\tstatic final Templates DEFAULT = new CypherTemplates();\n\n\tprivate CypherTemplates() {\n\t\tsuper('\\\\');\n\n\t\tfinal String sizeOfOneElement = \"size({0})\";\n\n\t\t// boolean\n\t\tadd(Ops.AND, \"{0} AND {1}\", Precedence.AND);\n\t\tadd(Ops.NOT, \"NOT {0}\", Precedence.NOT_HIGH);\n\t\tadd(Ops.OR, \"{0} OR {1}\", Precedence.OR);\n\t\tadd(Ops.XNOR, \"NOT ({0} XOR {1})\", Precedence.XNOR);\n\t\tadd(Ops.XOR, \"{0} XOR {1}\", Precedence.XOR);\n\n\t\t// collection\n\t\tadd(Ops.COL_IS_EMPTY, \"size({0}) = 0\");\n\t\tadd(Ops.COL_SIZE, sizeOfOneElement);\n\n\t\t// array\n\t\tadd(Ops.ARRAY_SIZE, sizeOfOneElement);\n\n\t\t// map\n\t\tadd(Ops.MAP_SIZE, \"size(keys({0}))\");\n\t\tadd(Ops.MAP_IS_EMPTY, \"size(keys({0})) = 0\");\n\t\tadd(Ops.CONTAINS_KEY, \"any(v in keys({0}) where v = {1})\");\n\t\tadd(Ops.CONTAINS_VALUE, \"any(v in [k IN KEYS({0}) | {0}[k]] where v = {1})\");\n\n\t\t// comparison\n\t\tadd(Ops.BETWEEN, \"{0} >= {1} AND {0} <= {2}\", Precedence.COMPARISON);\n\t\tadd(Ops.GOE, \"{0} >= {1}\", Precedence.COMPARISON);\n\t\tadd(Ops.GT, \"{0} > {1}\", Precedence.COMPARISON);\n\t\tadd(Ops.LOE, \"{0} <= {1}\", Precedence.COMPARISON);\n\t\tadd(Ops.LT, \"{0} < {1}\", Precedence.COMPARISON);\n\n\t\t// numeric\n\t\tadd(Ops.NEGATE, \"-{0}\", Precedence.NEGATE);\n\t\tadd(Ops.ADD, \"{0} + {1}\", Precedence.ARITH_LOW);\n\t\tadd(Ops.DIV, \"{0} / {1}\", Precedence.ARITH_HIGH);\n\t\tadd(Ops.MOD, \"{0} % {1}\", Precedence.ARITH_HIGH);\n\t\tadd(Ops.MULT, \"{0} * {1}\", Precedence.ARITH_HIGH);\n\t\tadd(Ops.SUB, \"{0} - {1}\", Precedence.ARITH_LOW);\n\n\t\t// various\n\t\tadd(Ops.EQ, \"{0} = {1}\", Precedence.EQUALITY);\n\t\tadd(Ops.EQ_IGNORE_CASE, \"{0l} = {1l}\", Precedence.EQUALITY);\n\t\tadd(Ops.INSTANCE_OF, UNSUPPORTED_MARKER, Precedence.COMPARISON);\n\t\tadd(Ops.NE, \"{0} != {1}\", Precedence.EQUALITY);\n\n\t\tadd(Ops.IN, \"any(v in {0} where v = {1})\", Precedence.COMPARISON);\n\t\tadd(Ops.NOT_IN, \"none(v in {0} where v = {1})\", Precedence.COMPARISON);\n\t\tadd(Ops.IS_NULL, \"{0} is null\", Precedence.COMPARISON);\n\t\tadd(Ops.IS_NOT_NULL, \"{0} is not null\", Precedence.COMPARISON);\n\t\tadd(Ops.ALIAS, \"{0} as {1}\", 0);\n\n\t\tadd(Ops.NUMCAST, UNSUPPORTED_MARKER);\n\t\tadd(Ops.STRING_CAST, UNSUPPORTED_MARKER);\n\n\t\t// string\n\t\tadd(Ops.CONCAT, \"{0} + {1}\", Precedence.ARITH_LOW);\n\t\tadd(Ops.LOWER, \"toLower({0})\");\n\t\tadd(Ops.SUBSTR_1ARG, \"substring({0}, {1})\");\n\t\tadd(Ops.SUBSTR_2ARGS, \"substring({0}, {1}, {2})\");\n\t\tadd(Ops.TRIM, \"trim({0})\");\n\t\tadd(Ops.UPPER, \"toUpper({0})\");\n\t\tadd(Ops.MATCHES, \"{0} =~ {1}\");\n\t\tadd(Ops.MATCHES_IC, \"{0} =~ ('(?i)' + {1})\");\n\t\tadd(Ops.STARTS_WITH, \"{0} STARTS WITH {1}\");\n\t\tadd(Ops.STARTS_WITH_IC, \"{0l} STARTS WITH {1l}\");\n\t\tadd(Ops.ENDS_WITH, \"{0} ENDS WITH {1}\");\n\t\tadd(Ops.ENDS_WITH_IC, \"{0l} ENDS WITH {1l}\");\n\t\tadd(Ops.STRING_CONTAINS, \"{0} CONTAINS {1}\");\n\t\tadd(Ops.STRING_CONTAINS_IC, \"{0l} CONTAINS {1l}\");\n\t\tadd(Ops.CHAR_AT, \"substring({0}, {1}, 1)\");\n\t\tadd(Ops.STRING_LENGTH, sizeOfOneElement);\n\t\tadd(Ops.INDEX_OF, UNSUPPORTED_MARKER);\n\t\tadd(Ops.INDEX_OF_2ARGS, UNSUPPORTED_MARKER);\n\t\tadd(Ops.STRING_IS_EMPTY, \"size({0}) = 0 \");\n\t\tadd(Ops.LIKE, \"{0} =~ '.*' + {1} + '.*'\", Precedence.COMPARISON);\n\t\tadd(Ops.LIKE_IC, \"{0} =~ '(?i).*' + {1} + '.*'\", Precedence.COMPARISON);\n\t\tadd(Ops.LIKE_ESCAPE, UNSUPPORTED_MARKER, Precedence.COMPARISON);\n\t\tadd(Ops.LIKE_ESCAPE_IC, UNSUPPORTED_MARKER, Precedence.COMPARISON);\n\n\t\tadd(Ops.StringOps.LEFT, \"left({0}, {1})\");\n\t\tadd(Ops.StringOps.RIGHT, \"right({0}, {1})\");\n\t\tadd(Ops.StringOps.LTRIM, \"ltrim({0})\");\n\t\tadd(Ops.StringOps.RTRIM, \"rtrim({0})\");\n\t\tadd(Ops.StringOps.LOCATE, UNSUPPORTED_MARKER);\n\t\tadd(Ops.StringOps.LOCATE2, UNSUPPORTED_MARKER);\n\t\tadd(Ops.StringOps.LPAD, UNSUPPORTED_MARKER);\n\t\tadd(Ops.StringOps.RPAD, UNSUPPORTED_MARKER);\n\t\tadd(Ops.StringOps.LPAD2, UNSUPPORTED_MARKER);\n\t\tadd(Ops.StringOps.RPAD2, UNSUPPORTED_MARKER);\n\n\t\t// date time\n\t\tadd(Ops.DateTimeOps.SYSDATE, \"datetime()\");\n\t\tadd(Ops.DateTimeOps.CURRENT_DATE, \"date()\");\n\t\tadd(Ops.DateTimeOps.CURRENT_TIME, \"time()\");\n\t\tadd(Ops.DateTimeOps.CURRENT_TIMESTAMP, \"datetime().epochmillis\");\n\t\tadd(Ops.DateTimeOps.DATE, \"date({0})\");\n\n\t\tadd(Ops.DateTimeOps.MILLISECOND, \"{0}.millisecond\");\n\t\tadd(Ops.DateTimeOps.SECOND, \"{0}.second\");\n\t\tadd(Ops.DateTimeOps.MINUTE, \"{0}.minute\");\n\t\tadd(Ops.DateTimeOps.HOUR, \"{0}.hour\");\n\t\tadd(Ops.DateTimeOps.WEEK, \"{0}.week\");\n\t\tadd(Ops.DateTimeOps.MONTH, \"{0}.month\");\n\t\tadd(Ops.DateTimeOps.YEAR, \"{0}.year\");\n\t\tadd(Ops.DateTimeOps.YEAR_MONTH, UNSUPPORTED_MARKER);\n\t\tadd(Ops.DateTimeOps.YEAR_WEEK, \"{0}.weekYear\");\n\t\tadd(Ops.DateTimeOps.DAY_OF_WEEK, \"{0}.dayOfWeek\");\n\t\tadd(Ops.DateTimeOps.DAY_OF_MONTH, UNSUPPORTED_MARKER);\n\t\tadd(Ops.DateTimeOps.DAY_OF_YEAR, UNSUPPORTED_MARKER);\n\n\t\tadd(Ops.DateTimeOps.ADD_YEARS, \"{0} + duration({years: {1}})\");\n\t\tadd(Ops.DateTimeOps.ADD_MONTHS, \"{0} + duration({months: {1}})\");\n\t\tadd(Ops.DateTimeOps.ADD_WEEKS, \"{0} + duration({weeks: {1}})\");\n\t\tadd(Ops.DateTimeOps.ADD_DAYS, \"{0} + duration({days: {1}})\");\n\t\tadd(Ops.DateTimeOps.ADD_HOURS, \"{0} + duration({hours: {1}})\");\n\t\tadd(Ops.DateTimeOps.ADD_MINUTES, \"{0} + duration({minutes: {1}})\");\n\t\tadd(Ops.DateTimeOps.ADD_SECONDS, \"{0} + duration({seconds: {1}})\");\n\n\t\tadd(Ops.DateTimeOps.DIFF_YEARS, \"duration.between({0}, {1}).years\");\n\t\tadd(Ops.DateTimeOps.DIFF_MONTHS, \"duration.between({0}, {1}).months\");\n\t\tadd(Ops.DateTimeOps.DIFF_WEEKS, \"duration.between({0}, {1}).weeks\");\n\t\tadd(Ops.DateTimeOps.DIFF_DAYS, \"duration.between({0}, {1}).days\");\n\t\tadd(Ops.DateTimeOps.DIFF_HOURS, \"duration.between({0}, {1}).hours\");\n\t\tadd(Ops.DateTimeOps.DIFF_MINUTES, \"duration.between({0}, {1}).minutes\");\n\t\tadd(Ops.DateTimeOps.DIFF_SECONDS, \"duration.between({0}, {1}).seconds\");\n\n\t\tadd(Ops.DateTimeOps.TRUNC_YEAR, \"date.truncate('year', {0})\");\n\t\tadd(Ops.DateTimeOps.TRUNC_MONTH, \"date.truncate('month', {0})\");\n\t\tadd(Ops.DateTimeOps.TRUNC_WEEK, \"date.truncate('week', {0})\");\n\t\tadd(Ops.DateTimeOps.TRUNC_DAY, \"date.truncate('day', {0})\");\n\t\tadd(Ops.DateTimeOps.TRUNC_HOUR, \"datetime.truncate('hour', {0})\");\n\t\tadd(Ops.DateTimeOps.TRUNC_MINUTE, \"datetime.truncate('minute', {0})\");\n\t\tadd(Ops.DateTimeOps.TRUNC_SECOND, \"datetime.truncate('second', {0})\");\n\n\t\t// math\n\t\tadd(Ops.MathOps.ABS, \"abs({0})\");\n\t\tadd(Ops.MathOps.ACOS, \"acos({0})\");\n\t\tadd(Ops.MathOps.ASIN, \"asin({0})\");\n\t\tadd(Ops.MathOps.ATAN, \"atan({0})\");\n\t\tadd(Ops.MathOps.CEIL, \"ceil({0})\");\n\t\tadd(Ops.MathOps.COS, \"cos({0})\");\n\t\tadd(Ops.MathOps.COSH, UNSUPPORTED_MARKER);\n\t\tadd(Ops.MathOps.COT, \"cot({0})\");\n\t\tadd(Ops.MathOps.COTH, UNSUPPORTED_MARKER);\n\t\tadd(Ops.MathOps.DEG, \"degrees({0})\");\n\t\tadd(Ops.MathOps.TAN, \"tan({0})\");\n\t\tadd(Ops.MathOps.TANH, UNSUPPORTED_MARKER);\n\t\tadd(Ops.MathOps.SQRT, \"sqrt({0})\");\n\t\tadd(Ops.MathOps.SIGN, \"sign({0})\");\n\t\tadd(Ops.MathOps.SIN, \"sin({0})\");\n\t\tadd(Ops.MathOps.SINH, UNSUPPORTED_MARKER);\n\t\tadd(Ops.MathOps.ROUND, \"round({0})\");\n\t\tadd(Ops.MathOps.ROUND2, \"round({0}, {1})\");\n\t\tadd(Ops.MathOps.RAD, \"radians({0})\");\n\t\tadd(Ops.MathOps.RANDOM, UNSUPPORTED_MARKER);\n\t\tadd(Ops.MathOps.RANDOM2, UNSUPPORTED_MARKER);\n\t\tadd(Ops.MathOps.POWER, UNSUPPORTED_MARKER);\n\t\tadd(Ops.MathOps.MIN, \"CASE WHEN {0} < {1} THEN {0} ELSE {1} END\");\n\t\tadd(Ops.MathOps.MAX, \"CASE WHEN {0} > {1} THEN {0} ELSE {1} END\");\n\t\tadd(Ops.MathOps.LOG, UNSUPPORTED_MARKER);\n\t\tadd(Ops.MathOps.LN, UNSUPPORTED_MARKER);\n\t\tadd(Ops.MathOps.FLOOR, \"floor({0})\");\n\t\tadd(Ops.MathOps.EXP, \"exp({0})\");\n\n\t\t// path types\n\t\tadd(PathType.PROPERTY, \"{0}.{1s}\");\n\t\tadd(PathType.VARIABLE, \"{0s}\");\n\t\tadd(PathType.DELEGATE, \"{0}\");\n\t\tadd(Ops.ORDINAL, UNSUPPORTED_MARKER);\n\n\t\tfor (PathType type : new PathType[] { PathType.LISTVALUE, PathType.MAPVALUE, PathType.ARRAYVALUE }) {\n\t\t\tadd(type, \"{0}[{1}]\");\n\t\t}\n\t\tfor (PathType type : new PathType[] { PathType.LISTVALUE_CONSTANT, PathType.MAPVALUE_CONSTANT,\n\t\t\t\tPathType.ARRAYVALUE_CONSTANT }) {\n\t\t\tadd(type, \"{0}[{1s}]\");\n\t\t}\n\n\t\t// case\n\t\tadd(Ops.CASE, \"CASE {0} END\", Precedence.CASE);\n\t\tadd(Ops.CASE_WHEN, \"WHEN {0} THEN {1} {2}\", Precedence.CASE);\n\t\tadd(Ops.CASE_ELSE, \"ELSE {0}\", Precedence.CASE);\n\n\t\t// case for\n\t\tadd(Ops.CASE_EQ, \"CASE {0} {1} END\", Precedence.CASE);\n\t\tadd(Ops.CASE_EQ_WHEN, \"WHEN {1} THEN {2} {3}\", Precedence.CASE);\n\t\tadd(Ops.CASE_EQ_ELSE, \"ELSE {0}\", Precedence.CASE);\n\n\t\t// coalesce\n\t\tadd(Ops.COALESCE, \"coalesce({0})\");\n\n\t\tadd(Ops.NULLIF, UNSUPPORTED_MARKER);\n\n\t\t// subquery\n\t\tadd(Ops.EXISTS, \"exists({0})\", 0);\n\n\t\t// numeric aggregates\n\t\tadd(Ops.AggOps.BOOLEAN_ALL, \"all({0})\");\n\t\tadd(Ops.AggOps.BOOLEAN_ANY, \"any({0})\");\n\t\tadd(Ops.AggOps.AVG_AGG, \"avg({0})\");\n\t\tadd(Ops.AggOps.MAX_AGG, \"max({0})\");\n\t\tadd(Ops.AggOps.MIN_AGG, \"min({0})\");\n\t\tadd(Ops.AggOps.SUM_AGG, \"sum({0})\");\n\t\tadd(Ops.AggOps.COUNT_AGG, \"count({0})\");\n\t\tadd(Ops.AggOps.COUNT_DISTINCT_AGG, \"count(distinct {0})\");\n\t\tadd(Ops.AggOps.COUNT_DISTINCT_ALL_AGG, \"count(distinct *)\");\n\t\tadd(Ops.AggOps.COUNT_ALL_AGG, \"count(*)\");\n\n\t\t// quantified expressions\n\t\tadd(Ops.QuantOps.AVG_IN_COL, \"avg({0})\");\n\t\tadd(Ops.QuantOps.MAX_IN_COL, \"max({0})\");\n\t\tadd(Ops.QuantOps.MIN_IN_COL, \"min({0})\");\n\n\t\tadd(Ops.QuantOps.ANY, \"any {0}\");\n\t\tadd(Ops.QuantOps.ALL, \"all {0}\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/querydsl/ToCypherFormatStringVisitor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.querydsl;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport com.querydsl.core.types.Constant;\nimport com.querydsl.core.types.Expression;\nimport com.querydsl.core.types.FactoryExpression;\nimport com.querydsl.core.types.Operation;\nimport com.querydsl.core.types.ParamExpression;\nimport com.querydsl.core.types.Path;\nimport com.querydsl.core.types.SubQueryExpression;\nimport com.querydsl.core.types.Template;\nimport com.querydsl.core.types.TemplateExpression;\nimport com.querydsl.core.types.Visitor;\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Cypher;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * This is basically a copy of Query-DSL's\n * {@link com.querydsl.core.types.ToStringVisitor}. The main purpose of the string\n * generated here is to be used with our {@link Cypher#raw(String, Object...)} feature,\n * that allows to insert arbitrary query fragments into the AST. It is easier to render\n * the Query-DSL fragments than recreating our AST from Query-DSL.\n * <p>\n * The main difference in the original {@code ToStringVisitor} is to be found in\n * {@link #visit(ParamExpression, CypherContext)} and\n * {@link #visit(Constant, CypherContext)}. Both methods will use the {@literal $E}\n * notation to indicate an expression for the {@code RawLiteral} and add the expression\n * (either a literal or parameter) to the {@link CypherContext}. After all rendering has\n * been done by Query-DSL, the adapter will take the renderer string as a format string\n * and pass it on to {@link Cypher#raw(String, Object...)} along with all expressions\n * collected along the way.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\npublic final class ToCypherFormatStringVisitor implements Visitor<String, CypherContext> {\n\n\t/**\n\t * Global instance of this visitor.\n\t */\n\tpublic static final ToCypherFormatStringVisitor INSTANCE = new ToCypherFormatStringVisitor();\n\n\tprivate ToCypherFormatStringVisitor() {\n\t}\n\n\t@Override\n\tpublic String visit(FactoryExpression<?> e, CypherContext context) {\n\n\t\tfinal StringBuilder builder = new StringBuilder();\n\t\tbuilder.append(\"new \").append(e.getType().getSimpleName()).append(\"(\");\n\t\tboolean first = true;\n\t\tfor (Expression<?> arg : e.getArgs()) {\n\t\t\tif (!first) {\n\t\t\t\tbuilder.append(\", \");\n\t\t\t}\n\t\t\tbuilder.append(arg.accept(this, context));\n\t\t\tfirst = false;\n\t\t}\n\t\tbuilder.append(\")\");\n\t\treturn builder.toString();\n\t}\n\n\t@Override\n\tpublic String visit(Operation<?> o, CypherContext context) {\n\n\t\tfinal Template template = context.getTemplate(o.getOperator());\n\t\tif (template != null) {\n\t\t\tfinal int precedence = context.getPrecedence(o.getOperator());\n\t\t\tfinal StringBuilder builder = new StringBuilder();\n\t\t\tfor (Template.Element element : template.getElements()) {\n\t\t\t\tfinal Object rv = element.convert(o.getArgs());\n\t\t\t\tif (rv instanceof Expression) {\n\t\t\t\t\tif (precedence > -1 && rv instanceof Operation\n\t\t\t\t\t\t\t&& precedence < context.getPrecedence(((Operation<?>) rv).getOperator())) {\n\t\t\t\t\t\tbuilder.append(\"(\").append(((Expression<?>) rv).accept(this, context)).append(\")\");\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tbuilder.append(((Expression<?>) rv).accept(this, context));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbuilder.append(rv.toString());\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn builder.toString();\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"unknown operation with operator \" + o.getOperator().name() + \" and args \" + o.getArgs());\n\t\t}\n\t}\n\n\t@Override\n\tpublic String visit(ParamExpression<?> param, CypherContext context) {\n\n\t\tcontext.add(Cypher.parameter(param.getName()));\n\t\treturn \"$E\";\n\t}\n\n\t@Override\n\tpublic String visit(Path<?> p, CypherContext context) {\n\n\t\tfinal Path<?> parent = p.getMetadata().getParent();\n\t\tfinal Object elem = p.getMetadata().getElement();\n\t\tif (parent != null) {\n\t\t\tTemplate pattern = context.getTemplate(p.getMetadata().getPathType());\n\t\t\tif (pattern != null) {\n\t\t\t\tfinal List<?> args = Arrays.asList(parent, elem);\n\t\t\t\tfinal StringBuilder builder = new StringBuilder();\n\t\t\t\tfor (Template.Element element : pattern.getElements()) {\n\t\t\t\t\tObject rv = element.convert(args);\n\t\t\t\t\tif (rv instanceof Expression) {\n\t\t\t\t\t\tbuilder.append(((Expression<?>) rv).accept(this, context));\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tbuilder.append(rv.toString());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn builder.toString();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new IllegalArgumentException(\"No pattern for \" + p.getMetadata().getPathType());\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\treturn elem.toString();\n\t\t}\n\t}\n\n\t@Override\n\tpublic String visit(SubQueryExpression<?> expr, CypherContext context) {\n\t\treturn expr.getMetadata().toString();\n\t}\n\n\t@Override\n\tpublic String visit(TemplateExpression<?> expr, CypherContext context) {\n\n\t\tfinal StringBuilder builder = new StringBuilder();\n\t\tfor (Template.Element element : expr.getTemplate().getElements()) {\n\t\t\tObject rv = element.convert(expr.getArgs());\n\t\t\tif (rv instanceof Expression) {\n\t\t\t\tbuilder.append(((Expression<?>) rv).accept(this, context));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbuilder.append(rv.toString());\n\t\t\t}\n\t\t}\n\t\treturn builder.toString();\n\t}\n\n\t@Override\n\tpublic String visit(Constant<?> expr, CypherContext context) {\n\n\t\tObject constantValue = expr.getConstant();\n\t\tif (constantValue == null) {\n\t\t\tcontext.add(Cypher.literalOf(null));\n\t\t}\n\t\telse if (constantValue instanceof Boolean) {\n\t\t\tcontext.add(Cypher.literalOf(constantValue));\n\t\t}\n\t\telse {\n\t\t\tcontext.add(context.getOrCreateParameterFor(constantValue));\n\t\t}\n\n\t\treturn \"$E\";\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/querydsl/UnsupportedOperatorException.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.querydsl;\n\nimport java.io.Serial;\n\nimport com.querydsl.core.types.Operator;\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Thrown when a QueryDSL operator cannot be used with the Cypher-DSL predicate converter.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = STABLE, since = \"2021.1.0\")\npublic final class UnsupportedOperatorException extends IllegalArgumentException {\n\n\t@Serial\n\tprivate static final long serialVersionUID = 2025849674095086421L;\n\n\tprivate final Operator unsupportedOperator;\n\n\tpublic UnsupportedOperatorException(Operator unsupportedOperator) {\n\t\tsuper(\"The Cypher-DSL cannot use the Query-DSL operator \" + unsupportedOperator);\n\t\tthis.unsupportedOperator = unsupportedOperator;\n\t}\n\n\tpublic Operator getUnsupportedOperator() {\n\t\treturn this.unsupportedOperator;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/querydsl/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Shims for turning Query-DSL predicates into conditions.\n */\npackage org.neo4j.cypherdsl.core.querydsl;\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/ConfigurableRenderer.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReadWriteLock;\nimport java.util.concurrent.locks.ReentrantReadWriteLock;\nimport java.util.function.BiFunction;\n\nimport org.neo4j.cypherdsl.core.Statement;\nimport org.neo4j.cypherdsl.core.StatementContext;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.internal.DefaultStatementContext;\nimport org.neo4j.cypherdsl.core.utils.LRUCache;\n\n/**\n * The default renderer for any Cypher-DSL statement.\n *\n * @author Michael J. Simons\n * @author Gerrit Meier\n * @since 1.0\n */\nfinal class ConfigurableRenderer implements GeneralizedRenderer, Renderer {\n\n\tprivate static final Map<Configuration, ConfigurableRenderer> CONFIGURATIONS = new ConcurrentHashMap<>(8);\n\n\tprivate static final int STATEMENT_CACHE_SIZE = 128;\n\n\tprivate final LRUCache<Integer, String> renderedStatementCache = new LRUCache<>(STATEMENT_CACHE_SIZE);\n\n\tprivate final ReadWriteLock lock = new ReentrantReadWriteLock();\n\n\tprivate final Lock read = this.lock.readLock();\n\n\tprivate final Lock write = this.lock.writeLock();\n\n\tprivate final Configuration configuration;\n\n\tConfigurableRenderer(Configuration configuration) {\n\t\tthis.configuration = configuration;\n\t}\n\n\t/**\n\t * Creates a new instance of the configurable renderer or uses an existing one\n\t * matching the given configuration.\n\t * @param configuration the configuration for the render\n\t * @return a new renderer\n\t */\n\tstatic ConfigurableRenderer create(Configuration configuration) {\n\t\treturn CONFIGURATIONS.computeIfAbsent(configuration, ConfigurableRenderer::new);\n\t}\n\n\t@Override\n\tpublic String render(Statement statement) {\n\t\treturn render((Visitable) statement);\n\t}\n\n\t@Override\n\t// This is about not using map.computeIfAbsent. This is done very much on purpose to\n\t// keep this\n\t// class thread safe. The LRUCache is basically LinkedHashMap and the method wouldn't\n\t// be threadsafe.\n\t@SuppressWarnings(\"squid:S3824\")\n\tpublic String render(Visitable visitable) {\n\n\t\trecord RenderingConfig(StatementContext ctx, boolean renderConstantsAsParameters) {\n\t\t}\n\n\t\tBiFunction<RenderingConfig, Visitable, String> renderOp = (cfg, v) -> {\n\t\t\tvar renderingVisitor = createVisitor(cfg.ctx, cfg.renderConstantsAsParameters);\n\t\t\tv.accept(renderingVisitor);\n\t\t\tvar result = renderingVisitor.getRenderedContent().trim();\n\t\t\treturn this.configuration.getDialect().getPrefix().map(pv -> pv + result).orElse(result);\n\t\t};\n\n\t\tif (visitable instanceof Statement statement) {\n\t\t\tString renderedContent;\n\n\t\t\tint key = Objects.hash(statement, statement.isRenderConstantsAsParameters(),\n\t\t\t\t\tthis.configuration.getDialect());\n\t\t\ttry {\n\t\t\t\tthis.read.lock();\n\t\t\t\trenderedContent = this.renderedStatementCache.get(key);\n\t\t\t}\n\t\t\tfinally {\n\t\t\t\tthis.read.unlock();\n\t\t\t}\n\n\t\t\tif (renderedContent == null) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.write.lock();\n\t\t\t\t\trenderedContent = renderOp.apply(\n\t\t\t\t\t\t\tnew RenderingConfig(statement.getContext(), statement.isRenderConstantsAsParameters()),\n\t\t\t\t\t\t\tstatement);\n\t\t\t\t\tthis.renderedStatementCache.put(key, renderedContent);\n\t\t\t\t}\n\t\t\t\tcatch (SchemaEnforcementFailedException ex) {\n\t\t\t\t\trenderedContent = \"\";\n\t\t\t\t}\n\t\t\t\tfinally {\n\t\t\t\t\tthis.write.unlock();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn renderedContent;\n\t\t}\n\t\telse {\n\t\t\treturn renderOp.apply(new RenderingConfig(new DefaultStatementContext(), false), visitable);\n\t\t}\n\t}\n\n\tprivate RenderingVisitor createVisitor(StatementContext statementContext, boolean renderConstantsAsParameters) {\n\n\t\tif (!this.configuration.isPrettyPrint()) {\n\t\t\treturn new DefaultVisitor(statementContext, renderConstantsAsParameters, this.configuration);\n\t\t}\n\t\telse {\n\t\t\treturn new PrettyPrintingVisitor(statementContext, renderConstantsAsParameters, this.configuration);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/Configuration.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport java.util.ArrayList;\nimport java.util.EnumSet;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.EXPERIMENTAL;\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * This class provides some configuration settings for the Cypher-DSL, mainly around\n * rendering of a statement. Instances of {@link Configuration} are threadsafe and can be\n * reused. Please use the {@link Configuration.Builder associated builder} via\n * {@link Configuration#newConfig()} to create new variants.\n *\n * @author Michael J. Simons\n * @since 2021.0.1\n */\n@API(status = STABLE, since = \"2021.0.1\")\npublic final class Configuration {\n\n\tprivate static final Configuration DEFAULT_CONFIG = newConfig().build();\n\n\tprivate static final Configuration PRETTY_PRINTING = newConfig().withPrettyPrint(true)\n\t\t.alwaysEscapeNames(false)\n\t\t.build();\n\n\t/**\n\t * Set to {@literal true} to enable pretty printing.\n\t */\n\tprivate final boolean prettyPrint;\n\n\t/**\n\t * Configure your favorite indentation style.\n\t */\n\tprivate final IndentStyle indentStyle;\n\n\t/**\n\t * The indentation sizes. Only applicable when using {@link IndentStyle#SPACE}.\n\t * Defaults to {@literal 2}.\n\t */\n\tprivate final int indentSize;\n\n\t/**\n\t * A flag if all names (node labels and relationship types) should be escaped all the\n\t * time. Defaults to {@literal true}. When pretty printing, this defaults to\n\t * {@literal false}.\n\t */\n\tprivate final boolean alwaysEscapeNames;\n\n\t/**\n\t * Configure if and which names (identifiers of entities, parameter names and aliases)\n\t * will be replaced with generated names during rendering. The names will stay\n\t * constant for the lifetime of a statement. It defaults to the empty set. This\n\t * setting can be useful if you want to normalize your statements: Imagine two\n\t * statements coming from two different sources who may have used different variable\n\t * or parameter names. Using generated names will make those statements produce the\n\t * same rendering, given they have the same semantics.\n\t *\n\t */\n\tprivate final Set<GeneratedNames> generatedNames;\n\n\t/**\n\t * The dialect to use when rendering a statement. The default dialect works well with\n\t * Neo4j 4.4 and prior.\n\t */\n\tprivate final Dialect dialect;\n\n\t/**\n\t * A flag of the renderer should be instructed to enforce a schema.\n\t */\n\tprivate final boolean enforceSchema;\n\n\t/**\n\t * The map of known relationship definitions. The key is the relationship type.\n\t */\n\tprivate final Map<String, List<RelationshipDefinition>> relationshipDefinitions;\n\n\t/**\n\t * Flag that can be used to disable dynamic labels, defaults to false.\n\t */\n\tprivate final boolean disableDynamicLabels;\n\n\tprivate Configuration(Builder builder) {\n\t\tthis.prettyPrint = builder.prettyPrint;\n\t\tthis.alwaysEscapeNames = builder.alwaysEscapeNames;\n\t\tthis.indentStyle = builder.indentStyle;\n\t\tthis.indentSize = builder.indentSize;\n\t\tthis.dialect = (builder.dialect != null) ? builder.dialect : Dialect.NEO4J_5_DEFAULT_CYPHER;\n\t\tthis.generatedNames = builder.generatedNames;\n\t\tthis.enforceSchema = builder.enforceSchema;\n\t\tthis.disableDynamicLabels = builder.disableDynamicLabels;\n\n\t\tMap<String, List<RelationshipDefinition>> mutableRelationshipDefinitions = new HashMap<>();\n\t\tbuilder.relationshipDefinitions.forEach((k, v) -> mutableRelationshipDefinitions.put(k, List.copyOf(v)));\n\t\tthis.relationshipDefinitions = Map.copyOf(mutableRelationshipDefinitions);\n\t}\n\n\t/**\n\t * Creates a new relationship definition from a string in the form\n\t * {@code (sourceLabel, TYPE, targetLabel)}.\n\t * @param definition the literal definition of the relationship\n\t * @return a new relationship definition\n\t */\n\tpublic static RelationshipDefinition relationshipDefinition(String definition) {\n\t\treturn RelationshipDefinition.of(definition);\n\t}\n\n\t/**\n\t * Cypher is not pretty printed by default. No indentation settings apply.\n\t * @return the default config\n\t */\n\tpublic static Configuration defaultConfig() {\n\t\treturn DEFAULT_CONFIG;\n\t}\n\n\t/**\n\t * Pretty printing with default indentation settings.\n\t * @return a configuration enabling pretty printing.\n\t */\n\tpublic static Configuration prettyPrinting() {\n\t\treturn PRETTY_PRINTING;\n\t}\n\n\t/**\n\t * {@return a new builder} for creating a new configuration from scratch\n\t */\n\tpublic static Builder newConfig() {\n\t\treturn Builder.newConfig();\n\t}\n\n\t/**\n\t * {@return <code>true</code> if this configuration uses pretty printing}\n\t */\n\tpublic boolean isPrettyPrint() {\n\t\treturn this.prettyPrint;\n\t}\n\n\t/**\n\t * {@return the indentation style} whether to use tabs or spaces to indent things\n\t */\n\tpublic IndentStyle getIndentStyle() {\n\t\treturn this.indentStyle;\n\t}\n\n\t/**\n\t * {@return width of one indentation}\n\t */\n\tpublic int getIndentSize() {\n\t\treturn this.indentSize;\n\t}\n\n\t/**\n\t * {@return <code>true</code> when names should be always escaped}\n\t */\n\tpublic boolean isAlwaysEscapeNames() {\n\t\treturn this.alwaysEscapeNames;\n\t}\n\n\t/**\n\t * Returns the set of object types for which generated names should be used.\n\t * @return the set of object types for which generated names should be used\n\t * @since 2023.2.0\n\t */\n\tpublic Set<GeneratedNames> getGeneratedNames() {\n\t\treturn this.generatedNames;\n\t}\n\n\t/**\n\t * Returns {@literal true} when symbolic and parameter names should be replaced with *\n\t * generated names.\n\t * @return {@literal true} when symbolic and parameter names should be replaced with\n\t * generated names\n\t * @since 2023.2.0\n\t */\n\tpublic boolean isUseGeneratedNames() {\n\t\treturn !this.generatedNames.isEmpty();\n\t}\n\n\t/**\n\t * {@return the target dialect}\n\t */\n\tpublic Dialect getDialect() {\n\t\treturn this.dialect;\n\t}\n\n\t/**\n\t * Returns {@literal true} if a schema should be enforced.\n\t * @return {@literal true} if a schema should be enforced\n\t * @since 2023.7.0\n\t */\n\t@API(status = EXPERIMENTAL, since = \"2023.7.0\")\n\tpublic boolean isEnforceSchema() {\n\t\treturn this.enforceSchema;\n\t}\n\n\t/**\n\t * Returns a map of predefined relationships.\n\t * @return a map of predefined relationships\n\t * @since 2023.7.0\n\t */\n\t@API(status = EXPERIMENTAL, since = \"2023.7.0\")\n\tpublic Map<String, List<RelationshipDefinition>> getRelationshipDefinitions() {\n\t\treturn this.relationshipDefinitions;\n\t}\n\n\t/**\n\t * Returns {@literal true} if dynamic labels are disabled.\n\t * @return {@literal true} if dynamic labels are disabled\n\t * @since 2025.0.3\n\t */\n\tpublic boolean isDisableDynamicLabels() {\n\t\treturn this.disableDynamicLabels;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (this == o) {\n\t\t\treturn true;\n\t\t}\n\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\treturn false;\n\t\t}\n\t\tConfiguration that = (Configuration) o;\n\t\treturn this.prettyPrint == that.prettyPrint && this.indentSize == that.indentSize\n\t\t\t\t&& this.indentStyle == that.indentStyle && this.alwaysEscapeNames == that.alwaysEscapeNames\n\t\t\t\t&& this.dialect == that.dialect && this.generatedNames.equals(that.generatedNames)\n\t\t\t\t&& this.enforceSchema == that.enforceSchema\n\t\t\t\t&& this.relationshipDefinitions.equals(that.relationshipDefinitions)\n\t\t\t\t&& this.disableDynamicLabels == that.disableDynamicLabels;\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn Objects.hash(this.prettyPrint, this.indentStyle, this.indentSize, this.alwaysEscapeNames, this.dialect,\n\t\t\t\tthis.generatedNames, this.enforceSchema, this.relationshipDefinitions, this.disableDynamicLabels);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"Configuration{\" + \"prettyPrint=\" + this.prettyPrint + \", indentStyle=\" + this.indentStyle\n\t\t\t\t+ \", indentSize=\" + this.indentSize + '}';\n\t}\n\n\t/**\n\t * Enum for the available indent styles.\n\t */\n\tpublic enum IndentStyle {\n\n\t\t/** Use tabs for indentation. */\n\t\tTAB,\n\t\t/** Use a configurable number of spaces for indentation. */\n\t\tSPACE\n\n\t}\n\n\t/**\n\t * Enum for configuring name rewriting.\n\t */\n\tpublic enum GeneratedNames {\n\n\t\t/**\n\t\t * Entity names are rewritten.\n\t\t */\n\t\tENTITY_NAMES,\n\t\t/**\n\t\t * Parameter names are rewritten.\n\t\t */\n\t\tPARAMETER_NAMES,\n\t\t/**\n\t\t * All aliases are rewritten.\n\t\t */\n\t\tALL_ALIASES,\n\t\t/**\n\t\t * All aliases except the ones used in the last {@literal RETURN} clause.\n\t\t */\n\t\tINTERNAL_ALIASES_ONLY,\n\t\t/**\n\t\t * This is an additional flag that is on by default for aliases, but can be\n\t\t * removed from the config, so that every alias name triggers a new generated\n\t\t * name. Otherwise, any overwriting of an alias will reuse the name that was\n\t\t * previously generated for that alias.\n\t\t */\n\t\tREUSE_ALIASES\n\n\t}\n\n\t/**\n\t * Simple definition of a known / schema relationship.\n\t *\n\t * @param sourceLabel the source label\n\t * @param type the type of the relationship\n\t * @param targetLabel the target label\n\t */\n\tpublic record RelationshipDefinition(String sourceLabel, String type, String targetLabel) {\n\n\t\t/**\n\t\t * Will make sure all parameters are trimmed.\n\t\t * @param sourceLabel the source label\n\t\t * @param type the type of the relationship\n\t\t * @param targetLabel the target label\n\t\t */\n\t\tpublic RelationshipDefinition {\n\t\t\tsourceLabel = sourceLabel.trim();\n\t\t\ttype = type.trim();\n\t\t\ttargetLabel = targetLabel.trim();\n\t\t}\n\n\t\tprivate static RelationshipDefinition of(String definition) {\n\t\t\tvar tuple = Objects.requireNonNull(definition).replace(\"(\", \"\").replace(\")\", \"\").split(\",\");\n\n\t\t\tif (tuple.length != 3) {\n\t\t\t\tthrow new IllegalArgumentException(\"Invalid relationship definition \" + definition);\n\t\t\t}\n\t\t\treturn new RelationshipDefinition(tuple[0], tuple[1], tuple[2]);\n\t\t}\n\n\t\tboolean selfReferential() {\n\t\t\treturn this.sourceLabel.equals(this.targetLabel);\n\t\t}\n\t}\n\n\t/**\n\t * Use this builder to create new {@link Configuration} instances.\n\t */\n\t@SuppressWarnings(\"HiddenField\")\n\tpublic static final class Builder {\n\n\t\tprivate boolean prettyPrint = false;\n\n\t\tprivate IndentStyle indentStyle = IndentStyle.SPACE;\n\n\t\tprivate int indentSize = 2;\n\n\t\tprivate boolean alwaysEscapeNames = true;\n\n\t\tprivate Dialect dialect = Dialect.NEO4J_5_DEFAULT_CYPHER;\n\n\t\tprivate Set<GeneratedNames> generatedNames = EnumSet.noneOf(GeneratedNames.class);\n\n\t\tprivate boolean enforceSchema = false;\n\n\t\tprivate boolean disableDynamicLabels = false;\n\n\t\tprivate Map<String, List<RelationshipDefinition>> relationshipDefinitions = new HashMap<>();\n\n\t\tprivate Builder() {\n\t\t}\n\n\t\tstatic Builder newConfig() {\n\t\t\treturn new Builder();\n\t\t}\n\n\t\t/**\n\t\t * Enables or disables pretty printing. Enabling pretty printing will disable\n\t\t * unnecessary escaping of labels and types.\n\t\t * @param prettyPrint use {@literal true} for enabling pretty printing\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withPrettyPrint(boolean prettyPrint) {\n\t\t\tthis.prettyPrint = prettyPrint;\n\t\t\tif (this.prettyPrint) {\n\t\t\t\treturn this.alwaysEscapeNames(false);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configures the indentation style.\n\t\t * @param indentStyle the new indentation style\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withIndentStyle(IndentStyle indentStyle) {\n\n\t\t\tif (indentStyle == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"Indent style is required.\");\n\t\t\t}\n\t\t\tthis.indentStyle = indentStyle;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configures the indentation size (width).\n\t\t * @param indentSize the new indentation size\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withIndentSize(int indentSize) {\n\t\t\tthis.indentSize = indentSize;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configure whether names should be always escaped.\n\t\t * @param alwaysEscapeNames use {@literal true} to always escape names\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder alwaysEscapeNames(boolean alwaysEscapeNames) {\n\t\t\tthis.alwaysEscapeNames = alwaysEscapeNames;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configure whether variable names should be always generated.\n\t\t * @param useGeneratedNames set to {@literal true} to use generated symbolic\n\t\t * names, parameter names and aliases\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withGeneratedNames(boolean useGeneratedNames) {\n\t\t\tif (useGeneratedNames) {\n\t\t\t\tthis.generatedNames = EnumSet.allOf(GeneratedNames.class);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.generatedNames = EnumSet.noneOf(GeneratedNames.class);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configure for which type of object generated names should be used.\n\t\t * @param useGeneratedNames the set of objects for which generated names should be\n\t\t * used\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withGeneratedNames(Set<GeneratedNames> useGeneratedNames) {\n\t\t\tthis.generatedNames = Objects.requireNonNullElseGet(useGeneratedNames,\n\t\t\t\t\t() -> EnumSet.noneOf(GeneratedNames.class));\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Use a configuration with a dialect fitting your target database if the default\n\t\t * dialect for {@link Dialect#NEO4J_4 Neo4j 4.x and earlier} leads to incompatible\n\t\t * results with your version of Neo4j.\n\t\t * @param dialect the new dialect\n\t\t * @return this builder. You can both use the original or this instance.\n\t\t * @since 2022.3.0\n\t\t */\n\t\tpublic Builder withDialect(Dialect dialect) {\n\t\t\tthis.dialect = dialect;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Adds a new relationship definition to the current schema.\n\t\t * @param relationshipDefinition a new relationship definition\n\t\t * @return this builder\n\t\t * @since 2023.7.0\n\t\t */\n\t\t@API(status = EXPERIMENTAL, since = \"2023.7.0\")\n\t\tpublic Builder withRelationshipDefinition(RelationshipDefinition relationshipDefinition) {\n\t\t\tif (relationshipDefinition == null) {\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tvar relationships = this.relationshipDefinitions.computeIfAbsent(relationshipDefinition.type,\n\t\t\t\t\tk -> new ArrayList<>());\n\t\t\trelationships.add(relationshipDefinition);\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configure whether to enforce a schema or not.\n\t\t * @param enforceSchema set to {@literal true} to enforce the schema defined by\n\t\t * known {@link #withRelationshipDefinition(RelationshipDefinition) relationship\n\t\t * definitions}.\n\t\t * @return this builder\n\t\t * @since 2023.7.0\n\t\t */\n\t\t@API(status = EXPERIMENTAL, since = \"2023.7.0\")\n\t\tpublic Builder withEnforceSchema(boolean enforceSchema) {\n\t\t\tthis.enforceSchema = enforceSchema;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Use this setting to disable dynamic labels.\n\t\t * @param disableDynamicLabels the new value\n\t\t * @return this builder\n\t\t * @since 2025.0.3\n\t\t */\n\t\tpublic Builder disableDynamicLabels(boolean disableDynamicLabels) {\n\t\t\tthis.disableDynamicLabels = disableDynamicLabels;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * {@return a new immutable configuration}\n\t\t */\n\t\tpublic Configuration build() {\n\t\t\treturn new Configuration(this);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/DefaultVisitor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.ArrayDeque;\nimport java.util.Deque;\nimport java.util.EnumSet;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.atomic.AtomicReference;\nimport java.util.function.Supplier;\nimport java.util.stream.Collectors;\n\nimport org.neo4j.cypherdsl.build.annotations.RegisterForReflection;\nimport org.neo4j.cypherdsl.core.AliasedExpression;\nimport org.neo4j.cypherdsl.core.Case;\nimport org.neo4j.cypherdsl.core.CollectExpression;\nimport org.neo4j.cypherdsl.core.Condition;\nimport org.neo4j.cypherdsl.core.CountExpression;\nimport org.neo4j.cypherdsl.core.Create;\nimport org.neo4j.cypherdsl.core.Delete;\nimport org.neo4j.cypherdsl.core.ExistentialSubquery;\nimport org.neo4j.cypherdsl.core.Foreach;\nimport org.neo4j.cypherdsl.core.FunctionInvocation;\nimport org.neo4j.cypherdsl.core.Hint;\nimport org.neo4j.cypherdsl.core.InTransactions;\nimport org.neo4j.cypherdsl.core.KeyValueMapEntry;\nimport org.neo4j.cypherdsl.core.Labels;\nimport org.neo4j.cypherdsl.core.Limit;\nimport org.neo4j.cypherdsl.core.ListComprehension;\nimport org.neo4j.cypherdsl.core.ListExpression;\nimport org.neo4j.cypherdsl.core.Literal;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Match;\nimport org.neo4j.cypherdsl.core.Merge;\nimport org.neo4j.cypherdsl.core.MergeAction;\nimport org.neo4j.cypherdsl.core.NestedExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Operation;\nimport org.neo4j.cypherdsl.core.Operator;\nimport org.neo4j.cypherdsl.core.Order;\nimport org.neo4j.cypherdsl.core.Parameter;\nimport org.neo4j.cypherdsl.core.PatternComprehension;\nimport org.neo4j.cypherdsl.core.PatternExpression;\nimport org.neo4j.cypherdsl.core.PatternSelector;\nimport org.neo4j.cypherdsl.core.ProcedureCall;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.PropertyLookup;\nimport org.neo4j.cypherdsl.core.QuantifiedPathPattern;\nimport org.neo4j.cypherdsl.core.Relationship;\nimport org.neo4j.cypherdsl.core.Remove;\nimport org.neo4j.cypherdsl.core.Return;\nimport org.neo4j.cypherdsl.core.Set;\nimport org.neo4j.cypherdsl.core.Skip;\nimport org.neo4j.cypherdsl.core.SortItem;\nimport org.neo4j.cypherdsl.core.StatementContext;\nimport org.neo4j.cypherdsl.core.Subquery;\nimport org.neo4j.cypherdsl.core.SubqueryExpression;\nimport org.neo4j.cypherdsl.core.SymbolicName;\nimport org.neo4j.cypherdsl.core.UnionPart;\nimport org.neo4j.cypherdsl.core.Unwind;\nimport org.neo4j.cypherdsl.core.Use;\nimport org.neo4j.cypherdsl.core.Where;\nimport org.neo4j.cypherdsl.core.With;\nimport org.neo4j.cypherdsl.core.ast.ProvidesAffixes;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.CaseElse;\nimport org.neo4j.cypherdsl.core.internal.CaseWhenThen;\nimport org.neo4j.cypherdsl.core.internal.ConstantParameterHolder;\nimport org.neo4j.cypherdsl.core.internal.Distinct;\nimport org.neo4j.cypherdsl.core.internal.LoadCSV;\nimport org.neo4j.cypherdsl.core.internal.NameResolvingStrategy;\nimport org.neo4j.cypherdsl.core.internal.Namespace;\nimport org.neo4j.cypherdsl.core.internal.ProcedureName;\nimport org.neo4j.cypherdsl.core.internal.ReflectiveVisitor;\nimport org.neo4j.cypherdsl.core.internal.RelationshipLength;\nimport org.neo4j.cypherdsl.core.internal.RelationshipPatternCondition;\nimport org.neo4j.cypherdsl.core.internal.RelationshipTypes;\nimport org.neo4j.cypherdsl.core.internal.SchemaNamesBridge;\nimport org.neo4j.cypherdsl.core.internal.ScopingStrategy;\nimport org.neo4j.cypherdsl.core.internal.UsingPeriodicCommit;\nimport org.neo4j.cypherdsl.core.internal.YieldItems;\n\n/**\n * This is a simple (some would call it naive) implementation of a visitor to the Cypher\n * AST created by the Cypher builder based on the {@link ReflectiveVisitor reflective\n * visitor}.\n * <p>\n * It takes care of separating elements of subtrees containing the element type with a\n * separator and provides pairs of {@code enter} / {@code leave} for the structuring\n * elements of the Cypher AST as needed.\n * <p>\n * This rendering visitor is not meant to be used outside framework code, and we don't\n * give any guarantees on the format being output apart from that it works within the\n * constraints of SDN-RX respectively SDN 6 and later.\n *\n * @author Michael J. Simons\n * @author Gerrit Meier\n * @since 1.0\n */\n@SuppressWarnings({ \"unused\", \"squid:S1172\" })\n@RegisterForReflection\nclass DefaultVisitor extends ReflectiveVisitor implements RenderingVisitor {\n\n\tprivate static final EnumSet<Operator> SKIP_SPACES = EnumSet.of(Operator.EXPONENTIATION, Operator.UNARY_MINUS,\n\t\t\tOperator.UNARY_PLUS);\n\n\t/**\n\t * Target of all rendering.\n\t */\n\tprotected final StringBuilder builder = new StringBuilder();\n\n\t/**\n\t * A set of aliased expressions that already have been seen and for which an alias\n\t * must be used on each following appearance.\n\t */\n\tprotected final java.util.Set<AliasedExpression> visitableToAliased = new HashSet<>();\n\n\t/**\n\t * This keeps track on which level of the tree a separator is needed.\n\t */\n\tprivate final Map<Integer, SeparatorAndSupplier> separatorOnLevel = new ConcurrentHashMap<>();\n\n\t/**\n\t * Keeps track of scoped, named variables.\n\t */\n\tprivate final ScopingStrategy scopingStrategy;\n\n\t/**\n\t * Keeps track if currently in an aliased expression so that the content can be\n\t * skipped when already visited.\n\t */\n\tprivate final Deque<AliasedExpression> currentAliasedElements = new ArrayDeque<>();\n\n\t/**\n\t * A cache of delegates, avoiding unnecessary object creation.\n\t */\n\tprivate final Map<Class<? extends Visitor>, Visitor> delegateCache = new ConcurrentHashMap<>();\n\n\tprivate final NameResolvingStrategy nameResolvingStrategy;\n\n\tprivate final boolean enforceSchema;\n\n\tprivate final Map<String, List<Configuration.RelationshipDefinition>> relationshipDefinitions;\n\n\tprivate final Deque<Boolean> inPatternExpression = new ArrayDeque<>();\n\n\t/**\n\t * Rendering parameters is not a config property due to some needs in Spring Data\n\t * Neo4j: This needs to be configured per statement, not per config there.\n\t */\n\tprivate final boolean renderConstantsAsParameters;\n\n\tprotected final boolean alwaysEscapeNames;\n\n\tprivate final Dialect dialect;\n\n\tprivate final boolean disableDynamicLabels;\n\n\tboolean inReturn;\n\n\tboolean inSubquery;\n\n\tprivate final Deque<Boolean> inLabelExpression = new ArrayDeque<>();\n\n\t/**\n\t * The current level in the tree of cypher elements.\n\t */\n\tprivate int currentLevel = 0;\n\n\t/**\n\t * Will be set to true when entering an already visited node.\n\t */\n\tprivate boolean skipNodeContent = false;\n\n\t/**\n\t * Will be set to true when entering an already visited relationship.\n\t */\n\tprivate boolean skipRelationshipContent = false;\n\n\t/**\n\t * Will be true when inside a {@link RelationshipPatternCondition}.\n\t */\n\tprivate boolean inRelationshipCondition = false;\n\n\tprivate boolean inEntity;\n\n\tprivate boolean inPropertyLookup;\n\n\tprivate Relationship.Direction directionOverride;\n\n\tDefaultVisitor(StatementContext statementContext) {\n\t\tthis(statementContext, false);\n\t}\n\n\tDefaultVisitor(StatementContext statementContext, boolean renderConstantsAsParameters) {\n\t\tthis(statementContext, renderConstantsAsParameters, Configuration.newConfig().alwaysEscapeNames(true).build());\n\t}\n\n\tDefaultVisitor(StatementContext statementContext, boolean renderConstantsAsParameters,\n\t\t\tConfiguration configuration) {\n\t\tthis.nameResolvingStrategy = configuration.isUseGeneratedNames()\n\t\t\t\t? NameResolvingStrategy.useGeneratedNames(statementContext, configuration.getGeneratedNames())\n\t\t\t\t: NameResolvingStrategy.useGivenNames(statementContext);\n\n\t\tthis.scopingStrategy = ScopingStrategy.create(List.of(this.nameResolvingStrategy::enterScope),\n\t\t\t\tList.of(this.nameResolvingStrategy::leaveScope));\n\n\t\tthis.renderConstantsAsParameters = renderConstantsAsParameters;\n\t\tthis.alwaysEscapeNames = configuration.isAlwaysEscapeNames();\n\t\tthis.dialect = configuration.getDialect();\n\t\tthis.enforceSchema = configuration.isEnforceSchema();\n\t\tthis.disableDynamicLabels = configuration.isDisableDynamicLabels();\n\t\tthis.relationshipDefinitions = configuration.getRelationshipDefinitions();\n\t}\n\n\tboolean hasIdentifiables() {\n\t\treturn !this.scopingStrategy.getIdentifiables().isEmpty();\n\t}\n\n\tprivate void enableSeparator(int level, boolean on, Supplier<String> supplier) {\n\t\tif (on) {\n\t\t\tthis.separatorOnLevel.put(level,\n\t\t\t\t\tnew SeparatorAndSupplier(new AtomicReference<>(\"\"), (supplier != null) ? supplier : () -> \"\"));\n\t\t}\n\t\telse {\n\t\t\tthis.separatorOnLevel.remove(level);\n\t\t}\n\t}\n\n\tprivate Optional<SeparatorAndSupplier> separatorOnCurrentLevel() {\n\n\t\treturn Optional.ofNullable(this.separatorOnLevel.get(this.currentLevel));\n\t}\n\n\t@Override\n\tprotected boolean preEnter(Visitable visitable) {\n\n\t\tVisitable lastAliased = this.currentAliasedElements.peek();\n\t\tif (this.skipNodeContent || this.visitableToAliased.contains(lastAliased)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (visitable instanceof AliasedExpression aliasedExpression) {\n\t\t\tthis.currentAliasedElements.push(aliasedExpression);\n\t\t}\n\n\t\tint nextLevel = ++this.currentLevel + 1;\n\t\tif (visitable instanceof TypedSubtree<?> ts) {\n\t\t\tenableSeparator(nextLevel, true, ts::separator);\n\t\t}\n\n\t\tseparatorOnCurrentLevel().ifPresent(ref -> this.builder.append(ref.seperator().getAndSet(\"\")));\n\n\t\tif (visitable instanceof ProvidesAffixes providesAffixes) {\n\t\t\tprovidesAffixes.getPrefix().ifPresent(this::doWithPrefix);\n\t\t}\n\n\t\tboolean doEnter = !this.skipNodeContent;\n\t\tif (doEnter) {\n\t\t\tthis.scopingStrategy.doEnter(visitable);\n\t\t}\n\t\treturn doEnter;\n\t}\n\n\t@Override\n\tprotected final PreEnterResult getPreEnterResult(Visitable visitable) {\n\t\tboolean doEnter = preEnter(visitable);\n\t\tif (!doEnter) {\n\t\t\treturn PreEnterResult.skip();\n\t\t}\n\n\t\tClass<? extends Visitor> handlerType;\n\t\tif (visitable instanceof Labels && this.disableDynamicLabels) {\n\t\t\thandlerType = Neo4j5Pre26LabelsVisitor.class;\n\t\t}\n\t\telse {\n\t\t\thandlerType = this.dialect.getHandler(visitable);\n\t\t}\n\t\tif (handlerType != null) {\n\t\t\tVisitor handler = this.delegateCache.computeIfAbsent(handlerType, this::newHandler);\n\t\t\treturn PreEnterResult.delegateTo(handler);\n\t\t}\n\t\treturn PreEnterResult.doEnter();\n\t}\n\n\tprivate Visitor newHandler(Class<? extends Visitor> handlerType) {\n\t\ttry {\n\t\t\tConstructor<? extends Visitor> ctor = handlerType.getDeclaredConstructor(DefaultVisitor.class);\n\t\t\treturn ctor.newInstance(this);\n\t\t}\n\t\tcatch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex) {\n\t\t\tthrow new IllegalArgumentException(this.dialect.name()\n\t\t\t\t\t+ \" has defined an illegal handler not providing a constructor accepting a delegate.\");\n\t\t}\n\t}\n\n\t@Override\n\tprotected void postLeave(Visitable visitable) {\n\n\t\tthis.scopingStrategy.doLeave(visitable);\n\n\t\tseparatorOnCurrentLevel().ifPresent(ref -> ref.seperator().set(ref.supplier().get()));\n\n\t\tif (visitable instanceof ProvidesAffixes providesAffixes) {\n\t\t\tprovidesAffixes.getSuffix().ifPresent(this::doWithSuffix);\n\t\t}\n\n\t\tif (visitable instanceof TypedSubtree) {\n\t\t\tenableSeparator(this.currentLevel + 1, false, null);\n\t\t}\n\n\t\tif (this.currentAliasedElements.peek() == visitable) {\n\t\t\tthis.currentAliasedElements.pop();\n\t\t}\n\n\t\tif (visitable instanceof AliasedExpression aliasedExpression) {\n\t\t\tthis.visitableToAliased.add(aliasedExpression);\n\t\t}\n\n\t\t--this.currentLevel;\n\t}\n\n\tprotected void doWithPrefix(String prefix) {\n\t\tthis.builder.append(prefix);\n\t}\n\n\tprotected void doWithSuffix(String suffix) {\n\t\tthis.builder.append(suffix);\n\t}\n\n\tvoid enter(Match match) {\n\t\tif (match.isOptional()) {\n\t\t\tthis.builder.append(\"OPTIONAL \");\n\t\t}\n\t\tthis.builder.append(\"MATCH \");\n\t}\n\n\tvoid leave(Match match) {\n\n\t\tthis.builder.append(\" \");\n\t}\n\n\tvoid enter(Where where) {\n\t\tthis.builder.append(\" WHERE \");\n\t}\n\n\tvoid enter(Create create) {\n\t\tthis.builder.append(\"CREATE \");\n\t}\n\n\tvoid leave(Create create) {\n\t\tthis.builder.append(\" \");\n\t}\n\n\tvoid enter(Merge merge) {\n\t\tthis.builder.append(\"MERGE \");\n\t}\n\n\tvoid leave(Merge merge) {\n\t\tif (!merge.hasEvents()) { // The last SET will include this\n\t\t\tthis.builder.append(\" \");\n\t\t}\n\t}\n\n\tvoid enter(MergeAction onCreateOrMatchEvent) {\n\t\tswitch (onCreateOrMatchEvent.getType()) {\n\t\t\tcase ON_CREATE -> this.builder.append(\"ON CREATE\");\n\t\t\tcase ON_MATCH -> this.builder.append(\"ON MATCH\");\n\t\t}\n\t\tthis.builder.append(\" \");\n\t}\n\n\tvoid enter(Condition condition) {\n\t\tthis.inRelationshipCondition = condition instanceof RelationshipPatternCondition;\n\t}\n\n\tvoid leave(Condition condition) {\n\t\tthis.inRelationshipCondition = false;\n\t}\n\n\tvoid enter(Distinct distinct) {\n\t\tthis.builder.append(\"DISTINCT \");\n\t}\n\n\tvoid enter(Return returning) {\n\n\t\tthis.inReturn = true;\n\t\taddBlankIfNecessary();\n\t\tif (!returning.isRaw()) {\n\t\t\tthis.builder.append(\"RETURN \");\n\t\t}\n\t}\n\n\tvoid leave(Return returning) {\n\t\tthis.inReturn = false;\n\t}\n\n\tvoid enter(With with) {\n\t\tthis.builder.append(\"WITH \");\n\t}\n\n\tvoid leave(With with) {\n\t\tthis.builder.append(\" \");\n\t}\n\n\tvoid enter(Delete delete) {\n\n\t\tif (delete.isDetach()) {\n\t\t\tthis.builder.append(\"DETACH \");\n\t\t}\n\n\t\tthis.builder.append(\"DELETE \");\n\t}\n\n\tvoid leave(Delete match) {\n\t\tthis.builder.append(\" \");\n\t}\n\n\tboolean inLastReturn() {\n\t\treturn this.inReturn && !this.inSubquery;\n\t}\n\n\tvoid enter(AliasedExpression aliased) {\n\n\t\tif (this.visitableToAliased.contains(aliased)) {\n\t\t\tthis.builder.append(escapeIfNecessary(this.nameResolvingStrategy.resolve(aliased, false, inLastReturn())));\n\t\t}\n\t}\n\n\tvoid leave(AliasedExpression aliased) {\n\n\t\tif (!(this.visitableToAliased.contains(aliased) || this.scopingStrategy.isSkipAliasing())) {\n\t\t\tthis.builder.append(\" AS \")\n\t\t\t\t.append(escapeIfNecessary(this.nameResolvingStrategy.resolve(aliased, true, inLastReturn())));\n\t\t}\n\t}\n\n\tvoid enter(NestedExpression nested) {\n\t\tthis.builder.append(\"(\");\n\t}\n\n\tvoid leave(NestedExpression nested) {\n\t\tthis.builder.append(\")\");\n\t}\n\n\tvoid enter(Order order) {\n\t\taddBlankIfNecessary();\n\t\tthis.builder.append(\"ORDER BY \");\n\t}\n\n\tprivate void addBlankIfNecessary() {\n\t\tvar lastString = this.builder.substring(Math.max(0, this.builder.length() - 1));\n\t\tif (!lastString.isBlank() && !lastString.equals(\"{\")) {\n\t\t\tthis.builder.append(\" \");\n\t\t}\n\t}\n\n\tvoid enter(Skip skip) {\n\t\tthis.builder.append(\" SKIP \");\n\t}\n\n\tvoid enter(Limit limit) {\n\t\tthis.builder.append(\" LIMIT \");\n\t}\n\n\tvoid enter(SortItem.Direction direction) {\n\t\tthis.builder.append(\" \").append(direction.getSymbol());\n\t}\n\n\tvoid enter(PropertyLookup propertyLookup) {\n\n\t\tthis.inPropertyLookup = true;\n\t\tif (propertyLookup.isDynamicLookup()) {\n\t\t\tthis.builder.append(\"[\");\n\t\t}\n\t\telse {\n\t\t\tthis.builder.append(\".\");\n\t\t}\n\t}\n\n\tvoid leave(PropertyLookup propertyLookup) {\n\n\t\tthis.inPropertyLookup = false;\n\t\tif (propertyLookup.isDynamicLookup()) {\n\t\t\tthis.builder.append(\"]\");\n\t\t}\n\t}\n\n\tvoid enter(FunctionInvocation functionInvocation) {\n\t\tString functionName = functionInvocation.getFunctionName();\n\t\tif (\"elementId\".equals(functionName)) {\n\t\t\tfunctionName = \"toString(id\";\n\t\t}\n\t\tthis.builder.append(functionName).append(\"(\");\n\t}\n\n\tvoid leave(FunctionInvocation functionInvocation) {\n\t\tString functionName = functionInvocation.getFunctionName();\n\t\tif (\"elementId\".equals(functionName)) {\n\t\t\tthis.builder.append(\")\");\n\t\t}\n\t\tthis.builder.append(\")\");\n\t}\n\n\tvoid enter(Operation operation) {\n\n\t\tif (operation.needsGrouping()) {\n\t\t\tthis.builder.append(\"(\");\n\t\t}\n\t}\n\n\tvoid enter(Operator operator) {\n\n\t\tOperator.Type type = operator.getType();\n\t\tif (type == Operator.Type.LABEL) {\n\t\t\treturn;\n\t\t}\n\n\t\tboolean skipSpaces = SKIP_SPACES.contains(operator);\n\t\tif (type != Operator.Type.PREFIX && !skipSpaces) {\n\t\t\tthis.builder.append(\" \");\n\t\t}\n\t\tthis.builder.append(operator.getRepresentation());\n\t\tif (type != Operator.Type.POSTFIX && !skipSpaces) {\n\t\t\tthis.builder.append(\" \");\n\t\t}\n\t}\n\n\tvoid leave(Operation operation) {\n\n\t\tif (operation.needsGrouping()) {\n\t\t\tthis.builder.append(\")\");\n\t\t}\n\t}\n\n\tvoid enter(Literal<?> expression) {\n\t\tthis.builder.append(expression.asString());\n\t}\n\n\tvoid enter(Node node) {\n\n\t\tthis.builder.append(\"(\");\n\n\t\t// This is only relevant for nodes in relationships.\n\t\t// Otherwise, all the labels would be rendered again.\n\t\tthis.skipNodeContent = this.scopingStrategy.hasVisitedBefore(node);\n\n\t\tif (this.skipNodeContent) {\n\t\t\tthis.builder.append(this.nameResolvingStrategy\n\t\t\t\t.resolve(node.getSymbolicName().orElseGet(node::getRequiredSymbolicName), true, false));\n\t\t}\n\n\t\tthis.inEntity = true;\n\t}\n\n\tvoid leave(Node node) {\n\n\t\tthis.builder.append(\")\");\n\n\t\tthis.skipNodeContent = false;\n\t\tthis.inEntity = false;\n\t}\n\n\tvoid enter(NodeLabel nodeLabel) {\n\n\t\tescapeName(nodeLabel.getValue()).ifPresent(label -> {\n\t\t\tvar inLabelExpression = this.inLabelExpression.peek();\n\t\t\tif (inLabelExpression == null || !inLabelExpression) {\n\t\t\t\tthis.builder.append(Symbols.NODE_LABEL_START);\n\t\t\t}\n\t\t\tthis.builder.append(label);\n\t\t});\n\t}\n\n\tvoid enter(Labels labels) {\n\t\tthis.inLabelExpression.push(true);\n\t\tif (!labels.isEmpty()) {\n\t\t\tthis.builder.append(\":\");\n\t\t}\n\t\trenderLabelExpression(labels, null);\n\t}\n\n\t@SuppressWarnings(\"squid:S3776\")\n\tvoid renderLabelExpression(Labels l, Labels.Type parent) {\n\t\tif (l == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (l.isNegated()) {\n\t\t\tthis.builder.append(\"!\");\n\t\t}\n\t\tvar current = l.getType();\n\t\tboolean close = false;\n\t\tif (current != Labels.Type.LEAF) {\n\t\t\tclose = (parent != null || l.isNegated()) && l.getType() != parent;\n\t\t\tif (close && !l.isNegated() && (current == Labels.Type.CONJUNCTION || parent == Labels.Type.DISJUNCTION)) {\n\t\t\t\tclose = false;\n\t\t\t}\n\t\t}\n\t\tif (close) {\n\t\t\tthis.builder.append(\"(\");\n\t\t}\n\t\trenderLabelExpression(l.getLhs(), current);\n\t\tif (current == Labels.Type.LEAF) {\n\t\t\tl.getValue().forEach(v -> v.accept(this));\n\t\t}\n\t\telse if (EnumSet.of(Labels.Type.COLON_CONJUNCTION, Labels.Type.COLON_DISJUNCTION).contains(current)\n\t\t\t\t&& !l.getValue().isEmpty()) {\n\t\t\tl.getValue().get(0).accept(this);\n\t\t\tfor (var value : l.getValue().subList(1, l.getValue().size())) {\n\t\t\t\tthis.builder.append(current.getValue());\n\t\t\t\tvalue.accept(this);\n\t\t\t}\n\t\t}\n\t\telse if (!l.isEmpty()) {\n\t\t\tthis.builder.append(current.getValue());\n\t\t}\n\t\trenderLabelExpression(l.getRhs(), current);\n\t\tif (close) {\n\t\t\tthis.builder.append(\")\");\n\t\t}\n\t}\n\n\tvoid enter(Labels.Value value) {\n\n\t\tvar modifier = switch (value.modifier()) {\n\t\t\tcase ALL -> \"$(\";\n\t\t\tcase ANY -> \"$any(\";\n\t\t\tcase STATIC -> \"\";\n\t\t};\n\n\t\tthis.builder.append(modifier);\n\t}\n\n\tvoid leave(Labels.Value value) {\n\n\t\tif (value.modifier() != Labels.Modifier.STATIC) {\n\t\t\tthis.builder.append(\")\");\n\t\t}\n\t}\n\n\tvoid leave(Labels labels) {\n\t\tthis.inLabelExpression.pop();\n\t}\n\n\tvoid enter(Properties properties) {\n\n\t\tthis.builder.append(\" \");\n\t}\n\n\tvoid enter(SymbolicName symbolicName) {\n\t\tif (!this.inRelationshipCondition || this.nameResolvingStrategy.isResolved(symbolicName)) {\n\t\t\tif (Boolean.TRUE.equals(this.inPatternExpression.peek())\n\t\t\t\t\t&& !this.scopingStrategy.hasVisitedBefore(() -> Optional.of(symbolicName))) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.builder.append(this.nameResolvingStrategy.resolve(symbolicName, this.inEntity, this.inPropertyLookup));\n\t\t}\n\t}\n\n\tvoid enter(PatternExpression p) {\n\t\tthis.inPatternExpression.push(true);\n\t}\n\n\tvoid leave(PatternExpression p) {\n\t\tthis.inPatternExpression.pop();\n\t}\n\n\tvoid enter(Relationship relationship) {\n\t\tthis.skipRelationshipContent = this.scopingStrategy.hasVisitedBefore(relationship);\n\t\tif (this.enforceSchema && relationship.getDetails().getDirection() != Relationship.Direction.UNI) {\n\t\t\tthis.directionOverride = computeDirectionOverride(relationship);\n\t\t}\n\t}\n\n\t/**\n\t * Helper to retrieve a nodes label.\n\t * @param node the node\n\t * @return a set of labels\n\t */\n\tprivate java.util.Set<String> getLabels(Node node) {\n\t\tvar nl = node.getLabels();\n\t\tif (nl.isEmpty()) {\n\t\t\tvar patternElement = this.scopingStrategy.lookup(node);\n\t\t\tif (patternElement instanceof Node boundNode) {\n\t\t\t\tnl = boundNode.getLabels();\n\t\t\t}\n\t\t}\n\t\treturn nl.stream().map(NodeLabel::getValue).collect(Collectors.toSet());\n\t}\n\n\t/**\n\t * Computes an overwrite for enforcing a schema.\n\t * @param relationship the relationship to potentially override\n\t * @return a new direction\n\t */\n\tRelationship.Direction computeDirectionOverride(Relationship relationship) {\n\t\tvar sourceLabels = getLabels(relationship.getLeft());\n\t\tvar targetLabels = getLabels(relationship.getRight());\n\t\tvar details = relationship.getDetails();\n\n\t\t// Bail out on equal labels\n\t\tif (sourceLabels.equals(targetLabels)) {\n\t\t\treturn details.getDirection();\n\t\t}\n\n\t\tfor (String type : details.getTypes()) {\n\t\t\touter: if (this.relationshipDefinitions.containsKey(type)) {\n\t\t\t\tvar knownRelationships = this.relationshipDefinitions.get(type).stream().toList();\n\t\t\t\tfor (var knownRelationship : knownRelationships) {\n\t\t\t\t\tif (knownRelationship.selfReferential() && (sourceLabels.isEmpty() || targetLabels.isEmpty())) {\n\t\t\t\t\t\tbreak outer;\n\t\t\t\t\t}\n\t\t\t\t\tif (sourceLabels.contains(knownRelationship.targetLabel())\n\t\t\t\t\t\t\t&& (targetLabels.isEmpty() || targetLabels.contains(knownRelationship.sourceLabel()))\n\t\t\t\t\t\t\t|| targetLabels.contains(knownRelationship.sourceLabel()) && (sourceLabels.isEmpty()\n\t\t\t\t\t\t\t\t\t|| sourceLabels.contains(knownRelationship.sourceLabel()))) {\n\t\t\t\t\t\treturn Relationship.Direction.RTL;\n\t\t\t\t\t}\n\t\t\t\t\telse if (sourceLabels.contains(knownRelationship.sourceLabel())\n\t\t\t\t\t\t\t&& (targetLabels.isEmpty() || targetLabels.contains(knownRelationship.targetLabel()))\n\t\t\t\t\t\t\t|| targetLabels.contains(knownRelationship.targetLabel()) && (sourceLabels.isEmpty()\n\t\t\t\t\t\t\t\t\t|| sourceLabels.contains(knownRelationship.sourceLabel()))) {\n\t\t\t\t\t\treturn Relationship.Direction.LTR;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!sourceLabels.isEmpty() && !targetLabels.isEmpty()) {\n\t\t\t\tthrow new SchemaEnforcementFailedException();\n\t\t\t}\n\t\t}\n\t\tif (details.getTypes().isEmpty()) {\n\t\t\tvar knownRelationships = this.relationshipDefinitions.values().stream().flatMap(List::stream).toList();\n\t\t\tfor (var knownRelationship : knownRelationships) {\n\t\t\t\tif (sourceLabels.contains(knownRelationship.targetLabel())\n\t\t\t\t\t\t&& targetLabels.contains(knownRelationship.sourceLabel())) {\n\t\t\t\t\treturn Relationship.Direction.RTL;\n\t\t\t\t}\n\t\t\t\telse if (sourceLabels.contains(knownRelationship.sourceLabel())\n\t\t\t\t\t\t&& targetLabels.contains(knownRelationship.targetLabel())) {\n\t\t\t\t\treturn Relationship.Direction.LTR;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn details.getDirection();\n\t}\n\n\tvoid enter(Relationship.Details details) {\n\n\t\tRelationship.Direction direction = Optional.ofNullable(this.directionOverride).orElseGet(details::getDirection);\n\t\tthis.builder.append(direction.getSymbolLeft());\n\t\tif (details.hasContent()) {\n\t\t\tthis.builder.append(\"[\");\n\t\t}\n\n\t\tthis.inEntity = true;\n\t}\n\n\tvoid enter(RelationshipTypes types) {\n\n\t\tif (this.skipRelationshipContent) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.builder.append(types.getValues()\n\t\t\t.stream()\n\t\t\t.map(this::escapeName)\n\t\t\t.map(Optional::orElseThrow)\n\t\t\t.collect(Collectors.joining(Symbols.REL_TYP_SEPARATOR, Symbols.REL_TYPE_START, \"\")));\n\t}\n\n\tvoid enter(RelationshipLength length) {\n\n\t\tif (this.skipRelationshipContent) {\n\t\t\treturn;\n\t\t}\n\n\t\tInteger minimum = length.getMinimum();\n\t\tInteger maximum = length.getMaximum();\n\n\t\tif (length.isUnbounded()) {\n\t\t\tthis.builder.append(\"*\");\n\t\t\treturn;\n\t\t}\n\n\t\tif (minimum == null && maximum == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.builder.append(\"*\");\n\t\tif (minimum != null) {\n\t\t\tthis.builder.append(minimum);\n\t\t}\n\t\tthis.builder.append(\"..\");\n\t\tif (maximum != null) {\n\t\t\tthis.builder.append(maximum);\n\t\t}\n\t}\n\n\tvoid leave(Relationship.Details details) {\n\n\t\tRelationship.Direction direction = Optional.ofNullable(this.directionOverride).orElseGet(details::getDirection);\n\t\tif (details.hasContent()) {\n\t\t\tthis.builder.append(\"]\");\n\t\t}\n\t\tthis.builder.append(direction.getSymbolRight());\n\n\t\tthis.inEntity = false;\n\t}\n\n\tvoid leave(Relationship relationship) {\n\n\t\tthis.skipRelationshipContent = false;\n\t\tthis.directionOverride = null;\n\t}\n\n\tvoid enter(Parameter<?> parameter) {\n\n\t\tObject value = parameter.getValue();\n\t\tif (value instanceof ConstantParameterHolder constantParameterHolder && !this.renderConstantsAsParameters) {\n\t\t\tthis.builder.append(constantParameterHolder.asString());\n\t\t}\n\t\telse {\n\t\t\tthis.builder.append(\"$\").append(this.nameResolvingStrategy.resolve(parameter));\n\t\t}\n\t}\n\n\tvoid enter(MapExpression map) {\n\n\t\tthis.builder.append(\"{\");\n\t}\n\n\tvoid enter(KeyValueMapEntry map) {\n\n\t\tthis.builder.append(escapeIfNecessary(map.getKey())).append(\": \");\n\t}\n\n\tvoid leave(MapExpression map) {\n\n\t\tthis.builder.append(\"}\");\n\t}\n\n\tvoid enter(ListExpression list) {\n\n\t\tthis.builder.append(\"[\");\n\t}\n\n\tvoid leave(ListExpression list) {\n\n\t\tthis.builder.append(\"]\");\n\t}\n\n\tvoid enter(Unwind unwind) {\n\n\t\tthis.builder.append(\"UNWIND \");\n\t}\n\n\tvoid leave(Unwind unwind) {\n\n\t\tthis.builder.append(\" \");\n\t}\n\n\tvoid enter(UnionPart unionPart) {\n\n\t\tthis.builder.append(\" UNION \");\n\t\tif (unionPart.isAll()) {\n\t\t\tthis.builder.append(\"ALL \");\n\t\t}\n\t}\n\n\tvoid enter(Set set) {\n\n\t\tthis.builder.append(\"SET \");\n\t}\n\n\tvoid leave(Set set) {\n\t\tthis.builder.append(\" \");\n\t}\n\n\tvoid enter(Remove remove) {\n\n\t\tthis.builder.append(\"REMOVE \");\n\t}\n\n\tvoid leave(Remove remove) {\n\t\tthis.builder.append(\" \");\n\t}\n\n\tvoid enter(PatternComprehension patternComprehension) {\n\t\tthis.builder.append(\"[\");\n\t}\n\n\tvoid leave(PatternComprehension patternComprehension) {\n\t\tthis.builder.append(\"]\");\n\t}\n\n\tvoid enter(ListComprehension listComprehension) {\n\t\tthis.builder.append(\"[\");\n\t}\n\n\tvoid leave(ListComprehension listComprehension) {\n\t\tthis.builder.append(\"]\");\n\t}\n\n\tvoid enter(Case genericCase) {\n\t\tthis.builder.append(\"CASE\");\n\t}\n\n\tvoid enter(Case.SimpleCase simpleCase) {\n\t\tthis.builder.append(\"CASE \");\n\t}\n\n\tvoid enter(CaseWhenThen caseWhenExpression) {\n\t\tthis.builder.append(\" WHEN \");\n\t}\n\n\tvoid leave(CaseWhenThen caseWhenExpression) {\n\t\tthis.builder.append(\" THEN \");\n\t}\n\n\tvoid enter(CaseElse caseElseExpression) {\n\t\tthis.builder.append(\" ELSE \");\n\t}\n\n\tvoid leave(Case caseExpression) {\n\t\tthis.builder.append(\" END\");\n\t}\n\n\tvoid enter(ProcedureCall procedureCall) {\n\n\t\tthis.builder.append(\"CALL \");\n\t}\n\n\tvoid leave(Namespace namespace) {\n\n\t\tthis.builder.append(\".\");\n\t}\n\n\tvoid leave(ProcedureName procedureName) {\n\n\t\tthis.builder.append(procedureName.getValue());\n\t}\n\n\tvoid enter(YieldItems yieldItems) {\n\n\t\tthis.builder.append(\" YIELD \");\n\t}\n\n\tvoid leave(ProcedureCall procedureCall) {\n\n\t\tthis.builder.append(\" \");\n\t}\n\n\tvoid enter(Enum<?> anEnum) {\n\n\t\tthis.builder.append(anEnum.name().replace(\"_\", \" \")).append(\" \");\n\t}\n\n\tvoid enter(Subquery subquery) {\n\n\t\tthis.inSubquery = true;\n\t\tthis.builder.append(\"CALL {\");\n\t}\n\n\tvoid leave(Subquery subquery) {\n\n\t\tthis.inSubquery = false;\n\t\tint l = this.builder.length() - 1;\n\t\tif (this.builder.charAt(l) == ' ' && !subquery.doesReturnOrYield()) {\n\t\t\tthis.builder.replace(l, this.builder.length(), \"} \");\n\t\t}\n\t\telse {\n\t\t\tthis.builder.append(\"} \");\n\t\t}\n\t}\n\n\tvoid leave(InTransactions inTransactions) {\n\n\t\tint l = this.builder.length() - 1;\n\t\tif (this.builder.charAt(l) != ' ') {\n\t\t\tthis.builder.append(\" \");\n\t\t}\n\t\tthis.builder.append(\"IN TRANSACTIONS \");\n\t\tif (inTransactions.getRows() != null) {\n\t\t\tthis.builder.append(\"OF \").append(inTransactions.getRows()).append(\" ROWS \");\n\t\t}\n\t}\n\n\tvoid enter(Foreach foreach) {\n\n\t\tthis.builder.append(\"FOREACH (\");\n\t}\n\n\tvoid leave(Foreach foreach) {\n\n\t\tthis.builder.setCharAt(this.builder.length() - 1, ')'); // replace trailing space\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// with ')'\n\t\tthis.builder.append(\" \");\n\t}\n\n\tvoid enter(SubqueryExpression subquery) {\n\n\t\tif (subquery instanceof CountExpression) {\n\t\t\tthis.builder.append(\"COUNT\");\n\t\t}\n\t\telse if (subquery instanceof ExistentialSubquery) {\n\t\t\tthis.builder.append(\"EXISTS\");\n\t\t}\n\t\telse if (subquery instanceof CollectExpression) {\n\t\t\tthis.builder.append(\"COLLECT\");\n\t\t}\n\t\tthis.builder.append(\" { \");\n\t}\n\n\tvoid leave(SubqueryExpression subquery) {\n\n\t\t// Trimming the inner match without having to do this in the match (looking up if\n\t\t// inside subquery).\n\t\tif (this.builder.charAt(this.builder.length() - 1) == ' ') {\n\t\t\tthis.builder.replace(this.builder.length() - 1, this.builder.length(), \" }\");\n\t\t}\n\t\telse {\n\t\t\tthis.builder.append(\" }\");\n\t\t}\n\t}\n\n\tvoid enter(Hint hint) {\n\n\t\tthis.builder.append(\" USING \");\n\t}\n\n\tvoid enter(LoadCSV loadCSV) {\n\n\t\tthis.builder.append(\"LOAD CSV\");\n\t\tif (loadCSV.isWithHeaders()) {\n\t\t\tthis.builder.append(\" WITH HEADERS\");\n\t\t}\n\t\tthis.builder.append(\" FROM '\").append(loadCSV.getUri().toString()).append(\"' AS \").append(loadCSV.getAlias());\n\n\t\tif (loadCSV.getFieldTerminator() != null) {\n\t\t\tthis.builder.append(\" FIELDTERMINATOR '\").append(loadCSV.getFieldTerminator()).append(\"'\");\n\t\t}\n\t\tthis.builder.append(\" \");\n\t}\n\n\tvoid enter(UsingPeriodicCommit usingPeriodicCommit) {\n\n\t\tthis.builder.append(\"USING PERIODIC COMMIT \");\n\t\tif (usingPeriodicCommit.rate() != null) {\n\t\t\tthis.builder.append(usingPeriodicCommit.rate()).append(\" \");\n\t\t}\n\t}\n\n\tvoid enter(Use use) {\n\t\tthis.builder.append(\"USE \");\n\t\tif (use.dynamic()) {\n\t\t\tthis.builder.append(\"graph.byName(\");\n\t\t}\n\t}\n\n\tvoid leave(Use use) {\n\t\tif (use.dynamic()) {\n\t\t\tthis.builder.append(\")\");\n\t\t}\n\t\tthis.builder.append(\" \");\n\t}\n\n\tvoid enter(PatternSelector shortest) {\n\n\t\tif (shortest instanceof PatternSelector.ShortestK shortestK) {\n\t\t\tthis.builder.append(\"SHORTEST \").append(shortestK.getK()).append(\" \");\n\t\t}\n\t\telse if (shortest instanceof PatternSelector.ShortestKGroups shortestK) {\n\t\t\tthis.builder.append(\"SHORTEST \").append(shortestK.getK()).append(\" GROUPS \");\n\t\t}\n\t\telse if (shortest instanceof PatternSelector.AllShortest) {\n\t\t\tthis.builder.append(\"ALL SHORTEST \");\n\t\t}\n\t\telse if (shortest instanceof PatternSelector.Any) {\n\t\t\tthis.builder.append(\"ANY \");\n\t\t}\n\t}\n\n\tvoid enter(QuantifiedPathPattern.TargetPattern qpp) {\n\t\tthis.builder.append(\"(\");\n\t}\n\n\tvoid leave(QuantifiedPathPattern.TargetPattern qpp) {\n\t\tthis.builder.append(\")\");\n\t}\n\n\tvoid enter(QuantifiedPathPattern.Quantifier quantifier) {\n\n\t\tthis.builder.append(quantifier.toString());\n\t}\n\n\t@Override\n\tpublic String getRenderedContent() {\n\t\treturn this.builder.toString();\n\t}\n\n\t/**\n\t * Escapes a symbolic name. Such a symbolic name is either used for a nodes label, the\n\t * type of a relationship or a variable.\n\t * @param unescapedName the name to escape.\n\t * @return an empty optional when the unescaped name is {@literal null}, otherwise the\n\t * correctly escaped name, safe to be used in statements.\n\t */\n\tprotected final Optional<String> escapeName(String unescapedName) {\n\n\t\treturn SchemaNamesBridge.sanitize(unescapedName, this.alwaysEscapeNames);\n\t}\n\n\tprotected final String escapeIfNecessary(String potentiallyNonIdentifier) {\n\n\t\treturn SchemaNamesBridge.sanitize(potentiallyNonIdentifier, false).orElse(null);\n\t}\n\n\trecord SeparatorAndSupplier(AtomicReference<String> seperator, Supplier<String> supplier) {\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/Dialect.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport java.util.Optional;\nimport java.util.function.Function;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Comparison;\nimport org.neo4j.cypherdsl.core.FunctionInvocation;\nimport org.neo4j.cypherdsl.core.Labels;\nimport org.neo4j.cypherdsl.core.PatternSelector;\nimport org.neo4j.cypherdsl.core.Subquery;\nimport org.neo4j.cypherdsl.core.With;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * The dialect to be used when rendering a statement into Cypher.\n *\n * @author Michael J. Simons\n * @since 2022.3.0\n */\n@API(status = STABLE, since = \"2022.3.0\")\npublic enum Dialect {\n\n\t/**\n\t * Neo4j 4.4 and earlier.\n\t */\n\tNEO4J_4 {\n\t\tprivate final DefaultNeo4j4HandlerSupplier handlerSupplier = new DefaultNeo4j4HandlerSupplier();\n\n\t\t@Override\n\t\tClass<? extends Visitor> getHandler(Visitable visitable) {\n\t\t\treturn this.handlerSupplier.apply(visitable).orElseGet(() -> super.getHandler(visitable));\n\t\t}\n\t},\n\n\t/**\n\t * Neo4j 5.\n\t */\n\tNEO4J_5 {\n\n\t\tprivate final DefaultNeo4j5HandlerSupplier handlerSupplier = new DefaultNeo4j5HandlerSupplier();\n\n\t\t@Override\n\t\tClass<? extends Visitor> getHandler(Visitable visitable) {\n\t\t\treturn this.handlerSupplier.apply(visitable).orElseGet(() -> super.getHandler(visitable));\n\t\t}\n\t},\n\n\t/**\n\t * Enhanced Neo4j 5 dialect that renders importing with statements for call subqueries\n\t * as variable scoped subqueries, suitable for Neo4j >= 5.23.\n\t *\n\t * @since 2024.1.0\n\t */\n\tNEO4J_5_23 {\n\t\tprivate final DefaultNeo4j5HandlerSupplier handlerSupplier = new DefaultNeo4j5HandlerSupplierWithNewImportScopeSubquerySupport();\n\n\t\t@Override\n\t\tClass<? extends Visitor> getHandler(Visitable visitable) {\n\t\t\treturn this.handlerSupplier.apply(visitable).orElseGet(() -> super.getHandler(visitable));\n\t\t}\n\t},\n\n\t/**\n\t * A Neo4j 5.26 and higher dialect that always renders the {@code CYPHER 5} prefix.\n\t * @since 2024.5.0\n\t * @deprecated Use {@link #NEO4J_5_CYPHER_5} if necessary or\n\t * {@link #NEO4J_5_DEFAULT_CYPHER} in all other cases.\n\t */\n\t@Deprecated(forRemoval = true)\n\tNEO4J_5_26 {\n\n\t\tprivate final DefaultNeo4j5HandlerSupplier handlerSupplier = new DefaultNeo4j5HandlerSupplierWithDynamicLabelsSupport();\n\n\t\t@Override\n\t\tClass<? extends Visitor> getHandler(Visitable visitable) {\n\t\t\treturn this.handlerSupplier.apply(visitable).orElseGet(() -> super.getHandler(visitable));\n\t\t}\n\n\t\t@Override\n\t\tOptional<String> getPrefix() {\n\t\t\treturn Optional.of(\"CYPHER 5 \");\n\t\t}\n\t},\n\n\t/**\n\t * Essentially the same as {@link #NEO4J_5_23} using the databases default Cypher\n\t * version. This is the default dialect for Cypher-DSL 2025.0.0 and onwards.\n\t *\n\t * @since 2025.0.0\n\t */\n\tNEO4J_5_DEFAULT_CYPHER {\n\t\t@Override\n\t\tClass<? extends Visitor> getHandler(Visitable visitable) {\n\t\t\treturn NEO4J_5_26.getHandler(visitable);\n\t\t}\n\t},\n\n\t/**\n\t * Essentially the same as {@link #NEO4J_5_23} but also enabling the {@code CYPHER 5}\n\t * prefix on generated statements. This dialect works on Neo4j 5.26 and higher.\n\t * Genrally, {@link #NEO4J_5_DEFAULT_CYPHER} is preferrable.\n\t *\n\t * @since 2025.0.0\n\t */\n\tNEO4J_5_CYPHER_5 {\n\t\t@Override\n\t\tClass<? extends Visitor> getHandler(Visitable visitable) {\n\t\t\treturn NEO4J_5_26.getHandler(visitable);\n\t\t}\n\n\t\t@Override\n\t\tOptional<String> getPrefix() {\n\t\t\treturn Optional.of(\"CYPHER 5 \");\n\t\t}\n\t},\n\n\t/**\n\t * Essentially the same as {@link #NEO4J_5_23} but also enabling the {@code CYPHER 25}\n\t * prefix on generated statements. This dialect works on Neo4j 5.26 and higher.\n\t * Genrally, {@link #NEO4J_5_23} is preferable.\n\t *\n\t * @since 2025.0.0\n\t */\n\tNEO4J_5_CYPHER_25 {\n\t\t@Override\n\t\tClass<? extends Visitor> getHandler(Visitable visitable) {\n\t\t\treturn NEO4J_5_26.getHandler(visitable);\n\t\t}\n\n\t\t@Override\n\t\tOptional<String> getPrefix() {\n\t\t\treturn Optional.of(\"CYPHER 25 \");\n\t\t}\n\t},\n\n\t/**\n\t * A placeholder for Neo4j 2025 calver. Same behaviour as\n\t * {@link #NEO4J_5_DEFAULT_CYPHER} in this version of Cypher-DSL.\n\t *\n\t * @since 2025.0.0\n\t */\n\tNEO4J_2025 {\n\t\t@Override\n\t\tClass<? extends Visitor> getHandler(Visitable visitable) {\n\t\t\treturn NEO4J_5_23.getHandler(visitable);\n\t\t}\n\t};\n\n\tClass<? extends Visitor> getHandler(Visitable visitable) {\n\t\treturn null;\n\t}\n\n\tOptional<String> getPrefix() {\n\t\treturn Optional.empty();\n\t}\n\n\tprivate static final class DefaultNeo4j4HandlerSupplier\n\t\t\timplements Function<Visitable, Optional<Class<? extends Visitor>>> {\n\n\t\t@Override\n\t\tpublic Optional<Class<? extends Visitor>> apply(Visitable visitable) {\n\t\t\tif (visitable instanceof PatternSelector) {\n\t\t\t\treturn Optional.of(PatternSelectorVisitorPreNeo4j521.class);\n\t\t\t}\n\t\t\telse if (visitable instanceof Labels) {\n\t\t\t\treturn Optional.of(Neo4j5Pre26LabelsVisitor.class);\n\t\t\t}\n\t\t\treturn Optional.empty();\n\t\t}\n\n\t}\n\n\tprivate static class DefaultNeo4j5HandlerSupplier\n\t\t\timplements Function<Visitable, Optional<Class<? extends Visitor>>> {\n\n\t\t@Override\n\t\tpublic Optional<Class<? extends Visitor>> apply(Visitable visitable) {\n\t\t\tif (visitable instanceof FunctionInvocation) {\n\t\t\t\treturn Optional.of(Neo4j5FunctionInvocationVisitor.class);\n\t\t\t}\n\t\t\telse if (visitable instanceof Comparison) {\n\t\t\t\treturn Optional.of(Neo4j5ComparisonVisitor.class);\n\t\t\t}\n\t\t\telse if (visitable instanceof PatternSelector) {\n\t\t\t\treturn Optional.of(PatternSelectorVisitorPreNeo4j521.class);\n\t\t\t}\n\t\t\telse if (visitable instanceof Labels) {\n\t\t\t\treturn Optional.of(Neo4j5Pre26LabelsVisitor.class);\n\t\t\t}\n\t\t\treturn Optional.empty();\n\t\t}\n\n\t}\n\n\tprivate static class DefaultNeo4j5HandlerSupplierWithNewImportScopeSubquerySupport\n\t\t\textends DefaultNeo4j5HandlerSupplier {\n\n\t\t@Override\n\t\tpublic Optional<Class<? extends Visitor>> apply(Visitable visitable) {\n\t\t\tif (visitable instanceof PatternSelector) {\n\t\t\t\treturn Optional.empty();\n\t\t\t}\n\t\t\treturn super.apply(visitable).or(() -> {\n\t\t\t\tif (visitable instanceof Subquery || visitable instanceof With) {\n\t\t\t\t\treturn Optional.of(Neo4j523SubqueryVisitor.class);\n\t\t\t\t}\n\t\t\t\treturn Optional.empty();\n\t\t\t});\n\t\t}\n\n\t}\n\n\tprivate static final class DefaultNeo4j5HandlerSupplierWithDynamicLabelsSupport\n\t\t\textends DefaultNeo4j5HandlerSupplierWithNewImportScopeSubquerySupport {\n\n\t\t@Override\n\t\tpublic Optional<Class<? extends Visitor>> apply(Visitable visitable) {\n\t\t\tif (visitable instanceof Labels) {\n\t\t\t\treturn Optional.empty();\n\t\t\t}\n\t\t\treturn super.apply(visitable);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/GeneralizedRenderer.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * This is a more general renderer than {@link Renderer}. The generalized renderer will\n * render any {@link Visitable}. This renderer will not cache rendered results for\n * visitables.\n *\n * @author Michael J. Simons\n * @since 2023.1.0\n */\n@API(status = STABLE, since = \"2023.1.0\")\npublic sealed interface GeneralizedRenderer extends Renderer permits ConfigurableRenderer {\n\n\t/**\n\t * Renders any {@link Visitable}.\n\t * @param visitable the visitable to render\n\t * @return a Cypher fragment (in case of arbitrary visitables), a full statement in\n\t * case a {@link org.neo4j.cypherdsl.core.Statement} was passed to the renderer.\n\t */\n\tString render(Visitable visitable);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/Neo4j523SubqueryVisitor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport java.util.ArrayDeque;\nimport java.util.Deque;\nimport java.util.Objects;\n\nimport org.neo4j.cypherdsl.build.annotations.RegisterForReflection;\nimport org.neo4j.cypherdsl.core.ReturnBody;\nimport org.neo4j.cypherdsl.core.Subquery;\nimport org.neo4j.cypherdsl.core.With;\nimport org.neo4j.cypherdsl.core.ast.EnterResult;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.ast.VisitorWithResult;\n\n/**\n * Rendering <a href=\n * \"https://neo4j.com/docs/cypher-manual/5/subqueries/call-subquery/#variable-scope-clause\">variable\n * scope call clauses</a>.\n *\n * @author Michael J. Simons\n * @since 2024.1.0\n */\n@RegisterForReflection(allDeclaredConstructors = true)\nfinal class Neo4j523SubqueryVisitor extends VisitorWithResult {\n\n\tprivate static final GeneralizedRenderer RETURN_BODY_RENDERER = Renderer\n\t\t.getRenderer(Configuration.newConfig().withDialect(Dialect.NEO4J_5_23).build(), GeneralizedRenderer.class);\n\n\tprivate final DefaultVisitor delegate;\n\n\tprivate With importing;\n\n\tNeo4j523SubqueryVisitor(DefaultVisitor delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n\t@Override\n\tpublic EnterResult enterWithResult(Visitable segment) {\n\n\t\tif (segment instanceof Subquery subquery) {\n\t\t\tthis.importing = subquery.importingWith();\n\t\t\tthis.delegate.enter(subquery);\n\t\t\tthis.delegate.builder.replace(this.delegate.builder.length() - 1, this.delegate.builder.length(), \"(\");\n\t\t\tif (this.importing != null) {\n\t\t\t\tthis.importing.accept(innerSegment -> {\n\t\t\t\t\tif (innerSegment instanceof ReturnBody returnBody) {\n\t\t\t\t\t\treturnBody.accept(this.delegate);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\telse if (this.delegate.hasIdentifiables()) {\n\t\t\t\tthis.delegate.builder.append(\"*\");\n\t\t\t}\n\t\t\tthis.delegate.builder.append(\") {\");\n\t\t}\n\t\telse if (segment instanceof With possibleImporting) {\n\t\t\tif (!Objects.equals(this.importing, possibleImporting)) {\n\t\t\t\tthis.delegate.enter(possibleImporting);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpossibleImporting.accept(new Visitor() {\n\t\t\t\t\tprivate final Deque<Boolean> entered = new ArrayDeque<>();\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void enter(Visitable segment) {\n\t\t\t\t\t\tthis.entered.push(Neo4j523SubqueryVisitor.this.delegate.preEnter(segment));\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void leave(Visitable segment) {\n\t\t\t\t\t\tif (this.entered.pop()) {\n\t\t\t\t\t\t\tNeo4j523SubqueryVisitor.this.delegate.postLeave(segment);\n\t\t\t\t\t\t\tvar currentLength = Neo4j523SubqueryVisitor.this.delegate.builder.length();\n\t\t\t\t\t\t\tif (segment instanceof TypedSubtree<?> t && Neo4j523SubqueryVisitor.this.delegate.builder\n\t\t\t\t\t\t\t\t.subSequence(currentLength - t.separator().length(), currentLength)\n\t\t\t\t\t\t\t\t.equals(t.separator())) {\n\t\t\t\t\t\t\t\tNeo4j523SubqueryVisitor.this.delegate.builder\n\t\t\t\t\t\t\t\t\t.setLength(currentLength - t.separator().length());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn EnterResult.SKIP_CHILDREN;\n\t\t\t}\n\t\t}\n\n\t\treturn EnterResult.CONTINUE;\n\t}\n\n\t@Override\n\tpublic void leave(Visitable segment) {\n\n\t\tif (segment instanceof Subquery subquery) {\n\t\t\tthis.delegate.leave(subquery);\n\t\t}\n\t\telse if (segment instanceof With possibleImporting) {\n\t\t\tif (Objects.equals(this.importing, possibleImporting)) {\n\t\t\t\tthis.importing = null;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.delegate.leave(possibleImporting);\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/Neo4j5ComparisonVisitor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport org.neo4j.cypherdsl.build.annotations.RegisterForReflection;\nimport org.neo4j.cypherdsl.core.Comparison;\nimport org.neo4j.cypherdsl.core.Operator;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.ast.EnterResult;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.VisitorWithResult;\nimport org.neo4j.cypherdsl.core.renderer.Neo4j5FunctionInvocationVisitor.SingleArgExtractor;\n\n/**\n * Takes care of\n * <ul>\n * <li>Inverting <code>NOT EXISTS (n.prop)</code> into <code>n.prop IS NULL</code></li>\n * </ul>\n * .\n *\n * @author Michael J. Simons\n */\n@RegisterForReflection(allDeclaredConstructors = true)\nfinal class Neo4j5ComparisonVisitor extends VisitorWithResult {\n\n\tprivate final DefaultVisitor delegate;\n\n\tNeo4j5ComparisonVisitor(DefaultVisitor delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n\t@Override\n\tpublic EnterResult enterWithResult(Visitable segment) {\n\n\t\tComparison comparison = (Comparison) segment;\n\t\tAtomicReference<Operator> capture = new AtomicReference<>();\n\t\tAtomicInteger level = new AtomicInteger(0);\n\t\tAtomicReference<Visitable> nPropExists = new AtomicReference<>();\n\t\tcomparison.accept(new VisitorWithResult() {\n\t\t\t@Override\n\t\t\tpublic EnterResult enterWithResult(Visitable visitable) {\n\t\t\t\tboolean isOneLevelBelow = level.getAndIncrement() == 1;\n\t\t\t\tif (isOneLevelBelow) {\n\t\t\t\t\tif (visitable instanceof Operator operator) {\n\t\t\t\t\t\tcapture.compareAndSet(null, operator);\n\t\t\t\t\t}\n\t\t\t\t\telse if (Neo4j5FunctionInvocationVisitor.isNPropExists(visitable)) {\n\t\t\t\t\t\tnPropExists.compareAndSet(null, visitable);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn EnterResult.CONTINUE;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void leave(Visitable segment) {\n\t\t\t\tlevel.decrementAndGet();\n\t\t\t}\n\t\t});\n\n\t\tif (capture.get() == Operator.NOT && nPropExists.get() != null) {\n\t\t\tSingleArgExtractor<Property> singleArgExtractor = new SingleArgExtractor<>(Property.class);\n\t\t\tnPropExists.get().accept(singleArgExtractor);\n\t\t\tsingleArgExtractor.singleArg.accept(this.delegate);\n\t\t\tthis.delegate.builder.append(\" IS NULL\");\n\t\t\treturn EnterResult.SKIP_CHILDREN;\n\t\t}\n\n\t\treturn EnterResult.CONTINUE;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/Neo4j5FunctionInvocationVisitor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport org.neo4j.cypherdsl.build.annotations.RegisterForReflection;\nimport org.neo4j.cypherdsl.core.FunctionInvocation;\nimport org.neo4j.cypherdsl.core.NestedExpression;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.ast.EnterResult;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.ast.VisitorWithResult;\n\n/**\n * Some logic to rewrite a couple of functions for Neo4j 5.\n *\n * @author Michael J. Simons\n * @since 2022.3.0\n */\n@RegisterForReflection(allDeclaredConstructors = true)\nfinal class Neo4j5FunctionInvocationVisitor implements Visitor {\n\n\tprivate final DefaultVisitor delegate;\n\n\tNeo4j5FunctionInvocationVisitor(DefaultVisitor delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n\tstatic boolean isNPropExists(Visitable visitable) {\n\n\t\tif (visitable instanceof NestedExpression) {\n\t\t\tAtomicReference<Visitable> capture = new AtomicReference<>();\n\t\t\tvisitable.accept(new VisitorWithResult() {\n\t\t\t\t@Override\n\t\t\t\tpublic EnterResult enterWithResult(Visitable segment) {\n\t\t\t\t\tif (segment instanceof NestedExpression) { // The same object\n\t\t\t\t\t\treturn EnterResult.CONTINUE;\n\t\t\t\t\t}\n\t\t\t\t\treturn capture.compareAndSet(null, segment) ? EnterResult.SKIP_CHILDREN : EnterResult.CONTINUE;\n\t\t\t\t}\n\t\t\t});\n\t\t\tvisitable = capture.get();\n\t\t}\n\n\t\tif (!(visitable instanceof FunctionInvocation functionInvocation)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (\"exists\".equals(functionInvocation.getFunctionName())) {\n\t\t\tSingleArgExtractor<Property> singleArgExtractor = new SingleArgExtractor<>(Property.class);\n\t\t\tfunctionInvocation.accept(singleArgExtractor);\n\t\t\treturn singleArgExtractor.singleArg != null;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void enter(Visitable visitable) {\n\n\t\tFunctionInvocation functionInvocation = (FunctionInvocation) visitable;\n\t\tif (\"distance\".equals(functionInvocation.getFunctionName())) {\n\t\t\tthis.delegate.builder.append(\"point.distance(\");\n\t\t}\n\t\telse if (\"elementId\".equals(functionInvocation.getFunctionName())) {\n\t\t\tthis.delegate.builder.append(\"elementId(\");\n\t\t}\n\t\telse if (!isNPropExists(visitable)) {\n\t\t\tthis.delegate.enter(functionInvocation);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void leave(Visitable visitable) {\n\n\t\tFunctionInvocation functionInvocation = (FunctionInvocation) visitable;\n\t\tif (isNPropExists(visitable)) {\n\t\t\tthis.delegate.builder.append(\" IS NOT NULL\");\n\t\t}\n\t\telse if (\"elementId\".equals(functionInvocation.getFunctionName())) {\n\t\t\tthis.delegate.builder.append(\")\");\n\t\t}\n\t\telse {\n\t\t\tthis.delegate.leave(functionInvocation);\n\t\t}\n\t}\n\n\tstatic class SingleArgExtractor<T> extends VisitorWithResult {\n\n\t\tfinal Class<T> expectedType;\n\n\t\tboolean insideArguments;\n\n\t\tint level = 0;\n\n\t\tT singleArg;\n\n\t\tSingleArgExtractor(Class<T> expectedType) {\n\t\t\tthis.expectedType = expectedType;\n\t\t}\n\n\t\t@SuppressWarnings(\"unchecked\")\n\t\t@Override\n\t\tpublic EnterResult enterWithResult(Visitable segment) {\n\t\t\tif (segment instanceof NestedExpression) {\n\t\t\t\treturn EnterResult.CONTINUE;\n\t\t\t}\n\n\t\t\tif (++this.level == 2) {\n\t\t\t\tthis.insideArguments = true;\n\t\t\t}\n\n\t\t\tif (this.insideArguments && this.level == 3 && this.expectedType.isInstance(segment)) {\n\t\t\t\tthis.singleArg = (this.singleArg != null) ? null : (T) segment;\n\t\t\t}\n\t\t\treturn EnterResult.CONTINUE;\n\t\t}\n\n\t\t@Override\n\t\tpublic void leave(Visitable segment) {\n\t\t\tthis.insideArguments = this.level-- != 2;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/Neo4j5Pre26LabelsVisitor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport java.util.EnumSet;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport org.neo4j.cypherdsl.build.annotations.RegisterForReflection;\nimport org.neo4j.cypherdsl.core.Labels;\nimport org.neo4j.cypherdsl.core.ListExpression;\nimport org.neo4j.cypherdsl.core.ListLiteral;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Parameter;\nimport org.neo4j.cypherdsl.core.StringLiteral;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.internal.SchemaNamesBridge;\n\n/**\n * Express colon conjunctions containing string resolvable expressions as static labels\n * prior to Neo4j 5.26.\n *\n * @author Michael J. Simons\n * @since 2025.0.2\n */\n@RegisterForReflection(allDeclaredConstructors = true)\nfinal class Neo4j5Pre26LabelsVisitor implements Visitor {\n\n\tprivate final DefaultVisitor delegate;\n\n\tprivate final AtomicBoolean didDelegate = new AtomicBoolean(false);\n\n\tNeo4j5Pre26LabelsVisitor(DefaultVisitor delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n\tvoid render(Object visitable) {\n\t\tif (visitable instanceof Parameter<?> parameter) {\n\t\t\trender(parameter.getValue());\n\t\t}\n\t\telse if (visitable instanceof ListExpression listExpression) {\n\t\t\tlistExpression.accept(segment -> {\n\t\t\t\tif (segment instanceof ListExpression) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\trender(segment);\n\t\t\t});\n\t\t}\n\t\telse if (visitable instanceof ListLiteral listLiteral) {\n\t\t\tfor (var literal : listLiteral.getContent()) {\n\t\t\t\trender(literal);\n\t\t\t}\n\t\t}\n\t\telse if (visitable instanceof StringLiteral stringLiteral) {\n\t\t\trenderAsLabel(stringLiteral.getContent().toString());\n\t\t}\n\t\telse if (visitable instanceof List<?> list) {\n\t\t\tfor (var item : list) {\n\t\t\t\tif (item instanceof String string) {\n\t\t\t\t\trenderAsLabel(string);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (visitable instanceof String string) {\n\t\t\trenderAsLabel(string);\n\t\t}\n\t\telse if (visitable instanceof NodeLabel label) {\n\t\t\trenderAsLabel(label.getValue());\n\t\t}\n\t\telse if (!\"org.neo4j.cypherdsl.core.ExpressionList\".equals(visitable.getClass().getName())) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot render the given Labels in a Cypher pre 5.26 compatible way\");\n\t\t}\n\t}\n\n\tprivate void renderAsLabel(String string) {\n\t\tthis.delegate.builder.append(\":\")\n\t\t\t.append(SchemaNamesBridge.sanitize(string, this.delegate.alwaysEscapeNames).orElseThrow());\n\t}\n\n\t@Override\n\tpublic void enter(Visitable segment) {\n\t\tif (!(segment instanceof Labels labels)) {\n\t\t\treturn;\n\t\t}\n\t\tif (labels.getLhs() == null && labels.getRhs() == null\n\t\t\t\t&& EnumSet.of(Labels.Type.LEAF, Labels.Type.COLON_CONJUNCTION).contains(labels.getType())) {\n\t\t\tfor (var value : labels.getValue()) {\n\t\t\t\trender(value.visitable());\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthis.didDelegate.compareAndSet(false, true);\n\t\t\tthis.delegate.enter(labels);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void leave(Visitable segment) {\n\n\t\tif (this.didDelegate.compareAndSet(true, false)) {\n\t\t\t// Cast needs to be in here to make the visitor pick up the correct target\n\t\t\tthis.delegate.leave((Labels) segment);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/PatternSelectorVisitorPreNeo4j521.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport java.util.ArrayDeque;\nimport java.util.Deque;\n\nimport org.neo4j.cypherdsl.core.PatternSelector;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nfinal class PatternSelectorVisitorPreNeo4j521 implements Visitor {\n\n\tprivate final DefaultVisitor delegate;\n\n\tprivate final Deque<Boolean> handled = new ArrayDeque<>();\n\n\tPatternSelectorVisitorPreNeo4j521(DefaultVisitor delegate) {\n\t\tthis.delegate = delegate;\n\t}\n\n\t@Override\n\tpublic void enter(Visitable segment) {\n\t\tif (segment instanceof PatternSelector.ShortestK shortestK && shortestK.getK() == 1) {\n\t\t\tthis.delegate.builder.append(\"shortestPath(\");\n\t\t\tthis.handled.push(true);\n\t\t}\n\t\telse if (segment instanceof PatternSelector.AllShortest) {\n\t\t\tthis.delegate.builder.append(\"allShortestPaths(\");\n\t\t\tthis.handled.push(true);\n\t\t}\n\t\telse {\n\t\t\tthis.delegate.enter(((PatternSelector) segment));\n\t\t\tthis.handled.push(false);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void leave(Visitable segment) {\n\t\tif (this.handled.pop()) {\n\t\t\tthis.delegate.builder.append(\")\");\n\t\t}\n\t\telse {\n\t\t\tthis.delegate.leave(segment);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/PrettyPrintingVisitor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport java.util.function.BiConsumer;\n\nimport org.neo4j.cypherdsl.build.annotations.RegisterForReflection;\nimport org.neo4j.cypherdsl.core.Condition;\nimport org.neo4j.cypherdsl.core.Create;\nimport org.neo4j.cypherdsl.core.KeyValueMapEntry;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Match;\nimport org.neo4j.cypherdsl.core.Merge;\nimport org.neo4j.cypherdsl.core.MergeAction;\nimport org.neo4j.cypherdsl.core.Operator;\nimport org.neo4j.cypherdsl.core.Parameter;\nimport org.neo4j.cypherdsl.core.PropertyLookup;\nimport org.neo4j.cypherdsl.core.Return;\nimport org.neo4j.cypherdsl.core.Set;\nimport org.neo4j.cypherdsl.core.StatementContext;\nimport org.neo4j.cypherdsl.core.Subquery;\nimport org.neo4j.cypherdsl.core.SubqueryExpression;\nimport org.neo4j.cypherdsl.core.Unwind;\nimport org.neo4j.cypherdsl.core.Use;\nimport org.neo4j.cypherdsl.core.Where;\nimport org.neo4j.cypherdsl.core.With;\nimport org.neo4j.cypherdsl.core.ast.ProvidesAffixes;\nimport org.neo4j.cypherdsl.core.internal.ConstantParameterHolder;\nimport org.neo4j.cypherdsl.core.renderer.Configuration.IndentStyle;\n\n/**\n * This visitor extends the default visitor and tries to pretty print a Cypher statement,\n * i.e. using some indentation and linebreaks.\n *\n * @author Andreas Berger\n * @author Michael J. Simons\n * @author Christophe Willemsen\n */\n@SuppressWarnings(\"unused\")\n@RegisterForReflection\nclass PrettyPrintingVisitor extends DefaultVisitor {\n\n\tprivate final BiConsumer<StringBuilder, Integer> indentionProvider;\n\n\t/**\n\t * In contrast to the current level in the {@link DefaultVisitor} that contains the\n\t * level of elements in the tree.\n\t */\n\tprivate int indentationLevel;\n\n\tprivate boolean passedFirstReadingOrUpdatingClause;\n\n\tPrettyPrintingVisitor(StatementContext statementContext, Configuration configuration) {\n\t\tthis(statementContext, false, configuration);\n\t}\n\n\tPrettyPrintingVisitor(StatementContext statementContext, boolean renderConstantsAsParameters,\n\t\t\tConfiguration configuration) {\n\t\tsuper(statementContext, renderConstantsAsParameters, configuration);\n\n\t\tIndentStyle indentStyle = configuration.getIndentStyle();\n\t\tint indentSize = configuration.getIndentSize();\n\n\t\tif (indentStyle == IndentStyle.TAB) {\n\t\t\tthis.indentionProvider = (builder, width) -> builder.append(\"\\t\".repeat(Math.max(0, width)));\n\t\t}\n\t\telse {\n\t\t\tthis.indentionProvider = (builder, width) -> builder.append(\" \".repeat(Math.max(0, width * indentSize)));\n\t\t}\n\t}\n\n\tprivate void indent(int width) {\n\t\tthis.indentionProvider.accept(this.builder, width);\n\t}\n\n\t@Override\n\tvoid enter(Where where) {\n\t\tif (this.currentVisitedElements.stream().noneMatch(Return.class::isInstance)) {\n\t\t\tthis.builder.append(\"\\n\");\n\t\t\tindent(this.indentationLevel);\n\t\t\tthis.builder.append(\"WHERE \");\n\t\t}\n\t\telse {\n\t\t\tsuper.enter(where);\n\t\t}\n\t}\n\n\t@Override\n\tvoid enter(Return returning) {\n\t\ttrimNewline();\n\t\tindent(this.indentationLevel);\n\t\tsuper.enter(returning);\n\t}\n\n\t@Override\n\tvoid enter(Unwind unwind) {\n\t\ttrimNewline();\n\t\tindent(this.indentationLevel);\n\t\tsuper.enter(unwind);\n\t}\n\n\t@Override\n\tvoid enter(With with) {\n\t\tif (this.passedFirstReadingOrUpdatingClause) {\n\t\t\ttrimNewline();\n\t\t\tindent(this.indentationLevel);\n\t\t}\n\t\tthis.passedFirstReadingOrUpdatingClause = true;\n\t\tsuper.enter(with);\n\t}\n\n\t@Override\n\tvoid enter(Set set) {\n\t\tif (this.currentVisitedElements.stream().noneMatch(MergeAction.class::isInstance)) {\n\t\t\ttrimNewline();\n\t\t\tindent(this.indentationLevel);\n\t\t}\n\t\tsuper.enter(set);\n\t}\n\n\t@Override\n\tvoid enter(Match match) {\n\t\tif (this.passedFirstReadingOrUpdatingClause) {\n\t\t\ttrimNewline();\n\t\t\tindent(this.indentationLevel);\n\t\t}\n\t\tthis.passedFirstReadingOrUpdatingClause = true;\n\t\tsuper.enter(match);\n\t}\n\n\t@Override\n\tvoid enter(Create create) {\n\t\tif (this.passedFirstReadingOrUpdatingClause) {\n\t\t\ttrimNewline();\n\t\t\tindent(this.indentationLevel);\n\t\t}\n\t\tthis.passedFirstReadingOrUpdatingClause = true;\n\t\tsuper.enter(create);\n\t}\n\n\t@Override\n\tvoid enter(PropertyLookup propertyLookup) {\n\t\tif (this.currentVisitedElements.stream().skip(1).limit(1).anyMatch(MapExpression.class::isInstance)) {\n\t\t\ttrimNewline();\n\t\t\tindent(this.indentationLevel);\n\t\t}\n\t\tsuper.enter(propertyLookup);\n\t}\n\n\t@Override\n\tvoid enter(KeyValueMapEntry map) {\n\t\tif (this.indentationLevel > 0) {\n\t\t\ttrimNewline();\n\t\t\tindent(this.indentationLevel);\n\t\t}\n\t\tsuper.enter(map);\n\t}\n\n\t@Override\n\tvoid enter(Condition condition) {\n\n\t\tif (condition instanceof ProvidesAffixes) {\n\t\t\tthis.indentationLevel++;\n\t\t}\n\t\tsuper.enter(condition);\n\t}\n\n\t@Override\n\tvoid leave(Condition condition) {\n\n\t\tif (condition instanceof ProvidesAffixes) {\n\t\t\tthis.indentationLevel--;\n\t\t}\n\t\tsuper.leave(condition);\n\t}\n\n\t@Override\n\tvoid enter(Operator operator) {\n\t\tOperator.Type type = operator.getType();\n\t\tif (type == Operator.Type.LABEL) {\n\t\t\treturn;\n\t\t}\n\t\tif (type != Operator.Type.PREFIX && operator != Operator.EXPONENTIATION) {\n\t\t\tthis.builder.append(\" \");\n\t\t}\n\t\tif (operator == Operator.OR || operator == Operator.AND || operator == Operator.XOR) {\n\t\t\ttrimNewline();\n\t\t\tindent(this.indentationLevel);\n\t\t}\n\t\tthis.builder.append(operator.getRepresentation());\n\t\tif (type != Operator.Type.POSTFIX && operator != Operator.EXPONENTIATION) {\n\t\t\tthis.builder.append(\" \");\n\t\t}\n\t}\n\n\t@Override\n\tvoid enter(MapExpression map) {\n\t\tthis.indentationLevel++;\n\t\tint cnt = 0;\n\t\tfor (int i = this.builder.length() - 1; i >= 0; --i) {\n\t\t\tif (Character.isWhitespace(this.builder.charAt(i))) {\n\t\t\t\t++cnt;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tthis.builder.setLength(this.builder.length() - cnt);\n\t\tthis.builder.append(\" \");\n\t\tsuper.enter(map);\n\t}\n\n\t@Override\n\tvoid leave(MapExpression map) {\n\t\tthis.indentationLevel--;\n\t\ttrimNewline();\n\t\tindent(this.indentationLevel);\n\t\tsuper.leave(map);\n\t}\n\n\t@Override\n\tvoid enter(MergeAction onCreateOrMatchEvent) {\n\t\ttrimNewline();\n\t\tindent(1);\n\t\tsuper.enter(onCreateOrMatchEvent);\n\t}\n\n\t@Override\n\tvoid enter(Merge merge) {\n\t\tif (this.passedFirstReadingOrUpdatingClause) {\n\t\t\ttrimNewline();\n\t\t\tindent(this.indentationLevel);\n\t\t}\n\t\tthis.passedFirstReadingOrUpdatingClause = true;\n\t\tsuper.enter(merge);\n\t}\n\n\t@Override\n\tvoid enter(SubqueryExpression subquery) {\n\t\tsuper.enter(subquery);\n\t\tthis.indentationLevel++;\n\t}\n\n\t@Override\n\tvoid leave(SubqueryExpression subquery) {\n\t\tthis.indentationLevel--;\n\t\ttrimNewline();\n\t\tindent(this.indentationLevel);\n\t\tthis.builder.append(\"}\");\n\t}\n\n\t@Override\n\tvoid enter(Subquery subquery) {\n\t\tthis.passedFirstReadingOrUpdatingClause = true;\n\t\ttrimNewline();\n\t\tindent(this.indentationLevel);\n\t\tthis.indentationLevel++;\n\t\tsuper.enter(subquery);\n\t}\n\n\t@Override\n\tvoid enter(Use use) {\n\t\ttrimNewline();\n\t\tindent(this.indentationLevel);\n\t\tsuper.enter(use);\n\t}\n\n\t@Override\n\tvoid leave(Subquery subquery) {\n\t\tthis.indentationLevel--;\n\t\ttrimNewline();\n\t\tindent(this.indentationLevel);\n\n\t\tthis.inSubquery = false;\n\t\tthis.builder.append(\"} \");\n\t}\n\n\tprivate void trimNewline() {\n\t\tfor (int i = this.builder.length() - 1; i >= 0; i--) {\n\t\t\tif (this.builder.charAt(i) == ' ') {\n\t\t\t\tthis.builder.deleteCharAt(i);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tthis.builder.append(\"\\n\");\n\t}\n\n\t@Override\n\tvoid enter(Parameter<?> parameter) {\n\n\t\tObject value = parameter.getValue();\n\t\tif (value instanceof ConstantParameterHolder constantParameterHolder) {\n\t\t\tthis.builder.append(constantParameterHolder.asString());\n\t\t}\n\t\telse {\n\t\t\tsuper.enter(parameter);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/Renderer.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Statement;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Instances of this class are supposed to be thread-safe. Please use\n * {@link Renderer#getDefaultRenderer()} to get hold of an implementation.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\n@API(status = STABLE, since = \"1.0\")\npublic sealed interface Renderer permits ConfigurableRenderer, GeneralizedRenderer {\n\n\t/**\n\t * Provides the default renderer. This method may or may not provide shared instances\n\t * of the renderer.\n\t * @return the default renderer.\n\t */\n\tstatic Renderer getDefaultRenderer() {\n\t\treturn getRenderer(Configuration.defaultConfig());\n\t}\n\n\t/**\n\t * Creates a new renderer for the given configuration.\n\t * @param configuration the configuration for this renderer\n\t * @return a new renderer (might be a shared instance).\n\t */\n\tstatic Renderer getRenderer(Configuration configuration) {\n\t\treturn getRenderer(configuration, Renderer.class);\n\t}\n\n\t/**\n\t * Creates a new renderer for the given configuration.\n\t * @param <T> the specific type of the renderer\n\t * @param configuration the configuration for this renderer\n\t * @param type reification of the renderers type\n\t * @return a new renderer (might be a shared instance).\n\t * @since 2023.1.0\n\t */\n\tstatic <T extends Renderer> T getRenderer(Configuration configuration, Class<T> type) {\n\t\treturn type.cast(ConfigurableRenderer.create(configuration));\n\t}\n\n\t/**\n\t * Renders a statement.\n\t * @param statement the statement to render\n\t * @return the rendered Cypher statement.\n\t */\n\tString render(Statement statement);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/RenderingVisitor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\n/**\n * Internal interface for various implementations of {@link Visitor visitors} that provide\n * a rendered view of the visitable they have been used with.\n *\n * @author Michael J. Simons\n */\ninterface RenderingVisitor extends Visitor {\n\n\t/**\n\t * {@return renderer content after this visitor has been accepted by a Visitable}\n\t */\n\tString getRenderedContent();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/SchemaEnforcementFailedException.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport java.io.Serial;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Thrown when schema validation fails.\n *\n * @author Michael J. Simons\n * @since 2023.7.0\n */\n@API(status = INTERNAL, since = \"2023.7.0\")\npublic final class SchemaEnforcementFailedException extends RuntimeException {\n\n\t@Serial\n\tprivate static final long serialVersionUID = 5473466301617398078L;\n\n\t/**\n\t * Creates a new instance, not to be used by client code.\n\t */\n\tpublic SchemaEnforcementFailedException() {\n\t\t// Make the Java module system happy.\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/Symbols.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\n/**\n * Symbols used during Cypher rendering.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\nfinal class Symbols {\n\n\tstatic final String NODE_LABEL_START = \":\";\n\n\tstatic final String REL_TYPE_START = \":\";\n\n\tstatic final String REL_TYP_SEPARATOR = \"|\";\n\n\tprivate Symbols() {\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/renderer/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * A renderer for {@link org.neo4j.cypherdsl.core.Statement statements} in the simplest\n * form possible.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/utils/Assertions.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.utils;\n\nimport java.util.Arrays;\nimport java.util.Objects;\n\nimport org.apiguardian.api.API;\n\n/**\n * Assertions used throughout the Cypher-DSL. Mostly copied over from\n * {@literal org.springframework.util.Assert}. Thanks to the original authors: Keith\n * Donald, Juergen Hoeller, Sam Brannen, Colin Sampaleanu and Rob Harrop. Not supported\n * for external use in any way.\n *\n * @author Michael J. Simons\n * @since 2020.0.0\n */\n@API(status = API.Status.INTERNAL, since = \"2020.0.0\")\npublic final class Assertions {\n\n\tprivate Assertions() {\n\t}\n\n\t/**\n\t * Assert that the given String contains valid text content; that is, it must not be\n\t * {@code null} and must contain at least one non-whitespace character.\n\t * <pre class=\"code\">Assert.hasText(name, \"'name' must not be empty\");</pre>\n\t * @param text the String to check\n\t * @param message the exception message to use if the assertion fails\n\t * @throws IllegalArgumentException if the text does not contain valid text content\n\t */\n\tpublic static void hasText(String text, String message) {\n\t\tif (!Strings.hasText(text)) {\n\t\t\tthrow new IllegalArgumentException(message);\n\t\t}\n\t}\n\n\t/**\n\t * Assert a boolean expression, throwing an {@code IllegalArgumentException} if the\n\t * expression evaluates to {@code false}. <pre class=\n\t * \"code\">Assert.isTrue(i &gt; 0, \"The value must be greater than zero\");</pre>\n\t * @param expression a boolean expression\n\t * @param message the exception message to use if the assertion fails\n\t * @throws IllegalArgumentException if {@code expression} is {@code false}\n\t */\n\tpublic static void isTrue(boolean expression, String message) {\n\t\tif (!expression) {\n\t\t\tthrow new IllegalArgumentException(message);\n\t\t}\n\t}\n\n\t/**\n\t * Assert that an object is not {@code null}.\n\t * <pre class=\"code\">Assert.notNull(clazz, \"The class must not be null\");</pre>\n\t * @param object the object to check\n\t * @param message the exception message to use if the assertion fails\n\t * @throws IllegalArgumentException if the object is {@code null}\n\t */\n\tpublic static void notNull(Object object, String message) {\n\t\tif (object == null) {\n\t\t\tthrow new IllegalArgumentException(message);\n\t\t}\n\t}\n\n\t/**\n\t * Assert that the provided object is an instance of the provided class.\n\t * <pre class=\"code\">Assert.instanceOf(Foo.class, foo, \"Foo expected\");</pre>\n\t * @param type the type to check against\n\t * @param obj the object to check\n\t * @param message the exception message to use if the assertion fails\n\t * @throws IllegalArgumentException if the object is not an instance of type\n\t */\n\tpublic static void isInstanceOf(Class<?> type, Object obj, String message) {\n\t\tnotNull(type, \"Type to check against must not be null\");\n\t\tif (!type.isInstance(obj)) {\n\t\t\tthrow new IllegalArgumentException(message);\n\t\t}\n\t}\n\n\t/**\n\t * Assert that an array contains elements; that is, it must not be {@code null} and\n\t * must contain at least one element.\n\t * <pre class=\"code\">Assert.notEmpty(array, \"The array must contain elements\");</pre>\n\t * @param array the array to check\n\t * @param message the exception message to use if the assertion fails\n\t * @throws IllegalArgumentException if the object array is {@code null} or contains no\n\t * elements\n\t */\n\tpublic static void notEmpty(Object[] array, String message) {\n\t\tif (isEmpty(array)) {\n\t\t\tthrow new IllegalArgumentException(message);\n\t\t}\n\t}\n\n\tprivate static boolean isEmpty(Object[] array) {\n\t\treturn array == null || array.length == 0 || Arrays.stream(array).allMatch(Objects::isNull);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/utils/LRUCache.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.utils;\n\nimport java.io.Serial;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * A non thread safe least recently used (LRU) cache. It must be used with a locking\n * implementation around it.\n *\n * @param <K> type of the keys\n * @param <V> type of the values\n * @author Michael J. Simons\n * @since 2021.0.2\n */\n@API(status = INTERNAL, since = \"2021.0.2\")\npublic final class LRUCache<K, V> extends LinkedHashMap<K, V> {\n\n\t@Serial\n\tprivate static final long serialVersionUID = -6819899594092598277L;\n\n\t/**\n\t * Cache size. When current size reaches that values, the eldest entries will be\n\t * removed.\n\t */\n\tprivate final int cacheSize;\n\n\t/**\n\t * Creates a new LRU cache with the given cache size.\n\t * @param cacheSize the number of entries to keep around.\n\t */\n\tpublic LRUCache(int cacheSize) {\n\t\tsuper(cacheSize / 4, 0.75f, true);\n\t\tthis.cacheSize = cacheSize;\n\t}\n\n\t@Override\n\tprotected boolean removeEldestEntry(Map.Entry<K, V> eldest) {\n\t\treturn size() >= this.cacheSize;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/utils/Strings.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.utils;\n\nimport java.util.concurrent.ThreadLocalRandom;\n\nimport org.apiguardian.api.API;\n\n/**\n * The usual, static class with helper methods centered around missing functionality in\n * {@link String}. Not supported for external use in any way.\n *\n * @author Michael J. Simons\n * @since 2020.1.0\n */\n@API(status = API.Status.INTERNAL, since = \"2020.1.0\")\npublic final class Strings {\n\n\tprivate Strings() {\n\t}\n\n\t/**\n\t * Returns true, if the string is neither null nor empty nor blank.\n\t * @param str a string to be checked for text.\n\t * @return true, if the string is neither null nor empty nor blank\n\t */\n\tpublic static boolean hasText(String str) {\n\t\treturn str != null && !str.isBlank();\n\t}\n\n\t/**\n\t * Returns a random identifier that is a valid identifier.\n\t * @param length the length of the identifier to generate.\n\t * @return a random identifier that is a valid identifier\n\t */\n\tpublic static String randomIdentifier(int length) {\n\n\t\tint leftLimit = 65; // letter 'A'\n\t\tint rightLimit = 122; // letter 'z'\n\t\t// I really need only random string values, this is fine\n\t\t@SuppressWarnings(\"squid:S2245\")\n\t\tThreadLocalRandom random = ThreadLocalRandom.current();\n\n\t\treturn random.ints(leftLimit, rightLimit + 1)\n\t\t\t.filter(Character::isLetter)\n\t\t\t.limit(length)\n\t\t\t.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)\n\t\t\t.toString();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/java/org/neo4j/cypherdsl/core/utils/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Set of {@code *Utils} classes for internal usage.\n */\npackage org.neo4j.cypherdsl.core.utils;\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/resources/META-INF/native-image/org.neo4j/neo4j-cypher-dsl/native-image.properties",
    "content": "#\n# Copyright (c) 2019-2026 \"Neo4j,\"\n# Neo4j Sweden AB [https://neo4j.com]\n#\n# This file is part of Neo4j.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nArgs = -H:ReflectionConfigurationResources=${.}/reflection-config.json \\\n  -H:ResourceConfigurationResources=${.}/resources-config.json\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/resources/META-INF/native-image/org.neo4j/neo4j-cypher-dsl/resources-config.json",
    "content": "{\n  \"bundles\": [\n    {\n      \"name\": \"org.neo4j.cypherdsl.core.messages\"\n    }\n  ]\n}"
  },
  {
    "path": "neo4j-cypher-dsl/src/main/resources/org/neo4j/cypherdsl/core/messages.properties",
    "content": "#\n# Copyright (c) 2019-2026 \"Neo4j,\"\n# Neo4j Sweden AB [https://neo4j.com]\n#\n# This file is part of Neo4j.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nassertions.expression-required = The expression is required.\nassertions.expressions-required = Expressions to return are required.\nassertions.at-least-one-expression-required = At least one expressions to return is required.\nassertions.node-required = The node is required.\nassertions.relationship-required = The relationship is required.\nassertions.variable-required = The variable is required.\nassertions.components-required = The components are required.\nassertions.temporal-value-required = The temporalValue is required.\nassertions.year-required = The year is required.\nassertions.month-required = The month is required.\nassertions.day-required = The day is required.\nassertions.tz-required = The timezone is required.\nassertions.range-target-required = The range's target expression must not be null.\nassertions.range-index-required = The index of the range must not be null.\nassertions.range-start-required = The start of the range must not be null.\nassertions.range-end-required = The end of the range must not be null.\nassertions.expression-for-function-required = The expression for {0}() is required.\nassertions.pattern-for-function-required = The pattern for {0}() is required.\nassertions.at-least-one-arg-required = {0}() requires at least one argument.\nassertions.correct-usage-of-distinct = The distinct operator can only be applied within aggregate functions.\nassertions.requires-name-for-mutation = A property container must be named to be mutated.\nassertions.named-path-required = The path needs to be named!\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/BooleanLiteralTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.CsvSource;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass BooleanLiteralTests {\n\n\t@ParameterizedTest\n\t@CsvSource(nullValues = \"n/a\", value = { \"n/a,false\", \"false,false\", \"true,true\" })\n\tvoid valueOfShouldWork(Boolean input, boolean expected) {\n\t\tLiteral<Boolean> literal = BooleanLiteral.of(input);\n\t\tassertThat(literal).isInstanceOf(BooleanLiteral.class);\n\t\tBooleanLiteral booleanLiteral = (BooleanLiteral) literal;\n\t\tif (expected) {\n\t\t\tassertThat(booleanLiteral).isEqualTo(BooleanLiteral.TRUE);\n\t\t}\n\t\telse {\n\t\t\tassertThat(booleanLiteral).isEqualTo(BooleanLiteral.FALSE);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/BuiltInFunctionsTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Locale;\n\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.EnumSource;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n *\n */\nclass BuiltInFunctionsTests {\n\n\t@Nested\n\tclass MathematicalFunctionsTest {\n\n\t\t/**\n\t\t * Sanity check that we didn't miss up the names. For the time being, the\n\t\t * constants are equal to the actual implementation names.\n\t\t */\n\t\t@ParameterizedTest\n\t\t@EnumSource(BuiltInFunctions.MathematicalFunctions.class)\n\t\tvoid functionNameSanityCheck(BuiltInFunctions.MathematicalFunctions function) {\n\n\t\t\tassertThat(function.name().toLowerCase(Locale.ROOT)).isEqualTo(function.getImplementationName());\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/ClausesTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Collections;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n */\nclass ClausesTests {\n\n\t@Test\n\tvoid updatingClausesShouldBeCheckInForeach() {\n\n\t\tClause anonymousClause = new Clause() {\n\t\t\t@Override\n\t\t\tpublic void accept(Visitor visitor) {\n\t\t\t\tClause.super.accept(visitor);\n\t\t\t}\n\t\t};\n\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> Clauses.forEach(SymbolicName.of(\"x\"), Cypher.literalNull(),\n\t\t\t\t\tCollections.singletonList(anonymousClause)))\n\t\t\t.withMessage(\n\t\t\t\t\t\"Only updating clauses SET, REMOVE, CREATE, MERGE, DELETE, and FOREACH are allowed as clauses applied inside FOREACH.\");\n\t}\n\n\t@Test\n\tvoid foreachShouldWork() {\n\n\t\tClause foreach = Clauses.forEach(SymbolicName.of(\"x\"), Cypher.literalNull(),\n\t\t\t\tCollections.singletonList(new Set(new ExpressionList())));\n\t\tassertThat(foreach).isNotNull();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/ComparisonTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n * @author Gerrit Meier\n */\nclass ComparisonTests {\n\n\t@Test\n\tvoid preconditionsShouldBeAsserted() {\n\n\t\tExpression expression = Cypher.literalOf(\"Arbitrary expression\");\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Comparison.create(null, Operator.EQUALITY, expression))\n\t\t\t.withMessage(\"Left expression must not be null.\");\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Comparison.create(expression, Operator.EQUALITY, null))\n\t\t\t.withMessage(\"Right expression must not be null.\");\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Comparison.create(expression, null, expression))\n\t\t\t.withMessage(\"Operator must not be empty.\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/Cypher5IT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Dialect;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * Tests around GH-1153\n */\nclass Cypher5IT {\n\n\tprivate final Renderer renderer = Renderer\n\t\t.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).withDialect(Dialect.NEO4J_5_CYPHER_5).build());\n\n\t@Test\n\tvoid cypher5PrefixOnSimpleStatements() {\n\t\tvar n = Cypher.node(\"Movie\").named(\"n\");\n\t\tvar stmt = Cypher.match(n).returning(n).build();\n\t\tassertThat(this.renderer.render(stmt)).isEqualTo(\"CYPHER 5 MATCH (n:Movie) RETURN n\");\n\t}\n\n\t@Test\n\tvoid unionShouldNotHaveDoublePrefixes() {\n\t\tStatement statement1 = Cypher.match(CypherIT.BIKE_NODE)\n\t\t\t.where(CypherIT.BIKE_NODE.property(\"a\").isEqualTo(Cypher.literalOf(\"A\")))\n\t\t\t.returning(CypherIT.BIKE_NODE)\n\t\t\t.build();\n\n\t\tStatement statement2 = Cypher.match(CypherIT.BIKE_NODE)\n\t\t\t.where(CypherIT.BIKE_NODE.property(\"b\").isEqualTo(Cypher.literalOf(\"B\")))\n\t\t\t.returning(CypherIT.BIKE_NODE)\n\t\t\t.build();\n\n\t\tStatement statement3 = Cypher.match(CypherIT.BIKE_NODE)\n\t\t\t.where(CypherIT.BIKE_NODE.property(\"c\").isEqualTo(Cypher.literalOf(\"C\")))\n\t\t\t.returning(CypherIT.BIKE_NODE)\n\t\t\t.build();\n\t\tStatement statement;\n\t\tstatement = Cypher.union(statement1, statement2, statement3);\n\n\t\tassertThat(this.renderer.render(statement)).isEqualTo(\n\t\t\t\t\"CYPHER 5 MATCH (b:Bike) WHERE b.a = 'A' RETURN b UNION MATCH (b:Bike) WHERE b.b = 'B' RETURN b UNION MATCH (b:Bike) WHERE b.c = 'C' RETURN b\");\n\t}\n\n\t@Test\n\tvoid useShouldWork() {\n\n\t\tvar statement = Cypher.match(Cypher.anyNode(\"n\")).returning(\"n\").build();\n\t\tvar cypher = this.renderer.render(Cypher.use(\"neo4j\", statement));\n\t\tassertThat(cypher).isEqualTo(\"CYPHER 5 USE neo4j MATCH (n) RETURN n\");\n\t}\n\n\t@Test\n\tvoid explainShouldWork() {\n\n\t\tvar statement = Cypher.match(Cypher.anyNode(\"n\")).returning(\"n\").build();\n\t\tvar cypher = this.renderer.render(DecoratedQuery.explain(statement));\n\t\tassertThat(cypher).isEqualTo(\"CYPHER 5 EXPLAIN MATCH (n) RETURN n\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/CypherIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.function.Function;\nimport java.util.function.Supplier;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.TestInstance;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.junit.jupiter.params.provider.ValueSource;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Dialect;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\nimport static org.assertj.core.api.Assertions.assertThatNoException;\n\n/**\n * @author Michael J. Simons\n * @author Gerrit Meier\n * @author Andreas Berger\n */\nclass CypherIT {\n\n\tpublic static final Configuration NEO5J_CONFIG = Configuration.newConfig().withDialect(Dialect.NEO4J_5).build();\n\tstatic final Node BIKE_NODE = Cypher.node(\"Bike\").named(\"b\");\n\tstatic final Node USER_NODE = Cypher.node(\"User\").named(\"u\");\n\n\tprivate static final Renderer cypherRenderer = Renderer.getDefaultRenderer();\n\n\t@Test\n\tvoid statementShouldBeRenderable() {\n\n\t\tStatement statement = Cypher.returning(Cypher.literalTrue().as(\"t\")).build();\n\t\tString cypher = statement.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"RETURN true AS t\");\n\t\tassertThat(statement.getCypher()).isSameAs(cypher);\n\t}\n\n\t@Test\n\tvoid parameterLiterals() {\n\n\t\tStatement statement = Cypher\n\t\t\t.returning(Cypher.literalOf(Cypher.parameter(\"asd\")).as(\"t\"),\n\t\t\t\t\tCypher.literalOf(Map.of(\"another\", Cypher.parameter(\"parameter\"))).as(\"t2\"))\n\t\t\t.build();\n\t\tString cypher = statement.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"RETURN $asd AS t, {another: $parameter} AS t2\");\n\t\tassertThat(statement.getCypher()).isSameAs(cypher);\n\t}\n\n\t@Test\n\tvoid shouldGenerateStatementsOfCorrectType() {\n\n\t\tStatement statement = Cypher.returning(Cypher.literalTrue().as(\"t\")).build();\n\t\tassertThat(statement).isInstanceOf(ResultStatement.class).isInstanceOf(Statement.SingleQuery.class);\n\n\t\tstatement = Cypher.match(BIKE_NODE, USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t.set(BIKE_NODE.property(\"x\").to(Cypher.literalTrue()))\n\t\t\t.build();\n\t\tassertThat(statement).isNotInstanceOf(ResultStatement.class).isInstanceOf(Statement.SingleQuery.class);\n\n\t\tstatement = Cypher.match(BIKE_NODE, USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t.set(BIKE_NODE.property(\"x\").to(Cypher.literalTrue()))\n\t\t\t.with(BIKE_NODE)\n\t\t\t.returning(BIKE_NODE)\n\t\t\t.build();\n\t\tassertThat(statement).isInstanceOf(ResultStatement.class).isInstanceOf(MultiPartQuery.class);\n\t}\n\n\t@Nested\n\tclass PathMatchingAndAssignment {\n\n\t\tprivate final Renderer renderer = Renderer\n\t\t\t.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).build());\n\n\t\tprivate final PatternElement stationsPattern = Cypher.node(\"Station\")\n\t\t\t.named(\"wos\")\n\t\t\t.relationshipBetween(Cypher.node(\"Station\").named(\"bmv\"), \"LINK\")\n\t\t\t.quantifyRelationship(QuantifiedPathPattern.plus());\n\n\t\tprivate final AliasedExpression stops = Cypher.listWith(Cypher.name(\"n\"))\n\t\t\t.in(Cypher.nodes(Cypher.path(\"p\").get()))\n\t\t\t.returning(Cypher.property(\"n\", \"name\"))\n\t\t\t.as(\"stops\");\n\n\t\t@Test\n\t\tvoid plain() {\n\t\t\tvar pattern = Cypher.node(\"Station\").relationshipTo(Cypher.node(\"Station\").named(\"b\"), \"LINK\").named(\"l\");\n\t\t\tvar statement = Cypher.match(Cypher.path(\"p\").definedBy(pattern)).returning(Cypher.name(\"p\")).build();\n\t\t\tassertThat(statement.getCypher()).isEqualTo(\"MATCH p = (:`Station`)-[l:`LINK`]->(b:`Station`) RETURN p\");\n\t\t}\n\n\t\t@Test\n\t\tvoid deprecatedShortest() {\n\t\t\tvar pattern = Cypher.node(\"Station\").relationshipTo(Cypher.node(\"Station\").named(\"b\"), \"LINK\").named(\"l\");\n\t\t\tvar statement = Cypher.match(Cypher.anyShortest().named(\"p\").definedBy(pattern))\n\t\t\t\t.returning(Cypher.name(\"p\"))\n\t\t\t\t.build();\n\t\t\tassertThat(statement.getCypher())\n\t\t\t\t.isEqualTo(\"MATCH p = ANY (:`Station`)-[l:`LINK`]->(b:`Station`) RETURN p\");\n\t\t}\n\n\t\t@ParameterizedTest\n\t\t@ValueSource(ints = { -1, 0, 1, 5 })\n\t\tvoid shortestK(int k) {\n\n\t\t\tif (k <= 0) {\n\t\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.shortestK(k))\n\t\t\t\t\t.withMessage(\"The path count needs to be greater than 0.\");\n\t\t\t}\n\t\t\telse {\n\t\t\t\tvar statement = Cypher.match(Cypher.shortestK(k).named(\"p\").definedBy(this.stationsPattern))\n\t\t\t\t\t.where(Cypher.property(\"wos\", \"name\").isEqualTo(Cypher.literalOf(\"Worcester Shrub Hill\")))\n\t\t\t\t\t.and(Cypher.property(\"bmv\", \"name\").isEqualTo(Cypher.literalOf(\"Bromsgrove\")))\n\t\t\t\t\t.returning(Cypher.length(Cypher.path(\"p\").get()).as(\"result\"))\n\t\t\t\t\t.build();\n\t\t\t\tassertThat(this.renderer.render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH p = SHORTEST %d (wos:Station)-[:LINK]-+(bmv:Station) WHERE (wos.name = 'Worcester Shrub Hill' AND bmv.name = 'Bromsgrove') RETURN length(p) AS result\",\n\t\t\t\t\t\tk);\n\t\t\t}\n\t\t}\n\n\t\t@ParameterizedTest\n\t\t@ValueSource(ints = { -1, 0, 1, 2 })\n\t\tvoid shortestKGroups(int k) {\n\n\t\t\tif (k <= 0) {\n\t\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.shortestK(k))\n\t\t\t\t\t.withMessage(\"The path count needs to be greater than 0.\");\n\t\t\t}\n\t\t\telse {\n\t\t\t\tvar statement = Cypher.match(Cypher.shortestKGroups(k).named(\"p\").definedBy(this.stationsPattern))\n\t\t\t\t\t.where(Cypher.property(\"wos\", \"name\").isEqualTo(Cypher.literalOf(\"Worcester Shrub Hill\")))\n\t\t\t\t\t.and(Cypher.property(\"bmv\", \"name\").isEqualTo(Cypher.literalOf(\"Bromsgrove\")))\n\t\t\t\t\t.returning(this.stops, Cypher.length(Cypher.path(\"p\").get()).as(\"pathLength\"))\n\t\t\t\t\t.build();\n\t\t\t\tassertThat(this.renderer.render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH p = SHORTEST %d GROUPS (wos:Station)-[:LINK]-+(bmv:Station) WHERE (wos.name = 'Worcester Shrub Hill' AND bmv.name = 'Bromsgrove') RETURN [n IN nodes(p) | n.name] AS stops, length(p) AS pathLength\",\n\t\t\t\t\t\tk);\n\t\t\t}\n\t\t}\n\n\t\t@Test\n\t\tvoid allShortest() {\n\t\t\tvar statement = Cypher.match(Cypher.allShortest().named(\"p\").definedBy(this.stationsPattern))\n\t\t\t\t.where(Cypher.property(\"wos\", \"name\").isEqualTo(Cypher.literalOf(\"Worcester Shrub Hill\")))\n\t\t\t\t.and(Cypher.property(\"bmv\", \"name\").isEqualTo(Cypher.literalOf(\"Bromsgrove\")))\n\t\t\t\t.returning(this.stops)\n\t\t\t\t.build();\n\t\t\tassertThat(this.renderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH p = ALL SHORTEST (wos:Station)-[:LINK]-+(bmv:Station) WHERE (wos.name = 'Worcester Shrub Hill' AND bmv.name = 'Bromsgrove') RETURN [n IN nodes(p) | n.name] AS stops\");\n\t\t}\n\n\t\t@Test\n\t\tvoid anyShortest() {\n\t\t\tvar pattern = Cypher.node(\"Station\")\n\t\t\t\t.withProperties(\"name\", Cypher.literalOf(\"Pershore\"))\n\t\t\t\t.relationshipBetween(\n\t\t\t\t\t\tCypher.node(\"Station\").named(\"b\").withProperties(\"name\", Cypher.literalOf(\"Bromsgrove\")),\n\t\t\t\t\t\t\"LINK\")\n\t\t\t\t.named(\"l\")\n\t\t\t\t.quantifyRelationship(QuantifiedPathPattern.plus())\n\t\t\t\t.where(Cypher.property(\"l\", \"distance\").lt(Cypher.literalOf(10)));\n\n\t\t\tvar distances = Cypher.listWith(Cypher.name(\"r\"))\n\t\t\t\t.in(Cypher.relationships(Cypher.path(\"path\").get()))\n\t\t\t\t.returning(Cypher.property(\"r\", \"distance\"))\n\t\t\t\t.as(\"distances\");\n\n\t\t\tvar statement = Cypher.match(Cypher.anyShortest().named(\"path\").definedBy(pattern))\n\t\t\t\t.returning(distances)\n\t\t\t\t.build();\n\n\t\t\tassertThat(this.renderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH path = ANY (:Station {name: 'Pershore'})-[l:LINK WHERE l.distance < 10]-+(b:Station {name: 'Bromsgrove'}) RETURN [r IN relationships(path) | r.distance] AS distances\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass SingleQuerySinglePart {\n\n\t\t@Nested\n\t\tclass ReadingAndReturn {\n\n\t\t\t@Test\n\t\t\tvoid unrelatedNodes() {\n\t\t\t\tStatement statement = Cypher.match(BIKE_NODE, USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (b:`Bike`), (u:`User`), (o:`U`) RETURN b, u\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid asteriskShouldWork() {\n\t\t\t\tStatement statement = Cypher.match(BIKE_NODE, USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (b:`Bike`), (u:`User`), (o:`U`) RETURN *\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid aliasedExpressionsInReturn() {\n\t\t\t\tNode unnamedNode = Cypher.node(\"ANode\");\n\t\t\t\tNode namedNode = Cypher.node(\"AnotherNode\").named(\"o\");\n\t\t\t\tStatement statement = Cypher.match(unnamedNode, namedNode)\n\t\t\t\t\t.returning(namedNode.as(\"theOtherNode\"))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (:`ANode`), (o:`AnotherNode`) RETURN o AS theOtherNode\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid simpleRelationship() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\"))\n\t\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[:`OWNS`]->(b:`Bike`) RETURN b, u\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid simpleRelationshipChainNamed() {\n\n\t\t\t\tfor (RelationshipChain chain : new RelationshipChain[] {\n\t\t\t\t\t\tUSER_NODE.relationshipTo(BIKE_NODE, \"OWNS\")\n\t\t\t\t\t\t\t.relationshipTo(Cypher.node(\"Brand\"), \"MADE_BY\")\n\t\t\t\t\t\t\t.named(SymbolicName.of(\"m\")),\n\t\t\t\t\t\tUSER_NODE.relationshipTo(BIKE_NODE, \"OWNS\")\n\t\t\t\t\t\t\t.relationshipTo(Cypher.node(\"Brand\"), \"MADE_BY\")\n\t\t\t\t\t\t\t.named(\"m\") }) {\n\t\t\t\t\tStatement statement = Cypher.match(chain).returning(BIKE_NODE, USER_NODE).build();\n\n\t\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[:`OWNS`]->(b:`Bike`)-[m:`MADE_BY`]->(:`Brand`) RETURN b, u\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Test // GH-169\n\t\t\tvoid multipleRelationshipTypes() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\", \"RIDES\"))\n\t\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[:`OWNS`|`RIDES`]->(b:`Bike`) RETURN b, u\");\n\t\t\t}\n\n\t\t\t@Test // GH-170\n\t\t\tvoid relationshipWithProperties() {\n\t\t\t\tStatement statement = Cypher\n\t\t\t\t\t.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\")\n\t\t\t\t\t\t.withProperties(Cypher.mapOf(\"boughtOn\", Cypher.literalOf(\"2019-04-16\"))))\n\t\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[:`OWNS` {boughtOn: '2019-04-16'}]->(b:`Bike`) RETURN b, u\");\n\t\t\t}\n\n\t\t\t@Test // GH-168\n\t\t\tvoid relationshipWithMinimumLength() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").min(3))\n\t\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[:`OWNS`*3..]->(b:`Bike`) RETURN b, u\");\n\t\t\t}\n\n\t\t\t@Test // GH-168\n\t\t\tvoid relationshipWithMaximumLength() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").max(5))\n\t\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[:`OWNS`*..5]->(b:`Bike`) RETURN b, u\");\n\t\t\t}\n\n\t\t\t@Test // GH-168\n\t\t\tvoid unboundedRelationship() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").unbounded())\n\t\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[:`OWNS`*]->(b:`Bike`) RETURN b, u\");\n\t\t\t}\n\n\t\t\t@Test // GH-168\n\t\t\tvoid relationshipWithLength() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").length(3, 5))\n\t\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[:`OWNS`*3..5]->(b:`Bike`) RETURN b, u\");\n\t\t\t}\n\n\t\t\t@Test // GH-168\n\t\t\tvoid relationshipWithLengthAndProperties() {\n\t\t\t\tStatement statement = Cypher\n\t\t\t\t\t.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\")\n\t\t\t\t\t\t.length(3, 5)\n\t\t\t\t\t\t.withProperties(Cypher.mapOf(\"boughtOn\", Cypher.literalOf(\"2019-04-16\"))))\n\t\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[:`OWNS`*3..5 {boughtOn: '2019-04-16'}]->(b:`Bike`) RETURN b, u\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid simpleRelationshipWithReturn() {\n\t\t\t\tRelationship owns = USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\");\n\n\t\t\t\tStatement statement = Cypher.match(owns).returning(BIKE_NODE, USER_NODE, owns).build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[o:`OWNS`]->(b:`Bike`) RETURN b, u, o\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid chainedRelations() {\n\t\t\t\tNode tripNode = Cypher.node(\"Trip\").named(\"t\");\n\t\t\t\tStatement statement = Cypher\n\t\t\t\t\t.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\")\n\t\t\t\t\t\t.named(\"r1\")\n\t\t\t\t\t\t.relationshipTo(tripNode, \"USED_ON\")\n\t\t\t\t\t\t.named(\"r2\"))\n\t\t\t\t\t.where(USER_NODE.property(\"name\").matches(\".*aName\"))\n\t\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH (u:`User`)-[r1:`OWNS`]->(b:`Bike`)-[r2:`USED_ON`]->(t:`Trip`) WHERE u.name =~ '.*aName' RETURN b, u\");\n\n\t\t\t\tstatement = Cypher\n\t\t\t\t\t.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").relationshipTo(tripNode, \"USED_ON\").named(\"r2\"))\n\t\t\t\t\t.where(USER_NODE.property(\"name\").matches(\".*aName\"))\n\t\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH (u:`User`)-[:`OWNS`]->(b:`Bike`)-[r2:`USED_ON`]->(t:`Trip`) WHERE u.name =~ '.*aName' RETURN b, u\");\n\n\t\t\t\tstatement = Cypher\n\t\t\t\t\t.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\")\n\t\t\t\t\t\t.relationshipTo(tripNode, \"USED_ON\")\n\t\t\t\t\t\t.named(\"r2\")\n\t\t\t\t\t\t.relationshipFrom(USER_NODE, \"WAS_ON\")\n\t\t\t\t\t\t.named(\"x\")\n\t\t\t\t\t\t.relationshipBetween(Cypher.node(\"SOMETHING\"))\n\t\t\t\t\t\t.named(\"y\"))\n\t\t\t\t\t.where(USER_NODE.property(\"name\").matches(\".*aName\"))\n\t\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH (u:`User`)-[:`OWNS`]->(b:`Bike`)-[r2:`USED_ON`]->(t:`Trip`)<-[x:`WAS_ON`]-(u)-[y]-(:`SOMETHING`) WHERE u.name =~ '.*aName' RETURN b, u\");\n\t\t\t}\n\n\t\t\t@Test // GH-177\n\t\t\tvoid chainedRelationshipsWithPropertiesAndLength() {\n\t\t\t\tNode tripNode = Cypher.node(\"Trip\").named(\"t\");\n\t\t\t\tStatement statement = Cypher\n\t\t\t\t\t.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\")\n\t\t\t\t\t\t.relationshipTo(tripNode, \"USED_ON\")\n\t\t\t\t\t\t.named(\"r2\")\n\t\t\t\t\t\t.min(1)\n\t\t\t\t\t\t.properties(Cypher.mapOf(\"when\", Cypher.literalOf(\"2019-04-16\")))\n\t\t\t\t\t\t.relationshipFrom(USER_NODE, \"WAS_ON\")\n\t\t\t\t\t\t.named(\"x\")\n\t\t\t\t\t\t.max(2)\n\t\t\t\t\t\t.properties(\"whatever\", Cypher.literalOf(\"2020-04-16\"))\n\t\t\t\t\t\t.relationshipBetween(Cypher.node(\"SOMETHING\"))\n\t\t\t\t\t\t.named(\"y\")\n\t\t\t\t\t\t.length(2, 3)\n\t\t\t\t\t\t.properties(Cypher.mapOf(\"idk\", Cypher.literalOf(\"2021-04-16\"))))\n\t\t\t\t\t.where(USER_NODE.property(\"name\").matches(\".*aName\"))\n\t\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH (u:`User`)-[:`OWNS`]->(b:`Bike`)-[r2:`USED_ON`*1.. {when: '2019-04-16'}]->(t:`Trip`)<-[x:`WAS_ON`*..2 {whatever: '2020-04-16'}]-(u)-[y*2..3 {idk: '2021-04-16'}]-(:`SOMETHING`) WHERE u.name =~ '.*aName' RETURN b, u\");\n\t\t\t}\n\n\t\t\t@Test // GH-182\n\t\t\tvoid sizeOfRelationship() {\n\n\t\t\t\tStatement statement = Cypher.match(Cypher.anyNode(\"a\"))\n\t\t\t\t\t.where(Cypher.property(\"a\", \"name\").isEqualTo(Cypher.literalOf(\"Alice\")))\n\t\t\t\t\t.returning(Cypher.size(Cypher.anyNode(\"a\").relationshipTo(Cypher.anyNode())).as(\"fof\"))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (a) WHERE a.name = 'Alice' RETURN size((a)-->()) AS fof\");\n\t\t\t}\n\n\t\t\t@Test // GH-182\n\t\t\tvoid sizeOfRelationshipChain() {\n\n\t\t\t\tStatement statement = Cypher.match(Cypher.anyNode(\"a\"))\n\t\t\t\t\t.where(Cypher.property(\"a\", \"name\").isEqualTo(Cypher.literalOf(\"Alice\")))\n\t\t\t\t\t.returning(Cypher\n\t\t\t\t\t\t.size(Cypher.anyNode(\"a\").relationshipTo(Cypher.anyNode()).relationshipTo(Cypher.anyNode()))\n\t\t\t\t\t\t.as(\"fof\"))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (a) WHERE a.name = 'Alice' RETURN size((a)-->()-->()) AS fof\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid sortOrderDefault() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t\t.returning(USER_NODE)\n\t\t\t\t\t.orderBy(Cypher.sort(USER_NODE.property(\"name\")))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN u ORDER BY u.name\");\n\t\t\t}\n\n\t\t\t@Test // GH-189\n\t\t\tvoid sortOrderDefaultBasedOnSortItemCollection() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t\t.returning(USER_NODE)\n\t\t\t\t\t.orderBy(Collections.singleton(Cypher.sort(USER_NODE.property(\"name\"))))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN u ORDER BY u.name\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid sortOrderAscending() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t\t.returning(USER_NODE)\n\t\t\t\t\t.orderBy(Cypher.sort(USER_NODE.property(\"name\")).ascending())\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN u ORDER BY u.name ASC\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid sortOrderDescending() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t\t.returning(USER_NODE)\n\t\t\t\t\t.orderBy(Cypher.sort(USER_NODE.property(\"name\")).descending())\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`) RETURN u ORDER BY u.name DESC\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid sortOrderConcatenation() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t\t.returning(USER_NODE)\n\t\t\t\t\t.orderBy(Cypher.sort(USER_NODE.property(\"name\")).descending(),\n\t\t\t\t\t\t\tCypher.sort(USER_NODE.property(\"age\")).ascending())\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`) RETURN u ORDER BY u.name DESC, u.age ASC\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid sortOrderDefaultExpression() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t\t.returning(USER_NODE)\n\t\t\t\t\t.orderBy(USER_NODE.property(\"name\"))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN u ORDER BY u.name\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid sortOrderAscendingExpression() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t\t.returning(USER_NODE)\n\t\t\t\t\t.orderBy(USER_NODE.property(\"name\").ascending())\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN u ORDER BY u.name ASC\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid sortOrderDescendingExpression() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t\t.returning(USER_NODE)\n\t\t\t\t\t.orderBy(USER_NODE.property(\"name\").descending())\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`) RETURN u ORDER BY u.name DESC\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid sortOrderConcatenationExpression() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t\t.returning(USER_NODE)\n\t\t\t\t\t.orderBy(USER_NODE.property(\"name\"))\n\t\t\t\t\t.descending()\n\t\t\t\t\t.and(USER_NODE.property(\"age\"))\n\t\t\t\t\t.ascending()\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`) RETURN u ORDER BY u.name DESC, u.age ASC\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid skip() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE).returning(USER_NODE).skip(1).build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN u SKIP 1\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid nullSkip() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE).returning(USER_NODE).skip((Number) null).build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN u\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid limit() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE).returning(USER_NODE).limit(1).build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN u LIMIT 1\");\n\t\t\t}\n\n\t\t\t@Test // GH-129\n\t\t\tvoid limitWithParams() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t\t.returning(USER_NODE)\n\t\t\t\t\t.limit(Cypher.parameter(\"param\"))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN u LIMIT $param\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid nullLimit() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE).returning(USER_NODE).limit((Number) null).build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN u\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid skipAndLimit() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE).returning(USER_NODE).skip(1).limit(1).build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN u SKIP 1 LIMIT 1\");\n\t\t\t}\n\n\t\t\t@Test // GH-129\n\t\t\tvoid skipAndLimitWithParams() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t\t.returning(USER_NODE)\n\t\t\t\t\t.skip(Cypher.parameter(\"skip\"))\n\t\t\t\t\t.limit(Cypher.parameter(\"limit\"))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (u:`User`) RETURN u SKIP $skip LIMIT $limit\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid nullSkipAndLimit() {\n\t\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t\t.returning(USER_NODE)\n\t\t\t\t\t.skip((Number) null)\n\t\t\t\t\t.limit((Number) null)\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN u\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid distinct() {\n\t\t\t\tString expected = \"MATCH (u:`User`) RETURN DISTINCT u SKIP 1 LIMIT 1\";\n\n\t\t\t\tStatement statement = Cypher.match(USER_NODE).returningDistinct(USER_NODE).skip(1).limit(1).build();\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\t\tstatement = Cypher.match(USER_NODE).returningDistinct(\"u\").skip(1).limit(1).build();\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass Finish {\n\n\t\t@Test\n\t\tvoid finishAfterMatch() {\n\t\t\tString expected = \"MATCH (u:`User`) FINISH\";\n\n\t\t\tStatement statement = Cypher.match(USER_NODE).finish().build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t}\n\n\t\t@Test\n\t\tvoid finishAfterMatchWithWhere() {\n\t\t\tString expected = \"MATCH (u:`User`) WHERE u:`User` FINISH\";\n\n\t\t\tStatement statement = Cypher.match(USER_NODE).where(USER_NODE.hasLabels(\"User\")).finish().build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t}\n\n\t\t@Test\n\t\tvoid finishAfterSet() {\n\t\t\tString expected = \"MATCH (u:`User`) SET u.name = 'hans' FINISH\";\n\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.set(USER_NODE.property(\"name\").to(Cypher.literalOf(\"hans\")))\n\t\t\t\t.finish()\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t}\n\n\t\t@Test\n\t\tvoid finishAfterDelete() {\n\t\t\tString expected = \"MATCH (u:`User`) DELETE u FINISH\";\n\n\t\t\tStatement statement = Cypher.match(USER_NODE).delete(USER_NODE).finish().build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t}\n\n\t\t@Test\n\t\tvoid finishAfterCreate() {\n\t\t\tString expected = \"CREATE (u:`User`) FINISH\";\n\n\t\t\tStatement statement = Cypher.create(USER_NODE).finish().build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t}\n\n\t\t@Test\n\t\tvoid finishAfterMerge() {\n\t\t\tString expected = \"MERGE (u:`User`)-[:`KNOWS`]->(u) FINISH\";\n\n\t\t\tStatement statement = Cypher.merge(USER_NODE.relationshipTo(USER_NODE, \"KNOWS\")).finish().build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass ExplainedAndProfiledQueries {\n\n\t\t@Test // GH-98\n\t\tvoid shouldRenderExplain() {\n\n\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.with(BIKE_NODE, USER_NODE)\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.explain();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"EXPLAIN MATCH (u:`User`)-[:`OWNS`]->(b:`Bike`) WHERE u.a IS NULL WITH b, u RETURN b\");\n\t\t}\n\n\t\t@Test // GH-99\n\t\tvoid shouldRenderProfile() {\n\n\t\t\tNode tripNode = Cypher.node(\"Trip\").named(\"tt\");\n\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.with(BIKE_NODE, USER_NODE)\n\t\t\t\t.match(tripNode)\n\t\t\t\t.where(tripNode.property(\"name\").isEqualTo(Cypher.literalOf(\"Festive500\")))\n\t\t\t\t.with(BIKE_NODE, USER_NODE, tripNode)\n\t\t\t\t.returning(BIKE_NODE, USER_NODE, tripNode)\n\t\t\t\t.profile();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"PROFILE MATCH (u:`User`)-[:`OWNS`]->(b:`Bike`) WHERE u.a IS NULL WITH b, u MATCH (tt:`Trip`) WHERE tt.name = 'Festive500' WITH b, u, tt RETURN b, u, tt\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass SingleQueryMultiPart {\n\n\t\t@Test\n\t\tvoid simpleWith() {\n\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.with(BIKE_NODE, USER_NODE)\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[:`OWNS`]->(b:`Bike`) WHERE u.a IS NULL WITH b, u RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderLeadingWith() {\n\t\t\tStatement statement = Cypher.with(Cypher.parameter(\"listOfPropertyMaps\").as(\"p\"))\n\t\t\t\t.unwind(\"p\")\n\t\t\t\t.as(\"item\")\n\t\t\t\t.returning(\"item\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"WITH $listOfPropertyMaps AS p UNWIND p AS item RETURN item\");\n\t\t}\n\n\t\t@Test // GH-189\n\t\tvoid shouldRenderLeadingWithBasedOnExpression() {\n\t\t\tStatement statement = Cypher.with(Collections.singleton(Cypher.parameter(\"listOfPropertyMaps\").as(\"p\")))\n\t\t\t\t.unwind(\"p\")\n\t\t\t\t.as(\"item\")\n\t\t\t\t.returning(\"item\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"WITH $listOfPropertyMaps AS p UNWIND p AS item RETURN item\");\n\t\t}\n\n\t\t@Test // GH-129\n\t\tvoid withWithSkip() {\n\t\t\tNode m = Cypher.node(\"Movie\").named(\"m\");\n\t\t\tStatement statement = Cypher.match(m).with(m).skip(1).returning(Cypher.count(m)).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (m:`Movie`) WITH m SKIP 1 RETURN count(m)\");\n\n\t\t\tstatement = Cypher.match(m).with(m).skip(Cypher.parameter(\"skip\")).returning(Cypher.count(m)).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (m:`Movie`) WITH m SKIP $skip RETURN count(m)\");\n\t\t}\n\n\t\t@Test // GH-129\n\t\tvoid withWithLimit() {\n\t\t\tNode m = Cypher.node(\"Movie\").named(\"m\");\n\t\t\tStatement statement = Cypher.match(m).with(m).limit(23).returning(Cypher.count(m)).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (m:`Movie`) WITH m LIMIT 23 RETURN count(m)\");\n\n\t\t\tstatement = Cypher.match(m).with(m).limit(Cypher.parameter(\"limit\")).returning(Cypher.count(m)).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (m:`Movie`) WITH m LIMIT $limit RETURN count(m)\");\n\t\t}\n\n\t\t@Test // GH-129\n\t\tvoid withWithSkipAndLimit() {\n\t\t\tNode m = Cypher.node(\"Movie\").named(\"m\");\n\t\t\tStatement statement = Cypher.match(m).with(m).skip(1).limit(23).returning(Cypher.count(m)).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (m:`Movie`) WITH m SKIP 1 LIMIT 23 RETURN count(m)\");\n\n\t\t\tstatement = Cypher.match(m)\n\t\t\t\t.with(m)\n\t\t\t\t.skip(Cypher.parameter(\"skip\"))\n\t\t\t\t.limit(Cypher.parameter(\"limit\"))\n\t\t\t\t.returning(Cypher.count(m))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (m:`Movie`) WITH m SKIP $skip LIMIT $limit RETURN count(m)\");\n\t\t}\n\n\t\t@Test // GH-129\n\t\tvoid withWithAndNullsForSkipAndLimit() {\n\t\t\tNode m = Cypher.node(\"Movie\").named(\"m\");\n\t\t\tStatement statement = Cypher.match(m)\n\t\t\t\t.with(m)\n\t\t\t\t.skip((Number) null)\n\t\t\t\t.limit((Number) null)\n\t\t\t\t.returning(Cypher.count(m))\n\t\t\t\t.build();\n\n\t\t\tString expected = \"MATCH (m:`Movie`) WITH m RETURN count(m)\";\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\tstatement = Cypher.match(m)\n\t\t\t\t.with(m)\n\t\t\t\t.skip((Expression) null)\n\t\t\t\t.limit((Expression) null)\n\t\t\t\t.returning(Cypher.count(m))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t}\n\n\t\t@Test\n\t\tvoid simpleWithChained() {\n\n\t\t\tNode tripNode = Cypher.node(\"Trip\").named(\"t\");\n\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.with(BIKE_NODE, USER_NODE)\n\t\t\t\t.match(tripNode)\n\t\t\t\t.where(tripNode.property(\"name\").isEqualTo(Cypher.literalOf(\"Festive500\")))\n\t\t\t\t.with(BIKE_NODE, USER_NODE, tripNode)\n\t\t\t\t.returning(BIKE_NODE, USER_NODE, tripNode)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`)-[:`OWNS`]->(b:`Bike`) WHERE u.a IS NULL WITH b, u MATCH (t:`Trip`) WHERE t.name = 'Festive500' WITH b, u, t RETURN b, u, t\");\n\t\t}\n\n\t\t@Test\n\t\tvoid deletingSimpleWith() {\n\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.delete(USER_NODE)\n\t\t\t\t.with(BIKE_NODE, USER_NODE)\n\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[:`OWNS`]->(b:`Bike`) WHERE u.a IS NULL DELETE u WITH b, u RETURN b, u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid deletingSimpleWithReverse() {\n\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.with(BIKE_NODE, USER_NODE)\n\t\t\t\t.delete(USER_NODE)\n\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[:`OWNS`]->(b:`Bike`) WHERE u.a IS NULL WITH b, u DELETE u RETURN b, u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid mixedClausesWithWith() {\n\n\t\t\tNode tripNode = Cypher.node(\"Trip\").named(\"t\");\n\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\"))\n\t\t\t\t.match(tripNode)\n\t\t\t\t.delete(tripNode)\n\t\t\t\t.with(BIKE_NODE, tripNode)\n\t\t\t\t.match(USER_NODE)\n\t\t\t\t.with(BIKE_NODE, USER_NODE)\n\t\t\t\t.returning(BIKE_NODE, USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`)-[:`OWNS`]->(b:`Bike`) MATCH (t:`Trip`) DELETE t WITH b, t MATCH (u:`User`) WITH b, u RETURN b, u\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass MultipleMatches {\n\n\t\t@Test\n\t\tvoid simple() {\n\t\t\tStatement statement = Cypher.match(BIKE_NODE)\n\t\t\t\t.match(USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (b:`Bike`) MATCH (u:`User`), (o:`U`) RETURN b\");\n\t\t}\n\n\t\t@Test // GH-189\n\t\tvoid simpleWithPatternCollection() {\n\t\t\tStatement statement = Cypher.match(Collections.singleton(BIKE_NODE))\n\t\t\t\t.match(USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (b:`Bike`) MATCH (u:`User`), (o:`U`) RETURN b\");\n\t\t}\n\n\t\t@Test // GH-189\n\t\tvoid simpleWithPatternCollectionInExposesMatch() {\n\t\t\tPatternElement[] patternElements = { USER_NODE, Cypher.node(\"U\").named(\"o\") };\n\t\t\tStatement statement = Cypher.match(Collections.singleton(BIKE_NODE))\n\t\t\t\t.match(Arrays.asList(patternElements))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (b:`Bike`) MATCH (u:`User`), (o:`U`) RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid simpleWhere() {\n\t\t\tStatement statement = Cypher.match(BIKE_NODE)\n\t\t\t\t.match(USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (b:`Bike`) MATCH (u:`User`), (o:`U`) WHERE u.a IS NULL RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid multiWhere() {\n\t\t\tStatement statement = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"a\").isNotNull())\n\t\t\t\t.match(USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (b:`Bike`) WHERE b.a IS NOT NULL MATCH (u:`User`), (o:`U`) WHERE u.a IS NULL RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\t@SuppressWarnings(\"deprecation\")\n\t\tvoid multiWhereMultiConditions() {\n\t\t\tStatement statement = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"a\").isNotNull())\n\t\t\t\t.and(BIKE_NODE.property(\"b\").isNull())\n\t\t\t\t.match(USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull().or(USER_NODE.internalId().isEqualTo(Cypher.literalOf(4711))))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (b:`Bike`) WHERE (b.a IS NOT NULL AND b.b IS NULL) MATCH (u:`User`), (o:`U`) WHERE (u.a IS NULL OR id(u) = 4711) RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid optional() {\n\t\t\tStatement statement = Cypher.optionalMatch(BIKE_NODE)\n\t\t\t\t.match(USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"OPTIONAL MATCH (b:`Bike`) MATCH (u:`User`), (o:`U`) WHERE u.a IS NULL RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid optionalWithFlag() {\n\t\t\tStatement statement = Cypher.match(true, BIKE_NODE)\n\t\t\t\t.match(USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"OPTIONAL MATCH (b:`Bike`) MATCH (u:`User`), (o:`U`) WHERE u.a IS NULL RETURN b\");\n\t\t}\n\n\t\t@Test // GH-189\n\t\tvoid optionalWithFlagAndPatternCollection() {\n\t\t\tStatement statement = Cypher.match(true, Collections.singleton(BIKE_NODE))\n\t\t\t\t.match(USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"OPTIONAL MATCH (b:`Bike`) MATCH (u:`User`), (o:`U`) WHERE u.a IS NULL RETURN b\");\n\t\t}\n\n\t\t@Test // GH-189\n\t\tvoid optionalWithPatternCollection() {\n\t\t\tStatement statement = Cypher.optionalMatch(Collections.singleton(BIKE_NODE))\n\t\t\t\t.match(USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"OPTIONAL MATCH (b:`Bike`) MATCH (u:`User`), (o:`U`) WHERE u.a IS NULL RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\t@SuppressWarnings({ \"ResultOfMethodCallIgnored\" }) // That is the purpose of this\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// test\n\t\tvoid usingSameWithStepWithoutReassign() {\n\t\t\tStatementBuilder.OrderableOngoingReadingAndWith firstStep = Cypher.match(BIKE_NODE).with(BIKE_NODE);\n\n\t\t\tfirstStep.optionalMatch(USER_NODE);\n\t\t\tfirstStep.optionalMatch(Cypher.node(\"Trip\"));\n\n\t\t\tStatement statement = firstStep.returning(Cypher.asterisk()).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (b:`Bike`) WITH b OPTIONAL MATCH (u:`User`) OPTIONAL MATCH (:`Trip`) RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\t@SuppressWarnings({ \"ResultOfMethodCallIgnored\" }) // That is the purpose of this\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// test\n\t\tvoid usingSameWithStepWithoutReassignThenUpdate() {\n\t\t\tStatementBuilder.OrderableOngoingReadingAndWith firstStep = Cypher.match(BIKE_NODE).with(BIKE_NODE);\n\n\t\t\tfirstStep.optionalMatch(USER_NODE);\n\t\t\tfirstStep.optionalMatch(Cypher.node(\"Trip\"));\n\t\t\tfirstStep.delete(\"u\");\n\n\t\t\tStatement statement = firstStep.returning(Cypher.asterisk()).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (b:`Bike`) WITH b OPTIONAL MATCH (u:`User`) OPTIONAL MATCH (:`Trip`) DELETE u RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid usingSameWithStepWithReassign() {\n\t\t\tExposesMatch firstStep = Cypher.match(BIKE_NODE).with(BIKE_NODE);\n\n\t\t\tfirstStep = firstStep.optionalMatch(USER_NODE);\n\t\t\tfirstStep = firstStep.optionalMatch(Cypher.node(\"Trip\"));\n\n\t\t\tStatement statement = ((ExposesReturning) firstStep).returning(Cypher.asterisk()).build();\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (b:`Bike`) WITH b OPTIONAL MATCH (u:`User`) OPTIONAL MATCH (:`Trip`) RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid queryPartsShouldBeExtractableInQueries() {\n\n\t\t\t// THose can be a couple of queries ending in a WITH statement so the\n\t\t\t// pipeline they present in the full query is also present in Java.\n\t\t\tFunction<ExposesMatch, ExposesMatch> step1Supplier = previous -> previous\n\t\t\t\t.match(Cypher.node(\"S1\").named(\"n\"))\n\t\t\t\t.where(Cypher.property(\"n\", \"a\").isEqualTo(Cypher.literalOf(\"A\")))\n\t\t\t\t.with(\"n\");\n\t\t\tFunction<ExposesMatch, ExposesReturning> step2Supplier = previous -> previous\n\t\t\t\t.match(Cypher.anyNode(\"n\").relationshipTo(Cypher.node(\"S2\").named(\"m\"), \"SOMEHOW_RELATED\"))\n\t\t\t\t.with(\"n\", \"m\");\n\n\t\t\tStatement statement = step1Supplier.andThen(step2Supplier)\n\t\t\t\t.apply(Statement.builder())\n\t\t\t\t.returning(\"n\", \"m\")\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n:`S1`) WHERE n.a = 'A' WITH n MATCH (n)-[:`SOMEHOW_RELATED`]->(m:`S2`) WITH n, m RETURN n, m\");\n\t\t}\n\n\t\t@Test\n\t\tvoid optionalNext() {\n\t\t\tStatement statement = Cypher.match(BIKE_NODE)\n\t\t\t\t.optionalMatch(USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (b:`Bike`) OPTIONAL MATCH (u:`User`), (o:`U`) WHERE u.a IS NULL RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid optionalNextBasedOnPatternElementCollection() {\n\t\t\tPatternElement[] patternElements = { USER_NODE, Cypher.node(\"U\").named(\"o\") };\n\t\t\tStatement statement = Cypher.match(BIKE_NODE)\n\t\t\t\t.optionalMatch(Arrays.asList(patternElements))\n\t\t\t\t.where(USER_NODE.property(\"a\").isNull())\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (b:`Bike`) OPTIONAL MATCH (u:`User`), (o:`U`) WHERE u.a IS NULL RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid optionalMatchThenDelete() {\n\t\t\tStatement statement = Cypher.match(BIKE_NODE)\n\t\t\t\t.optionalMatch(USER_NODE, Cypher.node(\"U\").named(\"o\"))\n\t\t\t\t.delete(USER_NODE, BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (b:`Bike`) OPTIONAL MATCH (u:`User`), (o:`U`) DELETE u, b\");\n\t\t}\n\n\t}\n\n\t@Nested\n\t@SuppressWarnings(\"deprecation\")\n\tclass FunctionRendering {\n\n\t\t@Test\n\t\tvoid inWhereClause() {\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.internalId().isEqualTo(Cypher.literalOf(1L)))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) WHERE id(u) = 1 RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid inReturnClause() {\n\t\t\tStatement statement = Cypher.match(USER_NODE).returning(Cypher.count(USER_NODE)).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN count(u)\");\n\t\t}\n\n\t\t@Test // GH-195\n\t\tvoid inReturnClauseBasedOnExpressionCollection() {\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.returning(Collections.singleton(Cypher.count(USER_NODE)))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN count(u)\");\n\t\t}\n\n\t\t@Test // GH-195\n\t\tvoid inDistinctReturnClauseBasedOnExpressionCollection() {\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.returningDistinct(Collections.singleton(Cypher.count(USER_NODE)))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN DISTINCT count(u)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid inReturnClauseWithDistinct() {\n\t\t\tStatement statement = Cypher.match(USER_NODE).returning(Cypher.countDistinct(USER_NODE)).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN count(DISTINCT u)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid aliasedInReturnClause() {\n\t\t\tStatement statement = Cypher.match(USER_NODE).returning(Cypher.count(USER_NODE).as(\"cnt\")).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN count(u) AS cnt\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldSupportMoreThanOneArgument() {\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.returning(Cypher.coalesce(USER_NODE.property(\"a\"), USER_NODE.property(\"b\"),\n\t\t\t\t\t\tCypher.literalOf(\"¯\\\\_(ツ)_/¯\")))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) RETURN coalesce(u.a, u.b, '¯\\\\\\\\_(ツ)_/¯')\");\n\t\t}\n\n\t\t@Test\n\t\tvoid literalsShouldDealWithNull() {\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.returning(Cypher.coalesce(Cypher.literalOf(null), USER_NODE.property(\"field\")).as(\"p\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) RETURN coalesce(NULL, u.field) AS p\");\n\t\t}\n\n\t\t@Test // GH-257\n\t\tvoid functionsBasedOnRelationships() {\n\t\t\tString expected = \"MATCH p = ANY (bacon:`Person` {name: 'Kevin Bacon'})-[*]-(meg:`Person` {name: 'Meg Ryan'}) RETURN p\";\n\n\t\t\tRelationship relationship = Cypher.node(\"Person\")\n\t\t\t\t.named(\"bacon\")\n\t\t\t\t.withProperties(\"name\", Cypher.literalOf(\"Kevin Bacon\"))\n\t\t\t\t.relationshipBetween(\n\t\t\t\t\t\tCypher.node(\"Person\").named(\"meg\").withProperties(\"name\", Cypher.literalOf(\"Meg Ryan\")))\n\t\t\t\t.unbounded();\n\t\t\tStatement statement = Cypher.match(Cypher.anyShortest().named(\"p\").definedBy(relationship))\n\t\t\t\t.returning(\"p\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\tSymbolicName p = Cypher.name(\"p\");\n\t\t\tstatement = Cypher.match(Cypher.anyShortest().named(p).definedBy(relationship)).returning(p).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass ComparisonRendering {\n\n\t\t@Test\n\t\tvoid equalsWithStringLiteral() {\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isEqualTo(Cypher.literalOf(\"Test\")))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) WHERE u.name = 'Test' RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid equalsWithNumberLiteral() {\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"age\").isEqualTo(Cypher.literalOf(21)))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) WHERE u.age = 21 RETURN u\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass Conditions {\n\n\t\t@Test\n\t\tvoid conditionsChainingAnd() {\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\")\n\t\t\t\t\t.isEqualTo(Cypher.literalOf(\"Test\"))\n\t\t\t\t\t.and(USER_NODE.property(\"age\").isEqualTo(Cypher.literalOf(21))))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE (u.name = 'Test' AND u.age = 21) RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid conditionsChainingOr() {\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\")\n\t\t\t\t\t.isEqualTo(Cypher.literalOf(\"Test\"))\n\t\t\t\t\t.or(USER_NODE.property(\"age\").isEqualTo(Cypher.literalOf(21))))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE (u.name = 'Test' OR u.age = 21) RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid includesAllShouldWork() {\n\n\t\t\tNode node = Cypher.anyNode().named(\"n\");\n\t\t\tStatement statement = Cypher.match(node)\n\t\t\t\t.where(Cypher.includesAll(node.property(\"l\"), Cypher.literalOf(new String[] { \"A\", \"B\" })))\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tStatement statement2 = Cypher.match(node)\n\t\t\t\t.where(node.property(\"l\").includesAll(Cypher.literalOf(new String[] { \"A\", \"B\" })))\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(statement.getCypher()).isEqualTo(\"MATCH (n) WHERE all(x IN ['A', 'B'] WHERE x IN n.l) RETURN n\");\n\t\t\tassertThat(statement2.getCypher()).isEqualTo(statement.getCypher());\n\t\t}\n\n\t\t@Test\n\t\tvoid includesAnyShouldWork() {\n\n\t\t\tNode node = Cypher.anyNode().named(\"n\");\n\t\t\tStatement statement = Cypher.match(node)\n\t\t\t\t.where(Cypher.includesAny(node.property(\"l\"), Cypher.literalOf(new String[] { \"A\", \"B\" })))\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tStatement statement2 = Cypher.match(node)\n\t\t\t\t.where(node.property(\"l\").includesAny(Cypher.literalOf(new String[] { \"A\", \"B\" })))\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(statement.getCypher()).isEqualTo(\"MATCH (n) WHERE any(x IN ['A', 'B'] WHERE x IN n.l) RETURN n\");\n\t\t\tassertThat(statement2.getCypher()).isEqualTo(statement.getCypher());\n\t\t}\n\n\t\t@Test\n\t\tvoid nestedConditions() {\n\t\t\tStatement statement;\n\n\t\t\tCondition isTrue = Cypher.isTrue();\n\t\t\tCondition isFalse = Cypher.isFalse();\n\t\t\tstatement = Cypher.match(USER_NODE).where(isTrue.or(isFalse).and(isTrue)).returning(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE ((true OR false) AND true) RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(isTrue.or(isFalse).and(isTrue))\n\t\t\t\t.or(isFalse)\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE (((true OR false) AND true) OR false) RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(isTrue.or(isFalse).and(isTrue))\n\t\t\t\t.or(isFalse)\n\t\t\t\t.and(isFalse)\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE ((((true OR false) AND true) OR false) AND false) RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(isTrue.or(isFalse).and(isTrue))\n\t\t\t\t.or(isFalse.and(isTrue))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE (((true OR false) AND true) OR (false AND true)) RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(isTrue.or(isFalse).and(isTrue))\n\t\t\t\t.or(isFalse.and(isTrue))\n\t\t\t\t.and(isTrue)\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) WHERE ((((true OR false) AND true) OR (false AND true)) AND true) RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(isTrue.or(isFalse).and(isTrue))\n\t\t\t\t.or(isFalse.or(isTrue))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE (((true OR false) AND true) OR false OR true) RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(isTrue.or(isFalse).and(isTrue).or(isFalse.or(isTrue)))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE (((true OR false) AND true) OR false OR true) RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(isTrue.or(isTrue).or(isTrue))\n\t\t\t\t.or(isFalse.or(isFalse).or(isFalse))\n\t\t\t\t.or(isTrue)\n\t\t\t\t.or(isTrue)\n\t\t\t\t.or(isTrue)\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) WHERE (true OR true OR true OR false OR false OR false OR true OR true OR true) RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid conditionsChainingXor() {\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\")\n\t\t\t\t\t.isEqualTo(Cypher.literalOf(\"Test\"))\n\t\t\t\t\t.xor(USER_NODE.property(\"age\").isEqualTo(Cypher.literalOf(21))))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE (u.name = 'Test' XOR u.age = 21) RETURN u\");\n\t\t}\n\n\t\t@Test // GH-110\n\t\tvoid multipleEmptyConditionsMustCollapse() {\n\n\t\t\tvar no = Cypher.noCondition();\n\t\t\tString expected = \"MATCH (u:`User`) RETURN u\";\n\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(USER_NODE).where(no.or(no)).and(no.and(no).or(no)).returning(USER_NODE).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\tstatement = Cypher.match(USER_NODE).where(no.or(no)).returning(USER_NODE).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\tstatement = Cypher.match(USER_NODE).where(no.and(no).or(no)).returning(USER_NODE).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t}\n\n\t\t@Test // GH-110\n\t\tvoid multipleEmptyConditionsMustCollapse2() {\n\n\t\t\tvar no = Cypher.noCondition();\n\t\t\tSupplier<Condition> t = () -> USER_NODE.property(\"a\").isEqualTo(Cypher.literalTrue());\n\t\t\tString expected = \"MATCH (u:`User`) WHERE u.a = true RETURN u\";\n\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(no.and(t.get()).or(no))\n\t\t\t\t.and(no.and(no).or(no))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\tstatement = Cypher.match(USER_NODE).where(no.or(no).or(t.get())).returning(USER_NODE).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\tstatement = Cypher.match(USER_NODE).where(no.and(t.get()).or(no)).returning(USER_NODE).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\tstatement = Cypher.match(USER_NODE).where(no.or(no)).and(t.get()).returning(USER_NODE).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t}\n\n\t\t@Test // GH-110\n\t\tvoid multipleEmptyConditionsMustCollapse3() {\n\n\t\t\tvar no = Cypher.noCondition();\n\t\t\tSupplier<Condition> t = () -> USER_NODE.property(\"a\").isEqualTo(Cypher.literalTrue());\n\t\t\tSupplier<Condition> f = () -> USER_NODE.property(\"b\").isEqualTo(Cypher.literalFalse());\n\t\t\tString expected = \"MATCH (u:`User`) WHERE (u.a = true AND u.b = false) RETURN u\";\n\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(no.and(t.get()).or(no))\n\t\t\t\t.and(no.and(f.get()).or(no))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\tstatement = Cypher.match(USER_NODE).where(no.or(no).or(t.get()).and(f.get())).returning(USER_NODE).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(no.and(t.get()).or(no))\n\t\t\t\t.and(f.get().or(no))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t}\n\n\t\t@Test\n\t\tvoid chainingOnWhere() {\n\t\t\tStatement statement;\n\n\t\t\tLiteral<?> test = Cypher.literalOf(\"Test\");\n\t\t\tLiteral<?> foobar = Cypher.literalOf(\"foobar\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) WHERE u.name = 'Test' RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE (u.name = 'Test' AND u.name = 'Test') RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE (u.name = 'Test' AND u.name = 'Test' AND u.name = 'Test') RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE (u.name = 'Test' OR u.name = 'Test') RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE (u.name = 'Test' OR u.name = 'Test' OR u.name = 'Test') RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar))\n\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) WHERE (((u.name = 'Test' AND u.name = 'Test') OR u.name = 'foobar') AND u.name = 'Test') RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar))\n\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) WHERE ((u.name = 'Test' OR u.name = 'foobar') AND u.name = 'Test' AND u.name = 'Test') RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar))\n\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar))\n\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) WHERE ((((u.name = 'Test' OR u.name = 'foobar') AND u.name = 'Test') OR u.name = 'foobar') AND u.name = 'Test') RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isNotNull())\n\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.or(USER_NODE.property(\"age\").isEqualTo(Cypher.literalOf(21)))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE ((u.name IS NOT NULL AND u.name = 'Test') OR u.age = 21) RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid chainingOnConditions() {\n\t\t\tStatement statement;\n\n\t\t\tLiteral<?> test = Cypher.literalOf(\"Test\");\n\t\t\tLiteral<?> foobar = Cypher.literalOf(\"foobar\");\n\t\t\tLiteral<?> bazbar = Cypher.literalOf(\"bazbar\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\")\n\t\t\t\t\t.isEqualTo(test)\n\t\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar))\n\t\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar)))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) WHERE (u.name = 'Test' OR u.name = 'foobar' OR u.name = 'foobar') RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\")\n\t\t\t\t\t.isEqualTo(test)\n\t\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(bazbar))\n\t\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar))\n\t\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar)))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) WHERE ((u.name = 'Test' AND u.name = 'bazbar') OR u.name = 'foobar' OR u.name = 'foobar') RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(bazbar).and(USER_NODE.property(\"name\").isEqualTo(foobar)))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) WHERE (u.name = 'Test' AND u.name = 'bazbar' AND u.name = 'foobar') RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\")\n\t\t\t\t\t.isEqualTo(test)\n\t\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(bazbar))\n\t\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar))\n\t\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar)))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) WHERE ((u.name = 'Test' AND u.name = 'bazbar') OR u.name = 'foobar' OR u.name = 'foobar') RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\")\n\t\t\t\t\t.isEqualTo(test)\n\t\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(bazbar))\n\t\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar))\n\t\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar))\n\t\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(bazbar)))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) WHERE (((u.name = 'Test' AND u.name = 'bazbar') OR u.name = 'foobar' OR u.name = 'foobar') AND u.name = 'bazbar') RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid chainingCombined() {\n\t\t\tStatement statement;\n\n\t\t\tLiteral<?> test = Cypher.literalOf(\"Test\");\n\t\t\tLiteral<?> foobar = Cypher.literalOf(\"foobar\");\n\t\t\tLiteral<?> bazbar = Cypher.literalOf(\"bazbar\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\")\n\t\t\t\t\t.isEqualTo(test)\n\t\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(bazbar))\n\t\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar))\n\t\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(foobar)))\n\t\t\t\t.and(USER_NODE.property(\"name\")\n\t\t\t\t\t.isEqualTo(bazbar)\n\t\t\t\t\t.and(USER_NODE.property(\"name\").isEqualTo(foobar))\n\t\t\t\t\t.or(USER_NODE.property(\"name\").isEqualTo(test))\n\t\t\t\t\t.not())\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) WHERE (((u.name = 'Test' AND u.name = 'bazbar') OR u.name = 'foobar' OR u.name = 'foobar') AND NOT (((u.name = 'bazbar' AND u.name = 'foobar') OR u.name = 'Test'))) RETURN u\");\n\n\t\t}\n\n\t\t@Test\n\t\tvoid negatedConditions() {\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isNotNull().not())\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) WHERE u.name IS NULL RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid noConditionShouldNotBeRendered() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(USER_NODE).where(Cypher.noCondition()).returning(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isEqualTo(Cypher.literalOf(\"test\")))\n\t\t\t\t.and(Cypher.noCondition())\n\t\t\t\t.or(Cypher.noCondition())\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) WHERE u.name = 'test' RETURN u\");\n\t\t}\n\n\t\t@Test // GH-137\n\t\tvoid groupingBug() {\n\n\t\t\tNode node = Cypher.node(\"Person\").named(\"person\");\n\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(node)\n\t\t\t\t.where(Cypher.literalOf(\"A\").isTrue().or(Cypher.literalOf(\"B\").isTrue()))\n\t\t\t\t.and(Cypher.literalOf(\"C\").isTrue())\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (person:`Person`) WHERE (('A' = true OR 'B' = true) AND 'C' = true) RETURN person\");\n\n\t\t\tstatement = Cypher.match(node)\n\t\t\t\t.where(Cypher.literalOf(\"A\").isTrue().or(Cypher.literalOf(\"B\").isTrue()))\n\t\t\t\t.and(Cypher.literalOf(\"C\").isTrue().or(Cypher.literalOf(\"D\").isTrue()))\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`) WHERE (('A' = true OR 'B' = true) AND ('C' = true OR 'D' = true)) RETURN person\");\n\t\t}\n\n\t\t@Test // GH-244\n\t\tvoid inPatternComprehensions() {\n\n\t\t\tStatement statement;\n\t\t\tNode a = Cypher.node(\"Person\").withProperties(\"name\", Cypher.literalOf(\"Keanu Reeves\")).named(\"a\");\n\t\t\tNode b = Cypher.anyNode(\"b\");\n\n\t\t\tstatement = Cypher.match(a)\n\t\t\t\t.returning(Cypher.listBasedOn(a.relationshipBetween(b))\n\t\t\t\t\t.where(b.hasLabels(\"Movie\").and(b.property(\"released\").isNotNull()))\n\t\t\t\t\t.returning(b.property(\"released\"))\n\t\t\t\t\t.as(\"years\"))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) WHERE (b:`Movie` AND b.released IS NOT NULL) | b.released] AS years\");\n\n\t\t\tstatement = Cypher.match(a)\n\t\t\t\t.returning(Cypher.listBasedOn(a.relationshipBetween(b))\n\t\t\t\t\t.where(b.hasLabels(\"Movie\")\n\t\t\t\t\t\t.and(b.property(\"released\").isNotNull())\n\t\t\t\t\t\t.or(b.property(\"title\").isEqualTo(Cypher.literalOf(\"The Matrix\")))\n\t\t\t\t\t\t.or(b.property(\"title\").isEqualTo(Cypher.literalOf(\"The Matrix 2\"))))\n\t\t\t\t\t.returning(b.property(\"released\"))\n\t\t\t\t\t.as(\"years\"))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) WHERE ((b:`Movie` AND b.released IS NOT NULL) OR b.title = 'The Matrix' OR b.title = 'The Matrix 2') | b.released] AS years\");\n\n\t\t\tstatement = Cypher.match(a)\n\t\t\t\t.returning(Cypher.listBasedOn(a.relationshipBetween(b))\n\t\t\t\t\t.where(b.hasLabels(\"Movie\"))\n\t\t\t\t\t.and(b.property(\"released\").isNotNull())\n\t\t\t\t\t.or(b.property(\"title\").isEqualTo(Cypher.literalOf(\"The Matrix\")))\n\t\t\t\t\t.or(b.property(\"title\").isEqualTo(Cypher.literalOf(\"The Matrix 2\")))\n\t\t\t\t\t.returning(b.property(\"released\"))\n\t\t\t\t\t.as(\"years\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) WHERE ((b:`Movie` AND b.released IS NOT NULL) OR b.title = 'The Matrix' OR b.title = 'The Matrix 2') | b.released] AS years\");\n\n\t\t\tstatement = Cypher.match(a)\n\t\t\t\t.returning(Cypher.listBasedOn(a.relationshipBetween(b))\n\t\t\t\t\t.where(b.hasLabels(\"Movie\"))\n\t\t\t\t\t.returning(b.property(\"released\"))\n\t\t\t\t\t.as(\"years\"))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) WHERE b:`Movie` | b.released] AS years\");\n\t\t}\n\n\t\t@Nested // GH-206, 3.6.5. Using path patterns in WHERE\n\t\tclass PathPatternConditions {\n\n\t\t\t@Test\n\t\t\tvoid doc3651And() {\n\t\t\t\tNode timothy = Cypher.node(\"Person\")\n\t\t\t\t\t.named(\"timothy\")\n\t\t\t\t\t.withProperties(\"name\", Cypher.literalOf(\"Timothy\"));\n\t\t\t\tNode other = Cypher.node(\"Person\").named(\"other\");\n\n\t\t\t\tStatement statement;\n\n\t\t\t\tString expected = \"MATCH (timothy:`Person` {name: 'Timothy'}), (other:`Person`) WHERE (other.name IN ['Andy', 'Peter'] AND (timothy)<--(other)) RETURN other.name, other.age\";\n\t\t\t\tstatement = Cypher.match(timothy, other)\n\t\t\t\t\t.where(other.property(\"name\")\n\t\t\t\t\t\t.in(Cypher.listOf(Cypher.literalOf(\"Andy\"), Cypher.literalOf(\"Peter\"))))\n\t\t\t\t\t.and(timothy.relationshipFrom(other))\n\t\t\t\t\t.returning(other.property(\"name\"), other.property(\"age\"))\n\t\t\t\t\t.build();\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\t\tstatement = Cypher.match(timothy, other)\n\t\t\t\t\t.where(other.property(\"name\")\n\t\t\t\t\t\t.in(Cypher.listOf(Cypher.literalOf(\"Andy\"), Cypher.literalOf(\"Peter\")))\n\t\t\t\t\t\t.and(timothy.relationshipFrom(other)))\n\t\t\t\t\t.returning(other.property(\"name\"), other.property(\"age\"))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid doc3651Or() {\n\t\t\t\tNode timothy = Cypher.node(\"Person\")\n\t\t\t\t\t.named(\"timothy\")\n\t\t\t\t\t.withProperties(\"name\", Cypher.literalOf(\"Timothy\"));\n\t\t\t\tNode other = Cypher.node(\"Person\").named(\"other\");\n\n\t\t\t\tStatement statement;\n\n\t\t\t\tString expected = \"MATCH (timothy:`Person` {name: 'Timothy'}), (other:`Person`) WHERE (other.name IN ['Andy', 'Peter'] OR (timothy)<--(other)) RETURN other.name, other.age\";\n\t\t\t\tstatement = Cypher.match(timothy, other)\n\t\t\t\t\t.where(other.property(\"name\")\n\t\t\t\t\t\t.in(Cypher.listOf(Cypher.literalOf(\"Andy\"), Cypher.literalOf(\"Peter\"))))\n\t\t\t\t\t.or(timothy.relationshipFrom(other))\n\t\t\t\t\t.returning(other.property(\"name\"), other.property(\"age\"))\n\t\t\t\t\t.build();\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\t\tstatement = Cypher.match(timothy, other)\n\t\t\t\t\t.where(other.property(\"name\")\n\t\t\t\t\t\t.in(Cypher.listOf(Cypher.literalOf(\"Andy\"), Cypher.literalOf(\"Peter\")))\n\t\t\t\t\t\t.or(timothy.relationshipFrom(other)))\n\t\t\t\t\t.returning(other.property(\"name\"), other.property(\"age\"))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid doc3651XOr() {\n\t\t\t\tNode timothy = Cypher.node(\"Person\")\n\t\t\t\t\t.named(\"timothy\")\n\t\t\t\t\t.withProperties(\"name\", Cypher.literalOf(\"Timothy\"));\n\t\t\t\tNode other = Cypher.node(\"Person\").named(\"other\");\n\n\t\t\t\tStatement statement;\n\n\t\t\t\tString expected = \"MATCH (timothy:`Person` {name: 'Timothy'}), (other:`Person`) WHERE (other.name IN ['Andy', 'Peter'] XOR (timothy)<--(other)) RETURN other.name, other.age\";\n\t\t\t\tstatement = Cypher.match(timothy, other)\n\t\t\t\t\t.where(other.property(\"name\")\n\t\t\t\t\t\t.in(Cypher.listOf(Cypher.literalOf(\"Andy\"), Cypher.literalOf(\"Peter\")))\n\t\t\t\t\t\t.xor(timothy.relationshipFrom(other)))\n\t\t\t\t\t.returning(other.property(\"name\"), other.property(\"age\"))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid doc3652() {\n\n\t\t\t\tNode person = Cypher.node(\"Person\").named(\"person\");\n\t\t\t\tNode peter = Cypher.node(\"Person\").named(\"peter\").withProperties(\"name\", Cypher.literalOf(\"Peter\"));\n\n\t\t\t\tStatement statement;\n\n\t\t\t\tstatement = Cypher.match(person, peter)\n\t\t\t\t\t.where(Cypher.not(person.relationshipTo(peter)))\n\t\t\t\t\t.returning(person.property(\"name\"), person.property(\"age\"))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH (person:`Person`), (peter:`Person` {name: 'Peter'}) WHERE NOT (person)-->(peter) RETURN person.name, person.age\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid doc3653() {\n\n\t\t\t\tNode person = Cypher.node(\"Person\").named(\"n\");\n\t\t\t\tStatement statement;\n\n\t\t\t\tstatement = Cypher.match(person)\n\t\t\t\t\t.where(person.relationshipBetween(\n\t\t\t\t\t\t\tCypher.anyNode().withProperties(\"name\", Cypher.literalOf(\"Timothy\")), \"KNOWS\"))\n\t\t\t\t\t.returning(person.property(\"name\"), person.property(\"age\"))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (n:`Person`) WHERE (n)-[:`KNOWS`]-( {name: 'Timothy'}) RETURN n.name, n.age\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid gh113() {\n\n\t\t\t\tNode foo = Cypher.node(\"Foo\").named(\"foo\");\n\t\t\t\tNode bar = Cypher.node(\"Bar\").named(\"bar\");\n\t\t\t\tRelationship fooBar = foo.relationshipTo(bar, \"FOOBAR\").named(\"rel\");\n\t\t\t\tPatternComprehension pc = Cypher.listBasedOn(fooBar)\n\t\t\t\t\t.where(bar.relationshipTo(Cypher.node(\"ZZZ\"), \"HAS\"))\n\t\t\t\t\t.returning(fooBar, bar);\n\t\t\t\tStatement statement = Cypher.match(foo).returning(foo.getRequiredSymbolicName(), pc).build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH (foo:`Foo`) RETURN foo, [(foo)-[rel:`FOOBAR`]->(bar:`Bar`) WHERE (bar)-[:`HAS`]->(:`ZZZ`) | [rel, bar]]\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid doc3654() {\n\n\t\t\t\tNode person = Cypher.node(\"Person\").named(\"n\");\n\t\t\t\tStatement statement;\n\n\t\t\t\tRelationship pathPattern = person.relationshipTo(Cypher.anyNode()).named(\"r\");\n\t\t\t\tstatement = Cypher.match(pathPattern)\n\t\t\t\t\t.where(person.property(\"name\").isEqualTo(Cypher.literalOf(\"Andy\")))\n\t\t\t\t\t.and(Cypher.type(pathPattern).matches(\"K.*\"))\n\t\t\t\t\t.returning(Cypher.type(pathPattern), pathPattern.property(\"since\"))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH (n:`Person`)-[r]->() WHERE (n.name = 'Andy' AND type(r) =~ 'K.*') RETURN type(r), r.since\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid afterWith() {\n\n\t\t\t\tNode timothy = Cypher.node(\"Person\")\n\t\t\t\t\t.named(\"timothy\")\n\t\t\t\t\t.withProperties(\"name\", Cypher.literalOf(\"Timothy\"));\n\t\t\t\tNode other = Cypher.node(\"Person\").named(\"other\");\n\n\t\t\t\tStatement statement;\n\n\t\t\t\tString expected = \"MATCH (timothy:`Person` {name: 'Timothy'}), (other:`Person`) WITH timothy, other WHERE (other.name IN ['Andy', 'Peter'] AND (timothy)<--(other)) RETURN other.name, other.age\";\n\t\t\t\tstatement = Cypher.match(timothy, other)\n\t\t\t\t\t.with(timothy, other)\n\t\t\t\t\t.where(other.property(\"name\")\n\t\t\t\t\t\t.in(Cypher.listOf(Cypher.literalOf(\"Andy\"), Cypher.literalOf(\"Peter\"))))\n\t\t\t\t\t.and(timothy.relationshipFrom(other))\n\t\t\t\t\t.returning(other.property(\"name\"), other.property(\"age\"))\n\t\t\t\t\t.build();\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\t\tstatement = Cypher.match(timothy, other)\n\t\t\t\t\t.with(timothy, other)\n\t\t\t\t\t.where(other.property(\"name\")\n\t\t\t\t\t\t.in(Cypher.listOf(Cypher.literalOf(\"Andy\"), Cypher.literalOf(\"Peter\")))\n\t\t\t\t\t\t.and(timothy.relationshipFrom(other)))\n\t\t\t\t\t.returning(other.property(\"name\"), other.property(\"age\"))\n\t\t\t\t\t.build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass RemoveClause {\n\n\t\t@Test\n\t\tvoid shouldRenderRemoveOnNodes() {\n\t\t\tStatement statement;\n\n\t\t\tstatement = Cypher.match(USER_NODE).remove(USER_NODE, \"A\", \"B\").returning(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) REMOVE u:`A`:`B` RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.with(USER_NODE)\n\t\t\t\t.set(USER_NODE, \"A\", \"B\")\n\t\t\t\t.remove(USER_NODE, \"C\", \"D\")\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WITH u SET u:`A`:`B` REMOVE u:`C`:`D` RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderRemoveOfProperties() {\n\t\t\tStatement statement;\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.remove(USER_NODE.property(\"a\"), USER_NODE.property(\"b\"))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) REMOVE u.a, u.b RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.with(USER_NODE)\n\t\t\t\t.remove(USER_NODE.property(\"a\"))\n\t\t\t\t.remove(USER_NODE.property(\"b\"))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WITH u REMOVE u.a REMOVE u.b RETURN u\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass MutatingSetClause {\n\n\t\t@Test\n\t\tvoid simpleWithParam() {\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.mutate(USER_NODE, Cypher.parameter(\"newMapsOfHell\"))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) SET u += $newMapsOfHell RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid afterMerge() {\n\t\t\tStatement statement = Cypher.merge(USER_NODE)\n\t\t\t\t.onMatch()\n\t\t\t\t.mutate(USER_NODE, Cypher.parameter(\"newMapsOfHell\"))\n\t\t\t\t.onCreate()\n\t\t\t\t.mutate(USER_NODE, Cypher.mapOf(\"a\", Cypher.literalOf(\"B\")))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MERGE (u:`User`) ON MATCH SET u += $newMapsOfHell ON CREATE SET u += {a: 'B'} RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid simpleWithMap() {\n\t\t\tStatement statement = Cypher.match(USER_NODE)\n\t\t\t\t.mutate(USER_NODE, Cypher.mapOf(\"a\", Cypher.literalOf(\"B\")))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) SET u += {a: 'B'} RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid chainedWithParam() {\n\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"r\"))\n\t\t\t\t.mutate(USER_NODE, Cypher.mapOf(\"a\", Cypher.literalOf(\"B\")))\n\t\t\t\t.mutate(BIKE_NODE, Cypher.parameter(\"newMapsOfHell\"))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`)-[r:`OWNS`]->(b:`Bike`) SET u += {a: 'B'} SET b += $newMapsOfHell RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid chainedWithMap() {\n\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"r\"))\n\t\t\t\t.mutate(USER_NODE, Cypher.mapOf(\"a\", Cypher.literalOf(\"B\")))\n\t\t\t\t.mutate(BIKE_NODE, Cypher.mapOf(\"c\", Cypher.literalOf(\"D\")))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`)-[r:`OWNS`]->(b:`Bike`) SET u += {a: 'B'} SET b += {c: 'D'} RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid multipleLevelsOfChaining() {\n\t\t\tStatement statement = Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"r\"))\n\t\t\t\t.mutate(USER_NODE, Cypher.mapOf(\"a\", Cypher.literalOf(\"B\")))\n\t\t\t\t.mutate(BIKE_NODE, Cypher.mapOf(\"c\", Cypher.literalOf(\"D\")))\n\t\t\t\t.mutate(Cypher.name(\"r\"), Cypher.mapOf(\"e\", Cypher.literalOf(\"F\")))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`)-[r:`OWNS`]->(b:`Bike`) SET u += {a: 'B'} SET b += {c: 'D'} SET r += {e: 'F'} RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid foldingMultipleMutatesIntoOne() {\n\t\t\tRelationship ownsRelationship = USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"r\");\n\t\t\tStatement statement = Cypher.match(ownsRelationship)\n\t\t\t\t.set(USER_NODE.mutate(Cypher.mapOf(\"a\", Cypher.literalOf(\"B\"))),\n\t\t\t\t\t\tBIKE_NODE.mutate(Cypher.mapOf(\"c\", Cypher.literalOf(\"D\"))),\n\t\t\t\t\t\townsRelationship.mutate(Cypher.mapOf(\"e\", Cypher.literalOf(\"F\"))))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`)-[r:`OWNS`]->(b:`Bike`) SET u += {a: 'B'}, b += {c: 'D'}, r += {e: 'F'} RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid afterMergeFolding() {\n\t\t\tRelationship ownsRelationship = USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"r\");\n\t\t\tStatement statement = Cypher.merge(ownsRelationship)\n\t\t\t\t.onMatch()\n\t\t\t\t.set(USER_NODE.mutate(Cypher.mapOf(\"a\", Cypher.literalOf(\"B\"))),\n\t\t\t\t\t\tBIKE_NODE.mutate(Cypher.mapOf(\"c\", Cypher.literalOf(\"D\"))),\n\t\t\t\t\t\townsRelationship.mutate(Cypher.mapOf(\"e\", Cypher.literalOf(\"F\"))))\n\t\t\t\t.onCreate()\n\t\t\t\t.mutate(USER_NODE, Cypher.mapOf(\"a\", Cypher.literalOf(\"B\")))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MERGE (u:`User`)-[r:`OWNS`]->(b:`Bike`) ON MATCH SET u += {a: 'B'}, b += {c: 'D'}, r += {e: 'F'} ON CREATE SET u += {a: 'B'} RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid mergeMutate() {\n\t\t\tStatement statement = Cypher.merge(USER_NODE)\n\t\t\t\t.mutate(USER_NODE, Cypher.mapOf(\"e\", Cypher.literalOf(\"F\")))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (u:`User`) SET u += {e: 'F'} RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid createMutate() {\n\t\t\tStatement statement = Cypher.create(USER_NODE)\n\t\t\t\t.mutate(USER_NODE, Cypher.mapOf(\"e\", Cypher.literalOf(\"F\")))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (u:`User`) SET u += {e: 'F'} RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid mergeMutateWithMapProjection() {\n\t\t\tStatement statement;\n\t\t\tSymbolicName map = Cypher.name(\"map\");\n\n\t\t\tstatement = Cypher\n\t\t\t\t.with(Cypher.mapOf(\"p\", Cypher.literalOf(\"Hello, Welt\"), \"i\", Cypher.literalOf(1)).as(map))\n\t\t\t\t.merge(USER_NODE)\n\t\t\t\t.mutate(USER_NODE, map.project(Cypher.asterisk()))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"WITH {p: 'Hello, Welt', i: 1} AS map MERGE (u:`User`) SET u += map{.*}\");\n\t\t}\n\n\t\t@Test\n\t\tvoid mergeMutateWithSymbolicName() {\n\t\t\tStatement statement;\n\t\t\tSymbolicName map = Cypher.name(\"map\");\n\n\t\t\tstatement = Cypher\n\t\t\t\t.with(Cypher.mapOf(\"p\", Cypher.literalOf(\"Hello, Welt\"), \"i\", Cypher.literalOf(1)).as(map))\n\t\t\t\t.merge(USER_NODE)\n\t\t\t\t.mutate(USER_NODE, map)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"WITH {p: 'Hello, Welt', i: 1} AS map MERGE (u:`User`) SET u += map\");\n\t\t}\n\n\t\t@Test\n\t\tvoid mergeMutateWithFunctionCall() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.merge(USER_NODE).mutate(USER_NODE, Cypher.call(\"returns.map\").asFunction()).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (u:`User`) SET u += returns.map()\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass SetClause {\n\n\t\t@Test\n\t\tvoid shouldRenderSetAfterCreate() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.create(USER_NODE)\n\t\t\t\t.set(USER_NODE.property(\"p\").to(Cypher.literalOf(\"Hallo, Welt\")))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (u:`User`) SET u.p = 'Hallo, Welt'\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderSetAfterMerge() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.merge(USER_NODE)\n\t\t\t\t.set(USER_NODE.property(\"p\").to(Cypher.literalOf(\"Hallo, Welt\")))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (u:`User`) SET u.p = 'Hallo, Welt'\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderSetAfterCreateAndWith() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.create(USER_NODE)\n\t\t\t\t.with(USER_NODE)\n\t\t\t\t.set(USER_NODE.property(\"p\").to(Cypher.literalOf(\"Hallo, Welt\")))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (u:`User`) WITH u SET u.p = 'Hallo, Welt'\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderSetAfterMergeAndWith() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.merge(USER_NODE)\n\t\t\t\t.with(USER_NODE)\n\t\t\t\t.set(USER_NODE.property(\"p\").to(Cypher.literalOf(\"Hallo, Welt\")))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (u:`User`) WITH u SET u.p = 'Hallo, Welt'\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderSet() {\n\n\t\t\tStatement statement;\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.set(USER_NODE.property(\"p\").to(Cypher.literalOf(\"Hallo, Welt\")))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) SET u.p = 'Hallo, Welt'\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.set(USER_NODE.property(\"p\").to(Cypher.literalOf(\"Hallo, Welt\")))\n\t\t\t\t.set(USER_NODE.property(\"a\").to(Cypher.literalOf(\"Selber hallo.\")))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) SET u.p = 'Hallo, Welt' SET u.a = 'Selber hallo.'\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.set(USER_NODE.property(\"p\").to(Cypher.literalOf(\"Hallo\")),\n\t\t\t\t\t\tUSER_NODE.property(\"g\").to(Cypher.literalOf(\"Welt\")))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) SET u.p = 'Hallo', u.g = 'Welt'\");\n\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderSetOnNodes() {\n\t\t\tStatement statement;\n\n\t\t\tstatement = Cypher.match(USER_NODE).set(USER_NODE, \"A\", \"B\").returning(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) SET u:`A`:`B` RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.with(USER_NODE)\n\t\t\t\t.set(USER_NODE, \"A\", \"B\")\n\t\t\t\t.set(USER_NODE, \"C\", \"D\")\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WITH u SET u:`A`:`B` SET u:`C`:`D` RETURN u\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderSetFromAListOfExpression() {\n\t\t\tStatement statement;\n\n\t\t\tstatement = Cypher.match(USER_NODE).set(USER_NODE.property(\"p\"), Cypher.literalOf(\"Hallo, Welt\")).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) SET u.p = 'Hallo, Welt'\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.set(USER_NODE.property(\"p\"), Cypher.literalOf(\"Hallo\"), USER_NODE.property(\"g\"),\n\t\t\t\t\t\tCypher.literalOf(\"Welt\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) SET u.p = 'Hallo', u.g = 'Welt'\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.set(USER_NODE.property(\"p\"), Cypher.literalOf(\"Hallo, Welt\"))\n\t\t\t\t.set(USER_NODE.property(\"p\"), Cypher.literalOf(\"Hallo\"), USER_NODE.property(\"g\"),\n\t\t\t\t\t\tCypher.literalOf(\"Welt\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) SET u.p = 'Hallo, Welt' SET u.p = 'Hallo', u.g = 'Welt'\");\n\n\t\t\t// noinspection ResultOfMethodCallIgnored\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.match(USER_NODE).set(USER_NODE.property(\"g\")))\n\t\t\t\t.withMessage(\"The list of expression to set must be even.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderMixedSet() {\n\t\t\tStatement statement;\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.set(USER_NODE.property(\"p1\"), Cypher.literalOf(\"Two expressions\"))\n\t\t\t\t.set(USER_NODE.property(\"p2\").to(Cypher.literalOf(\"A set expression\")))\n\t\t\t\t.set(USER_NODE.property(\"p3\").to(Cypher.literalOf(\"One of two set expression\")),\n\t\t\t\t\t\tUSER_NODE.property(\"p4\").to(Cypher.literalOf(\"Two of two set expression\")))\n\t\t\t\t.set(USER_NODE.property(\"p5\"), Cypher.literalOf(\"Pair one of 2 expressions\"), USER_NODE.property(\"p6\"),\n\t\t\t\t\t\tCypher.literalOf(\"Pair two of 4 expressions\"))\n\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) SET u.p1 = 'Two expressions' SET u.p2 = 'A set expression' SET u.p3 = 'One of two set expression', u.p4 = 'Two of two set expression' SET u.p5 = 'Pair one of 2 expressions', u.p6 = 'Pair two of 4 expressions' RETURN *\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass MergeClause {\n\n\t\t@Test\n\t\tvoid shouldRenderMergeWithoutReturn() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.merge(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (u:`User`)\");\n\n\t\t\tstatement = Cypher.merge(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\")).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (u:`User`)-[o:`OWNS`]->(b:`Bike`)\");\n\t\t}\n\n\t\t@Test // GH-189\n\t\tvoid shouldRenderMergeBasedOnPatternExpressionCollectionWithoutReturn() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.merge(Collections.singleton(USER_NODE)).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (u:`User`)\");\n\n\t\t\tstatement = Cypher.merge(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\")).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (u:`User`)-[o:`OWNS`]->(b:`Bike`)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderMultipleMergesWithoutReturn() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.merge(USER_NODE).merge(BIKE_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (u:`User`) MERGE (b:`Bike`)\");\n\n\t\t\tstatement = Cypher.merge(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\"))\n\t\t\t\t.merge(Cypher.node(\"Other\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MERGE (u:`User`)-[o:`OWNS`]->(b:`Bike`) MERGE (:`Other`)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderMergeReturn() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.merge(USER_NODE).returning(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (u:`User`) RETURN u\");\n\n\t\t\tRelationship r = USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\");\n\t\t\tstatement = Cypher.merge(r).returning(USER_NODE, r).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MERGE (u:`User`)-[o:`OWNS`]->(b:`Bike`) RETURN u, o\");\n\n\t\t\tstatement = Cypher.merge(USER_NODE)\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.orderBy(USER_NODE.property(\"name\"))\n\t\t\t\t.skip(23)\n\t\t\t\t.limit(42)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MERGE (u:`User`) RETURN u ORDER BY u.name SKIP 23 LIMIT 42\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderMultipleMergesReturn() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.merge(USER_NODE).merge(BIKE_NODE).returning(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (u:`User`) MERGE (b:`Bike`) RETURN u\");\n\n\t\t\tRelationship r = USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\");\n\t\t\tstatement = Cypher.merge(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\"))\n\t\t\t\t.merge(Cypher.node(\"Other\"))\n\t\t\t\t.returning(USER_NODE, r)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MERGE (u:`User`)-[o:`OWNS`]->(b:`Bike`) MERGE (:`Other`) RETURN u, o\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderMergeWithWith() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.merge(USER_NODE).with(USER_NODE).returning(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (u:`User`) WITH u RETURN u\");\n\n\t\t\tstatement = Cypher.merge(USER_NODE)\n\t\t\t\t.with(USER_NODE)\n\t\t\t\t.set(USER_NODE.property(\"x\").to(Cypher.literalOf(\"y\")))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (u:`User`) WITH u SET u.x = 'y'\");\n\t\t}\n\n\t\t@Test\n\t\tvoid matchShouldExposeMerge() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(USER_NODE).merge(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\")).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) MERGE (u)-[o:`OWNS`]->(b:`Bike`)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withShouldExposeMerge() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.withDistinct(USER_NODE)\n\t\t\t\t.merge(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WITH DISTINCT u MERGE (u)-[o:`OWNS`]->(b:`Bike`)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid mixedCreateAndMerge() {\n\t\t\tStatement statement;\n\n\t\t\tNode tripNode = Cypher.node(\"Trip\").named(\"t\");\n\n\t\t\tstatement = Cypher.create(USER_NODE)\n\t\t\t\t.merge(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\"))\n\t\t\t\t.withDistinct(BIKE_NODE)\n\t\t\t\t.merge(tripNode.relationshipFrom(BIKE_NODE, \"USED_ON\"))\n\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CREATE (u:`User`) MERGE (u)-[o:`OWNS`]->(b:`Bike`) WITH DISTINCT b MERGE (t:`Trip`)<-[:`USED_ON`]-(b) RETURN *\");\n\t\t}\n\n\t\t@Test // GH-104\n\t\tvoid singleCreateAction() {\n\n\t\t\tLiteral<String> halloWeltString = Cypher.literalOf(\"Hallo, Welt\");\n\t\t\tfor (Statement statement : new Statement[] {\n\t\t\t\t\tCypher.merge(USER_NODE).onCreate().set(USER_NODE.property(\"p\").to(halloWeltString)).build(),\n\t\t\t\t\tCypher.merge(USER_NODE).onCreate().set(USER_NODE.property(\"p\"), halloWeltString).build() }) {\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MERGE (u:`User`) ON CREATE SET u.p = 'Hallo, Welt'\");\n\t\t\t}\n\t\t}\n\n\t\t@Test // GH-104\n\t\tvoid singleMatchAction() {\n\n\t\t\tLiteral<String> halloWeltString = Cypher.literalOf(\"Hallo, Welt\");\n\t\t\tfor (Statement statement : new Statement[] {\n\t\t\t\t\tCypher.merge(USER_NODE).onMatch().set(USER_NODE.property(\"p\").to(halloWeltString)).build(),\n\t\t\t\t\tCypher.merge(USER_NODE).onMatch().set(USER_NODE.property(\"p\"), halloWeltString).build(), }) {\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MERGE (u:`User`) ON MATCH SET u.p = 'Hallo, Welt'\");\n\t\t\t}\n\t\t}\n\n\t\t@Test\n\t\tvoid stuffThanSingleMatchAction() {\n\n\t\t\tfor (Statement statement : new Statement[] { Cypher.create(BIKE_NODE)\n\t\t\t\t.set(BIKE_NODE.property(\"nice\").to(Cypher.literalTrue()))\n\t\t\t\t.merge(USER_NODE)\n\t\t\t\t.onMatch()\n\t\t\t\t.set(USER_NODE.property(\"happy\").to(Cypher.literalTrue()))\n\t\t\t\t.create(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\"))\n\t\t\t\t.build(), }) {\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\t\"CREATE (b:`Bike`) SET b.nice = true MERGE (u:`User`) ON MATCH SET u.happy = true CREATE (u)-[:`OWNS`]->(b)\");\n\t\t\t}\n\t\t}\n\n\t\t@Test\n\t\tvoid singleActionMultipleProperties() {\n\n\t\t\tfor (Statement statement : new Statement[] {\n\t\t\t\t\tCypher.merge(USER_NODE)\n\t\t\t\t\t\t.onMatch()\n\t\t\t\t\t\t.set(USER_NODE.property(\"p1\").to(Cypher.literalOf(\"v1\")),\n\t\t\t\t\t\t\t\tUSER_NODE.property(\"p2\").to(Cypher.literalOf(\"v2\")))\n\t\t\t\t\t\t.build(),\n\t\t\t\t\tCypher.merge(USER_NODE)\n\t\t\t\t\t\t.onCreate()\n\t\t\t\t\t\t.set(USER_NODE.property(\"p1\").to(Cypher.literalOf(\"v1\")),\n\t\t\t\t\t\t\t\tUSER_NODE.property(\"p2\").to(Cypher.literalOf(\"v2\")))\n\t\t\t\t\t\t.build(), }) {\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.matches(\"\\\\QMERGE (u:`User`) ON \\\\E(CREATE|MATCH)\\\\Q SET u.p1 = 'v1', u.p2 = 'v2'\\\\E\");\n\t\t\t}\n\t\t}\n\n\t\t@Test\n\t\tvoid multipleActionMultipleProperties() {\n\n\t\t\tStatement statement = Cypher.merge(USER_NODE)\n\t\t\t\t.onMatch()\n\t\t\t\t.set(USER_NODE.property(\"p1\").to(Cypher.literalOf(\"v1\")),\n\t\t\t\t\t\tUSER_NODE.property(\"p2\").to(Cypher.literalOf(\"v2\")))\n\t\t\t\t.onCreate()\n\t\t\t\t.set(USER_NODE.property(\"p3\").to(Cypher.literalOf(\"v3\")),\n\t\t\t\t\t\tUSER_NODE.property(\"p4\").to(Cypher.literalOf(\"v4\")))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MERGE (u:`User`) ON MATCH SET u.p1 = 'v1', u.p2 = 'v2' ON CREATE SET u.p3 = 'v3', u.p4 = 'v4'\");\n\t\t}\n\n\t\t@Test // GH-104\n\t\tvoid singleCreateThanMatchAction() {\n\n\t\t\tLiteral<String> helloWorldString = Cypher.literalOf(\"Hello, World\");\n\t\t\tLiteral<String> halloWeltString = Cypher.literalOf(\"Hallo, Welt\");\n\t\t\tStatement statement = Cypher.merge(USER_NODE)\n\t\t\t\t.onCreate()\n\t\t\t\t.set(USER_NODE.property(\"p\").to(helloWorldString))\n\t\t\t\t.onMatch()\n\t\t\t\t.set(USER_NODE.property(\"p\").to(halloWeltString))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MERGE (u:`User`) ON CREATE SET u.p = 'Hello, World' ON MATCH SET u.p = 'Hallo, Welt'\");\n\t\t}\n\n\t\t@Test // GH-104\n\t\tvoid singleMatchThanCreateAction() {\n\n\t\t\tLiteral<String> helloWorldString = Cypher.literalOf(\"Hello, World\");\n\t\t\tLiteral<String> halloWeltString = Cypher.literalOf(\"Hallo, Welt\");\n\t\t\tStatement statement = Cypher.merge(USER_NODE)\n\t\t\t\t.onMatch()\n\t\t\t\t.set(USER_NODE.property(\"p\").to(halloWeltString))\n\t\t\t\t.onCreate()\n\t\t\t\t.set(USER_NODE.property(\"p\").to(helloWorldString))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MERGE (u:`User`) ON MATCH SET u.p = 'Hallo, Welt' ON CREATE SET u.p = 'Hello, World'\");\n\t\t}\n\n\t\t@Test // GH-104\n\t\tvoid multipleMatchesAndCreates() {\n\n\t\t\tStatement statement = Cypher.merge(USER_NODE)\n\t\t\t\t.onMatch()\n\t\t\t\t.set(USER_NODE.property(\"p1\").to(Cypher.literalOf(\"v1\")))\n\t\t\t\t.onCreate()\n\t\t\t\t.set(USER_NODE.property(\"p2\").to(Cypher.literalOf(\"v2\")))\n\t\t\t\t.onCreate()\n\t\t\t\t.set(USER_NODE.property(\"p3\").to(Cypher.literalOf(\"v3\")))\n\t\t\t\t.onMatch()\n\t\t\t\t.set(USER_NODE.property(\"p4\").to(Cypher.literalOf(\"v4\")))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MERGE (u:`User`) ON MATCH SET u.p1 = 'v1' ON CREATE SET u.p2 = 'v2' ON CREATE SET u.p3 = 'v3' ON MATCH SET u.p4 = 'v4'\");\n\t\t}\n\n\t\t@Test // GH-104\n\t\tvoid actionThanSet() {\n\n\t\t\tStatement statement = Cypher.merge(USER_NODE)\n\t\t\t\t.onMatch()\n\t\t\t\t.set(USER_NODE.property(\"p1\").to(Cypher.literalOf(\"v1\")))\n\t\t\t\t.set(USER_NODE.property(\"p2\").to(Cypher.literalOf(\"v2\")))\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MERGE (u:`User`) ON MATCH SET u.p1 = 'v1' SET u.p2 = 'v2' RETURN u\");\n\t\t}\n\n\t\t@Test // GH-104\n\t\tvoid actionThanContinue() {\n\n\t\t\tStatement statement = Cypher.merge(USER_NODE)\n\t\t\t\t.onMatch()\n\t\t\t\t.set(USER_NODE.property(\"p1\").to(Cypher.literalOf(\"v1\")))\n\t\t\t\t.with(USER_NODE)\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MERGE (u:`User`) ON MATCH SET u.p1 = 'v1' WITH u RETURN u\");\n\t\t}\n\n\t\t@Test // GH-750\n\t\tvoid mergeShouldExposeRemoveLabels() {\n\n\t\t\tvar n = Cypher.node(\"LABEL1\").named(\"n\");\n\t\t\tvar statement = Cypher.merge(n).remove(n, \"OLD_LABEL\").set(n, \"NEW_LABEL\").build();\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MERGE (n:`LABEL1`) REMOVE n:`OLD_LABEL` SET n:`NEW_LABEL`\");\n\t\t}\n\n\t\t@Test // GH-750\n\t\tvoid mergeShouldExposeRemoveProperties() {\n\n\t\t\tvar n = Cypher.node(\"LABEL1\").named(\"n\");\n\t\t\tvar statement = Cypher.merge(n).remove(n.property(\"x\")).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (n:`LABEL1`) REMOVE n.x\");\n\t\t}\n\n\t\t@Test // GH-750\n\t\tvoid mergeShouldExposeSetLabels() {\n\n\t\t\tvar n = Cypher.node(\"LABEL1\").named(\"n\");\n\t\t\tvar statement = Cypher.merge(n).set(n, \"NEW_LABEL\").build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (n:`LABEL1`) SET n:`NEW_LABEL`\");\n\t\t}\n\n\t\t@Test // GH-750\n\t\tvoid mergeShouldExposeSetProperties() {\n\n\t\t\tvar n = Cypher.node(\"LABEL1\").named(\"n\");\n\t\t\tvar statement = Cypher.merge(n).set(n.property(\"x\"), Cypher.literalOf(\"y\")).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (n:`LABEL1`) SET n.x = 'y'\");\n\t\t}\n\n\t\t@Test // GH-750\n\t\tvoid mergeShouldExposeSetLabelsAfterAction() {\n\n\t\t\tvar n = Cypher.node(\"LABEL1\").named(\"n\");\n\t\t\tvar statement = Cypher.merge(n).onMatch().set(n, \"NEW_LABEL\").build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (n:`LABEL1`) ON MATCH SET n:`NEW_LABEL`\");\n\t\t}\n\n\t\t@Test // GH-750\n\t\tvoid mergeShouldExposeSetMultipleLabelsAfterAction() {\n\n\t\t\tvar n = Cypher.node(\"LABEL1\").named(\"n\");\n\t\t\tvar statement = Cypher.merge(n).onMatch().set(n, List.of(\"A\", \"B\")).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (n:`LABEL1`) ON MATCH SET n:`A`:`B`\");\n\t\t}\n\n\t\t@Test // GH-750\n\t\tvoid mergeShouldExposeSetPropertiesAfterAction() {\n\n\t\t\tvar n = Cypher.node(\"LABEL1\").named(\"n\");\n\t\t\tvar statement = Cypher.merge(n).onMatch().set(n.property(\"x\"), Cypher.literalOf(\"y\")).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (n:`LABEL1`) ON MATCH SET n.x = 'y'\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass CreateClause {\n\n\t\t@Test\n\t\tvoid shouldRenderCreateWithoutReturn() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.create(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (u:`User`)\");\n\n\t\t\tstatement = Cypher.create(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\")).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (u:`User`)-[o:`OWNS`]->(b:`Bike`)\");\n\t\t}\n\n\t\t@Test // GH-189\n\t\tvoid shouldRenderCreateBasedOnPatternElementCollectionWithoutReturn() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.create(Collections.singleton(USER_NODE)).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (u:`User`)\");\n\n\t\t\tstatement = Cypher.create(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\")).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (u:`User`)-[o:`OWNS`]->(b:`Bike`)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderMultipleCreatesWithoutReturn() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.create(USER_NODE).create(BIKE_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (u:`User`) CREATE (b:`Bike`)\");\n\n\t\t\tstatement = Cypher.create(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\"))\n\t\t\t\t.create(Cypher.node(\"Other\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"CREATE (u:`User`)-[o:`OWNS`]->(b:`Bike`) CREATE (:`Other`)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderMultipleCreatesBasedOnPatternElementCollectionWithoutReturn() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.create(USER_NODE).create(Collections.singleton(BIKE_NODE)).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (u:`User`) CREATE (b:`Bike`)\");\n\n\t\t\tstatement = Cypher.create(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\"))\n\t\t\t\t.create(Collections.singleton(Cypher.node(\"Other\")))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"CREATE (u:`User`)-[o:`OWNS`]->(b:`Bike`) CREATE (:`Other`)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderCreateReturn() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.create(USER_NODE).returning(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (u:`User`) RETURN u\");\n\n\t\t\tRelationship r = USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\");\n\t\t\tstatement = Cypher.create(r).returning(USER_NODE, r).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"CREATE (u:`User`)-[o:`OWNS`]->(b:`Bike`) RETURN u, o\");\n\n\t\t\tstatement = Cypher.create(USER_NODE)\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.orderBy(USER_NODE.property(\"name\"))\n\t\t\t\t.skip(23)\n\t\t\t\t.limit(42)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"CREATE (u:`User`) RETURN u ORDER BY u.name SKIP 23 LIMIT 42\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderMultipleCreatesReturn() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.create(USER_NODE).create(BIKE_NODE).returning(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (u:`User`) CREATE (b:`Bike`) RETURN u\");\n\n\t\t\tRelationship r = USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\");\n\t\t\tstatement = Cypher.create(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\"))\n\t\t\t\t.create(Cypher.node(\"Other\"))\n\t\t\t\t.returning(USER_NODE, r)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"CREATE (u:`User`)-[o:`OWNS`]->(b:`Bike`) CREATE (:`Other`) RETURN u, o\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderCreateWithWith() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.create(USER_NODE).with(USER_NODE).returning(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (u:`User`) WITH u RETURN u\");\n\n\t\t\tstatement = Cypher.create(USER_NODE)\n\t\t\t\t.with(USER_NODE)\n\t\t\t\t.set(USER_NODE.property(\"x\").to(Cypher.literalOf(\"y\")))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (u:`User`) WITH u SET u.x = 'y'\");\n\t\t}\n\n\t\t@Test\n\t\tvoid matchShouldExposeCreate() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(USER_NODE).create(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\")).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) CREATE (u)-[o:`OWNS`]->(b:`Bike`)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withShouldExposeCreate() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.withDistinct(USER_NODE)\n\t\t\t\t.create(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WITH DISTINCT u CREATE (u)-[o:`OWNS`]->(b:`Bike`)\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.withDistinct(USER_NODE.getRequiredSymbolicName())\n\t\t\t\t.create(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WITH DISTINCT u CREATE (u)-[o:`OWNS`]->(b:`Bike`)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withWithStringVarsShouldWork() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.withDistinct(\"u\")\n\t\t\t\t.create(USER_NODE.relationshipTo(BIKE_NODE, \"OWNS\").named(\"o\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WITH DISTINCT u CREATE (u)-[o:`OWNS`]->(b:`Bike`)\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass DeleteClause {\n\n\t\t@Test\n\t\tvoid shouldRenderDeleteWithoutReturn() {\n\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(USER_NODE).detachDelete(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) DETACH DELETE u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE).detachDelete(\"u\").build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) DETACH DELETE u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE).with(USER_NODE).detachDelete(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) WITH u DETACH DELETE u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"a\").isNotNull())\n\t\t\t\t.and(USER_NODE.property(\"b\").isNull())\n\t\t\t\t.delete(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE (u.a IS NOT NULL AND u.b IS NULL) DELETE u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE, BIKE_NODE).delete(USER_NODE, BIKE_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`), (b:`Bike`) DELETE u, b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderDeleteBasedOnExpressionCollectionWithoutReturn() {\n\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.detachDelete(Collections.singleton(USER_NODE.getRequiredSymbolicName()))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) DETACH DELETE u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.with(USER_NODE)\n\t\t\t\t.detachDelete(Collections.singleton(USER_NODE.getRequiredSymbolicName()))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) WITH u DETACH DELETE u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"a\").isNotNull())\n\t\t\t\t.and(USER_NODE.property(\"b\").isNull())\n\t\t\t\t.delete(Collections.singleton(USER_NODE.getRequiredSymbolicName()))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE (u.a IS NOT NULL AND u.b IS NULL) DELETE u\");\n\n\t\t\tExpression[] namedOnes = { USER_NODE.getRequiredSymbolicName(), BIKE_NODE.getRequiredSymbolicName() };\n\t\t\tstatement = Cypher.match(USER_NODE, BIKE_NODE).delete(Arrays.asList(namedOnes)).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`), (b:`Bike`) DELETE u, b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderDeleteWithReturn() {\n\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(USER_NODE).detachDelete(USER_NODE).returning(USER_NODE).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (u:`User`) DETACH DELETE u RETURN u\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"a\").isNotNull())\n\t\t\t\t.and(USER_NODE.property(\"b\").isNull())\n\t\t\t\t.detachDelete(USER_NODE)\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.orderBy(USER_NODE.property(\"a\").ascending())\n\t\t\t\t.skip(2)\n\t\t\t\t.limit(1)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) WHERE (u.a IS NOT NULL AND u.b IS NULL) DETACH DELETE u RETURN u ORDER BY u.a ASC SKIP 2 LIMIT 1\");\n\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"a\").isNotNull())\n\t\t\t\t.and(USER_NODE.property(\"b\").isNull())\n\t\t\t\t.detachDelete(USER_NODE)\n\t\t\t\t.returningDistinct(USER_NODE)\n\t\t\t\t.orderBy(USER_NODE.property(\"a\").ascending())\n\t\t\t\t.skip(2)\n\t\t\t\t.limit(1)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (u:`User`) WHERE (u.a IS NOT NULL AND u.b IS NULL) DETACH DELETE u RETURN DISTINCT u ORDER BY u.a ASC SKIP 2 LIMIT 1\");\n\t\t}\n\n\t\t@Test\n\t\t@SuppressWarnings(\"deprecation\")\n\t\tvoid shouldRenderNodeDelete() {\n\t\t\tNode n = Cypher.anyNode(\"n\");\n\t\t\tRelationship r = n.relationshipBetween(Cypher.anyNode()).named(\"r0\");\n\t\t\tStatement statement = Cypher.match(n)\n\t\t\t\t.where(n.internalId().isEqualTo(Cypher.literalOf(4711)))\n\t\t\t\t.optionalMatch(r)\n\t\t\t\t.delete(r, n)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (n) WHERE id(n) = 4711 OPTIONAL MATCH (n)-[r0]-() DELETE r0, n\");\n\t\t}\n\n\t\t@Test\n\t\t@SuppressWarnings(\"deprecation\")\n\t\tvoid shouldRenderChainedDeletes() {\n\t\t\tNode n = Cypher.anyNode(\"n\");\n\t\t\tRelationship r = n.relationshipBetween(Cypher.anyNode()).named(\"r0\");\n\t\t\tStatement statement = Cypher.match(n)\n\t\t\t\t.where(n.internalId().isEqualTo(Cypher.literalOf(4711)))\n\t\t\t\t.optionalMatch(r)\n\t\t\t\t.delete(r, n)\n\t\t\t\t.delete(BIKE_NODE)\n\t\t\t\t.detachDelete(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n) WHERE id(n) = 4711 OPTIONAL MATCH (n)-[r0]-() DELETE r0, n DELETE b DETACH DELETE u\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass ForeachClause {\n\n\t\t@Test\n\t\tvoid shouldRenderForeach() {\n\t\t\tNode n = Cypher.anyNode(\"n\");\n\n\t\t\tClause clause = Clauses.forEach(Cypher.name(\"a\"), Cypher.listOf(),\n\t\t\t\t\tList.of(Clauses.merge(List.of(n), List.of(MergeAction.of(MergeAction.Type.ON_CREATE,\n\t\t\t\t\t\t\t(Set) Clauses.set(List.of(Cypher.name(\"n\").property(\"prop\").to(Cypher.literalOf(1)))))))));\n\n\t\t\tassertThat(cypherRenderer.render(Statement.of(List.of(clause))))\n\t\t\t\t.isEqualTo(\"FOREACH (a IN [] | MERGE (n) ON CREATE SET n.prop = 1)\");\n\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderNestedForeach() {\n\t\t\tNode n = Cypher.anyNode(\"n\");\n\n\t\t\tClause clause = Clauses.forEach(Cypher.name(\"a\"), Cypher.listOf(), List.of(Clauses\n\t\t\t\t.forEach(Cypher.name(\"a\"), Cypher.listOf(), List.of(Clauses.merge(List.of(n), List.of(MergeAction.of(\n\t\t\t\t\t\tMergeAction.Type.ON_CREATE,\n\t\t\t\t\t\t(Set) Clauses.set(List.of(Cypher.name(\"n\").property(\"prop\").to(Cypher.literalOf(1)))))))))));\n\n\t\t\tassertThat(cypherRenderer.render(Statement.of(List.of(clause))))\n\t\t\t\t.isEqualTo(\"FOREACH (a IN [] | FOREACH (a IN [] | MERGE (n) ON CREATE SET n.prop = 1))\");\n\n\t\t}\n\n\t\t@Test\n\t\tvoid fakeIfAsDocumentedInKbShouldWork() {\n\t\t\tNode node = Cypher.node(\"Node\").named(\"node\").withProperties(\"id\", Cypher.literalOf(12345));\n\n\t\t\tProperty needsUpdate = node.property(\"needsUpdate\");\n\t\t\tStatement stmt = Cypher.match(node)\n\t\t\t\t.foreach(Cypher.name(\"i\"))\n\t\t\t\t.in(Cypher.caseExpression()\n\t\t\t\t\t.when(needsUpdate)\n\t\t\t\t\t.then(Cypher.listOf(Cypher.literalOf(\"1\")))\n\t\t\t\t\t.elseDefault(Cypher.listOf()))\n\t\t\t\t.apply((UpdatingClause) Clauses\n\t\t\t\t\t.set(List.of(Cypher.set(node.property(\"newProperty\"), Cypher.literalOf(5678)))),\n\t\t\t\t\t\t(UpdatingClause) Clauses.remove(List.of(needsUpdate)),\n\t\t\t\t\t\t(UpdatingClause) Clauses.set(List.of(Cypher.setLabel(node, \"Updated\"))))\n\t\t\t\t.build();\n\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\n\t\t\t\t\t\"MATCH (node:`Node` {id: 12345}) FOREACH (i IN CASE WHEN node.needsUpdate THEN ['1'] ELSE [] END | SET node.newProperty = 5678 REMOVE node.needsUpdate SET node:`Updated`)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid foreachCanBeChained() {\n\t\t\tSymbolicName event = Cypher.name(\"event\");\n\t\t\tSymbolicName create = Cypher.name(\"create\");\n\t\t\tSymbolicName delete = Cypher.name(\"delete\");\n\n\t\t\tListExpression t = Cypher.listOf(Cypher.literalOf(\"1\"));\n\t\t\tListExpression f = Cypher.listOf();\n\n\t\t\tNode user = Cypher.node(\"User\")\n\t\t\t\t.withProperties(\"id\", Cypher.property(Cypher.property(\"event\", \"keys\"), \"id\"))\n\t\t\t\t.named(\"n\");\n\t\t\tClause merge = Clauses.merge(List.of(user), List.of());\n\n\t\t\tvar stmt = Cypher.unwind(Cypher.parameter(\"messages\"))\n\t\t\t\t.as(event)\n\t\t\t\t.with(Cypher.caseExpression()\n\t\t\t\t\t.when(Cypher.valueAt(event, 0).eq(Cypher.literalOf(\"C\")))\n\t\t\t\t\t.then(t)\n\t\t\t\t\t.elseDefault(f)\n\t\t\t\t\t.as(create),\n\t\t\t\t\t\tCypher.caseExpression()\n\t\t\t\t\t\t\t.when(Cypher.valueAt(event, 0).eq(Cypher.literalOf(\"d\")))\n\t\t\t\t\t\t\t.then(t)\n\t\t\t\t\t\t\t.elseDefault(f)\n\t\t\t\t\t\t\t.as(delete),\n\t\t\t\t\t\tCypher.valueAt(event, 1).as(event))\n\t\t\t\t.foreach(Cypher.name(\"i\"))\n\t\t\t\t.in(create)\n\t\t\t\t.apply((UpdatingClause) merge,\n\t\t\t\t\t\t(UpdatingClause) Clauses\n\t\t\t\t\t\t\t.set(List.of(Cypher.set(user.asExpression(), Cypher.property(\"event\", \"properties\")))),\n\t\t\t\t\t\t(UpdatingClause) Clauses\n\t\t\t\t\t\t\t.set(List.of(Cypher.mutate(user.asExpression(), Cypher.property(\"event\", \"keys\")))))\n\t\t\t\t.foreach(Cypher.name(\"i\"))\n\t\t\t\t.in(delete)\n\t\t\t\t.apply((UpdatingClause) merge, (UpdatingClause) Clauses.delete(true, List.of(user.asExpression())))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\n\t\t\t\t\t\"UNWIND $messages AS event WITH CASE WHEN event[0] = 'C' THEN ['1'] ELSE [] END AS create, CASE WHEN event[0] = 'd' THEN ['1'] ELSE [] END AS delete, event[1] AS event FOREACH (i IN create | MERGE (n:`User` {id: event.keys.id}) SET n = event.properties SET n += event.keys) FOREACH (i IN delete | MERGE (n:`User` {id: event.keys.id}) DETACH DELETE n)\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass Expressions {\n\n\t\t@Test\n\t\tvoid shouldRenderParameters() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"a\").isEqualTo(Cypher.parameter(\"aParameter\")))\n\t\t\t\t.detachDelete(USER_NODE)\n\t\t\t\t.returning(USER_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (u:`User`) WHERE u.a = $aParameter DETACH DELETE u RETURN u\");\n\t\t}\n\n\t}\n\n\t@Nested\n\t@TestInstance(TestInstance.Lifecycle.PER_CLASS)\n\tclass OperationsAndComparisons {\n\n\t\t@SuppressWarnings(\"unused\") // This the source of test parameters\n\t\tprivate Stream<Arguments> operatorsToTest() {\n\t\t\treturn Stream.of(Arguments.of(\"Unary minus\", Cypher.minus(Cypher.literalOf(1)), \"RETURN -1\"),\n\t\t\t\t\tArguments.of(\"Unary plus\", Cypher.plus(Cypher.literalOf(1)), \"RETURN +1\"));\n\t\t}\n\n\t\t@ParameterizedTest(name = \"{0}\")\n\t\t@MethodSource(\"operatorsToTest\")\n\t\tvoid unaryOperatorsShouldWork(@SuppressWarnings(\"unused\") String name, Expression operator, String expected) {\n\t\t\tassertThat(cypherRenderer.render(Cypher.returning(operator).build())).isEqualTo(expected);\n\t\t}\n\n\t\t@Test\n\t\t@SuppressWarnings(\"ConstantConditions\") // This is what the test is about\n\t\tvoid preconditionsShouldBeAssertedOnUnary() {\n\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> Operation.create(Operator.OR, Cypher.literalTrue()))\n\t\t\t\t.withMessage(\"Operator must be unary.\");\n\n\t\t\t// Likely to be fail in IDEA when the JetBrains annotations are present and\n\t\t\t// asserted by the ides runner\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> Operation.create(null, Cypher.literalTrue()))\n\t\t\t\t.withMessage(\"Operator must not be null.\");\n\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> Operation.create(Operator.UNARY_MINUS, null))\n\t\t\t\t.withMessage(\"The expression must not be null.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderOperations() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(Cypher.anyNode(\"n\"))\n\t\t\t\t.returning(Cypher.literalOf(1).add(Cypher.literalOf(2)))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (n) RETURN (1 + 2)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderComparision() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(Cypher.anyNode(\"n\"))\n\t\t\t\t.returning(Cypher.literalOf(1).gt(Cypher.literalOf(2)))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (n) RETURN 1 > 2\");\n\n\t\t\tstatement = Cypher.match(Cypher.anyNode(\"n\"))\n\t\t\t\t.returning(Cypher.literalOf(1).gt(Cypher.literalOf(2)).isTrue())\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (n) RETURN (1 > 2) = true\");\n\n\t\t\tstatement = Cypher.match(Cypher.anyNode(\"n\"))\n\t\t\t\t.returning(Cypher.literalOf(1).gt(Cypher.literalOf(2)).isTrue().isFalse())\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (n) RETURN ((1 > 2) = true) = false\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass ExpressionsRendering {\n\n\t\t@Test\n\t\tvoid shouldRenderMap() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(Cypher.anyNode(\"n\"))\n\t\t\t\t.returning(Cypher.point(Cypher.mapOf(\"latitude\", Cypher.parameter(\"latitude\"), \"longitude\",\n\t\t\t\t\t\tCypher.parameter(\"longitude\"), \"crs\", Cypher.literalOf(\"WGS-84\"))))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (n) RETURN point({latitude: $latitude, longitude: $longitude, crs: 'WGS-84'})\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderPointFunction() {\n\t\t\tStatement statement;\n\t\t\tNode n = Cypher.anyNode(\"n\");\n\t\t\tstatement = Cypher.match(n)\n\t\t\t\t.where(Cypher.distance(n.property(\"location\"), Cypher.point(Cypher.parameter(\"point.point\")))\n\t\t\t\t\t.gt(Cypher.parameter(\"point.distance\")))\n\t\t\t\t.returning(n)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n) WHERE point.distance(n.location, point($point.point)) > $point.distance RETURN n\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass PropertyRendering {\n\n\t\t@Test // GH-157\n\t\tvoid usingExistingJavaMaps() {\n\n\t\t\tMap<String, Object> newProperties = new LinkedHashMap<>();\n\t\t\tnewProperties.put(\"prop1\", 23);\n\t\t\tnewProperties.put(\"theTruth\", 42);\n\t\t\tnewProperties.put(\"somethingElse\", \"foobar\");\n\t\t\tnewProperties.put(\"aParam\", Cypher.parameter(\"x\").withValue(\"y\"));\n\t\t\tNode node = Cypher.node(\"ANode\").named(\"n\").withProperties(newProperties);\n\n\t\t\tassertThat(Cypher.match(node).returning(node).build().getCypher())\n\t\t\t\t.isEqualTo(\"MATCH (n:`ANode` {prop1: 23, theTruth: 42, somethingElse: 'foobar', aParam: $x}) RETURN n\");\n\t\t}\n\n\t\t@Test // GH-114\n\t\tvoid manuallyNested() {\n\t\t\tNode node = Cypher.node(\"Person\").named(\"p\");\n\n\t\t\tProperty locationProperty = node.property(\"location\");\n\t\t\tStatement statement = Cypher.match(node)\n\t\t\t\t.where(Cypher.property(locationProperty, \"x\").gt(Cypher.literalOf(6)))\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (p:`Person`) WHERE p.location.x > 6 RETURN p\");\n\t\t}\n\n\t\t@Test // GH-114\n\t\tvoid chained() {\n\t\t\tNode node = Cypher.node(\"Person\").named(\"p\");\n\n\t\t\tStatement statement = Cypher.match(node)\n\t\t\t\t.where(node.property(\"location\", \"x\").gt(Cypher.literalOf(6)))\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (p:`Person`) WHERE p.location.x > 6 RETURN p\");\n\t\t}\n\n\t\t@Test // GH-114\n\t\tvoid chainedAndFancy() {\n\t\t\tNode node = Cypher.node(\"Person\").named(\"p\");\n\n\t\t\tStatement statement = Cypher\n\t\t\t\t.create(node.withProperties(Cypher.mapOf(\"home.location\", Cypher\n\t\t\t\t\t.point(Cypher.mapOf(\"latitude\", Cypher.literalOf(50.751), \"longitude\", Cypher.literalOf(6.179))))))\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CREATE (p:`Person` {`home.location`: point({latitude: 50.751, longitude: 6.179})}) RETURN p\");\n\n\t\t\tstatement = Cypher.match(node)\n\t\t\t\t.where(node.property(\"home.location\", \"y\").gt(Cypher.literalOf(50)))\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (p:`Person`) WHERE p.`home.location`.y > 50 RETURN p\");\n\t\t}\n\n\t\t@Test // GH-123\n\t\tvoid explicitlyDefined() {\n\t\t\tNode node = Cypher.node(\"Person\").named(\"p\");\n\n\t\t\tProperty ly1 = Cypher.property(node.getRequiredSymbolicName(), \"home.location\", \"y\");\n\t\t\tProperty ly2 = Cypher.property(\"p\", \"home.location\", \"y\");\n\n\t\t\tStatement statement = Cypher.match(node).where(ly1.gt(Cypher.literalOf(50))).returning(ly2).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (p:`Person`) WHERE p.`home.location`.y > 50 RETURN p.`home.location`.y\");\n\t\t}\n\n\t\t@Test\n\t\tvoid chainedInProjection() {\n\n\t\t\tNode node = Cypher.node(\"Person\").named(\"p\");\n\t\t\t// noinspection ResultOfMethodCallIgnored\n\t\t\tassertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> Cypher.match(node)\n\t\t\t\t\t.returning(node.project(\"__internalNeo4jId__\", Cypher.elementId(node), \"name\")\n\t\t\t\t\t\t.and(node.property(\"home.location\", \"y\")))\n\t\t\t\t\t.build())\n\t\t\t\t.withMessage(\"Cannot project nested properties!\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderNodeProperties() {\n\n\t\t\tfor (Node nodeWithProperties : new Node[] { Cypher.node(\"Test\", Cypher.mapOf(\"a\", Cypher.literalOf(\"b\"))),\n\t\t\t\t\tCypher.node(\"Test\").withProperties(Cypher.mapOf(\"a\", Cypher.literalOf(\"b\"))),\n\t\t\t\t\tCypher.node(\"Test\").withProperties(\"a\", Cypher.literalOf(\"b\")) }) {\n\n\t\t\t\tStatement statement;\n\t\t\t\tstatement = Cypher.match(nodeWithProperties).returning(Cypher.asterisk()).build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (:`Test` {a: 'b'}) RETURN *\");\n\n\t\t\t\tstatement = Cypher.merge(nodeWithProperties).returning(Cypher.asterisk()).build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (:`Test` {a: 'b'}) RETURN *\");\n\t\t\t}\n\t\t}\n\n\t\t@Test\n\t\tvoid nestedProperties() {\n\n\t\t\tNode nodeWithProperties = Cypher.node(\"Test\")\n\t\t\t\t.withProperties(\"outer\", Cypher.mapOf(\"a\", Cypher.literalOf(\"b\")));\n\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(nodeWithProperties).returning(Cypher.asterisk()).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (:`Test` {outer: {a: 'b'}}) RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldNotRenderPropertiesInReturn() {\n\n\t\t\tNode nodeWithProperties = BIKE_NODE.withProperties(\"a\", Cypher.literalOf(\"b\"));\n\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.match(nodeWithProperties, nodeWithProperties.relationshipFrom(USER_NODE, \"OWNS\"))\n\t\t\t\t.returning(nodeWithProperties)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (b:`Bike` {a: 'b'}), (b)<-[:`OWNS`]-(u:`User`) RETURN b\");\n\t\t}\n\n\t\t@Test // GH-127\n\t\tvoid dynamicPropertyLookupsOnNodes() {\n\n\t\t\tNode m = Cypher.node(\"Movie\").named(\"m\");\n\t\t\tStatement statement;\n\n\t\t\tstatement = Cypher.match(m).returning(m.property(Cypher.literalOf(\"title\"))).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (m:`Movie`) RETURN m['title']\");\n\n\t\t\tstatement = Cypher.match(m).returning(m.property(Cypher.parameter(\"prop\"))).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (m:`Movie`) RETURN m[$prop]\");\n\t\t}\n\n\t\t@Test // GH-127\n\t\tvoid dynamicPropertyLookupsOnRelationships() {\n\n\t\t\tNode m = Cypher.node(\"Movie\").named(\"m\");\n\t\t\tRelationship r = m.relationshipFrom(Cypher.anyNode(), \"ACTED_IN\").named(\"r\");\n\t\t\tStatement statement;\n\n\t\t\tstatement = Cypher.match(r).returning(r.property(Cypher.literalOf(\"roles\"))).build();\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (m:`Movie`)<-[r:`ACTED_IN`]-() RETURN r['roles']\");\n\n\t\t\tstatement = Cypher.match(r).returning(r.property(Cypher.parameter(\"prop\"))).build();\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (m:`Movie`)<-[r:`ACTED_IN`]-() RETURN r[$prop]\");\n\t\t}\n\n\t\t@Test // GH-127\n\t\tvoid arbitraryDynamicLookups() {\n\n\t\t\tNode m = Cypher.node(\"Movie\").named(\"m\");\n\t\t\tStatement statement;\n\n\t\t\tstatement = Cypher.match(m).returning(Cypher.property(\"m\", Cypher.literalOf(\"title\"))).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (m:`Movie`) RETURN m['title']\");\n\n\t\t\tstatement = Cypher.match(m)\n\t\t\t\t.returning(Cypher.property(SymbolicName.of(\"m\"), Cypher.literalOf(\"title\")))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (m:`Movie`) RETURN m['title']\");\n\n\t\t\tstatement = Cypher.with(Cypher.mapOf(\"a\", Cypher.literalOf(\"X\"), \"b\", Cypher.literalOf(\"Y\")).as(\"m\"))\n\t\t\t\t.returning(Cypher.property(\"m\", Cypher.literalOf(\"a\")), Cypher.property(\"m\", \"a\"))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"WITH {a: 'X', b: 'Y'} AS m RETURN m['a'], m.a\");\n\t\t}\n\n\t\t@Test\n\t\tvoid indexedProperties() {\n\n\t\t\tSymbolicName alias = SymbolicName.of(\"line\");\n\t\t\tStatement statement = Cypher.returning(Cypher.valueAt(alias, 1)).build();\n\t\t\tassertThat(statement.getCypher()).isEqualTo(\"RETURN line[1]\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass Returning {\n\n\t\t@Test\n\t\tvoid shouldRenderLeadingReturning() {\n\n\t\t\tString cypher = Cypher.returning(Cypher.literalOf(1)).build().getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\"RETURN 1\");\n\t\t}\n\n\t\t@Test // GH-189\n\t\tvoid shouldRenderLeadingReturningBasedOnExpressionCollection() {\n\n\t\t\tString cypher = Cypher.returning(Collections.singletonList(Cypher.literalOf(1))).build().getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\"RETURN 1\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass UnwindRendering {\n\n\t\t@Test\n\t\t@SuppressWarnings(\"deprecation\")\n\t\tvoid unwindWithoutWith() {\n\n\t\t\tfinal Node rootNode = Cypher.anyNode(\"n\");\n\t\t\tfinal SymbolicName label = Cypher.name(\"label\");\n\t\t\tfinal Statement statement = Cypher.match(rootNode)\n\t\t\t\t.where(rootNode.internalId().isEqualTo(Cypher.literalOf(1)))\n\t\t\t\t.unwind(rootNode.labels())\n\t\t\t\t.as(\"label\")\n\t\t\t\t.with(label)\n\t\t\t\t.where(label.in(Cypher.parameter(\"fixedLabels\")).not())\n\t\t\t\t.returning(Cypher.collect(label).as(\"labels\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n) WHERE id(n) = 1 UNWIND labels(n) AS label WITH label WHERE NOT (label IN $fixedLabels) RETURN collect(label) AS labels\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderLeadingUnwind() {\n\n\t\t\tStatement statement = Cypher.unwind(Cypher.literalOf(1), Cypher.literalTrue(), Cypher.literalFalse())\n\t\t\t\t.as(\"n\")\n\t\t\t\t.returning(Cypher.name(\"n\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"UNWIND [1, true, false] AS n RETURN n\");\n\t\t}\n\n\t\t@Test // GH-189\n\t\tvoid shouldRenderLeadingUnwindBasedOnExpressionCollection() {\n\n\t\t\tExpression[] expressions = { Cypher.literalOf(1), Cypher.literalTrue(), Cypher.literalFalse() };\n\t\t\tStatement statement = Cypher.unwind(Arrays.asList(expressions)).as(\"n\").returning(Cypher.name(\"n\")).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"UNWIND [1, true, false] AS n RETURN n\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderLeadingUnwindWithUpdate() {\n\n\t\t\tStatement statement = Cypher.unwind(Cypher.literalOf(1), Cypher.literalTrue(), Cypher.literalFalse())\n\t\t\t\t.as(\"n\")\n\t\t\t\t.merge(BIKE_NODE.withProperties(\"b\", Cypher.name(\"n\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"UNWIND [1, true, false] AS n MERGE (b:`Bike` {b: n}) RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderLeadingUnwindWithCreate() {\n\n\t\t\tStatement statement = Cypher.unwind(Cypher.literalOf(1), Cypher.literalTrue(), Cypher.literalFalse())\n\t\t\t\t.as(\"n\")\n\t\t\t\t.create(BIKE_NODE.withProperties(\"b\", Cypher.name(\"n\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"UNWIND [1, true, false] AS n CREATE (b:`Bike` {b: n}) RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderUnwind() {\n\n\t\t\tAliasedExpression collected = Cypher.collect(BIKE_NODE).as(\"collected\");\n\t\t\tStatement statement = Cypher.match(BIKE_NODE)\n\t\t\t\t.with(collected)\n\t\t\t\t.unwind(collected)\n\t\t\t\t.as(\"x\")\n\t\t\t\t.with(\"x\")\n\t\t\t\t.delete(Cypher.name(\"x\"))\n\t\t\t\t.returning(\"x\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (b:`Bike`) WITH collect(b) AS collected UNWIND collected AS x WITH x DELETE x RETURN x\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass Unions {\n\n\t\t@Test\n\t\tvoid shouldRenderUnions() {\n\n\t\t\tStatement statement1 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"a\").isEqualTo(Cypher.literalOf(\"A\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tStatement statement2 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"b\").isEqualTo(Cypher.literalOf(\"B\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tStatement statement3 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"c\").isEqualTo(Cypher.literalOf(\"C\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.union(statement1, statement2, statement3);\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (b:`Bike`) WHERE b.a = 'A' RETURN b UNION MATCH (b:`Bike`) WHERE b.b = 'B' RETURN b UNION MATCH (b:`Bike`) WHERE b.c = 'C' RETURN b\");\n\t\t}\n\n\t\t@Test // GH-189\n\t\tvoid shouldRenderUnionsBasedOnStatementCollections() {\n\n\t\t\tStatement statement1 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"a\").isEqualTo(Cypher.literalOf(\"A\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tStatement statement2 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"b\").isEqualTo(Cypher.literalOf(\"B\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tStatement statement3 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"c\").isEqualTo(Cypher.literalOf(\"C\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\t\t\tStatement statement;\n\t\t\tStatement[] statements = { statement1, statement2, statement3 };\n\t\t\tstatement = Cypher.union(Arrays.asList(statements));\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (b:`Bike`) WHERE b.a = 'A' RETURN b UNION MATCH (b:`Bike`) WHERE b.b = 'B' RETURN b UNION MATCH (b:`Bike`) WHERE b.c = 'C' RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldRenderAllUnions() {\n\n\t\t\tStatement statement1 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"a\").isEqualTo(Cypher.literalOf(\"A\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tStatement statement2 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"b\").isEqualTo(Cypher.literalOf(\"B\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.unionAll(statement1, statement2);\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (b:`Bike`) WHERE b.a = 'A' RETURN b UNION ALL MATCH (b:`Bike`) WHERE b.b = 'B' RETURN b\");\n\t\t}\n\n\t\t@Test // GH-189\n\t\tvoid shouldRenderAllUnionsBasedOnStatementCollections() {\n\n\t\t\tStatement statement1 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"a\").isEqualTo(Cypher.literalOf(\"A\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tStatement statement2 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"b\").isEqualTo(Cypher.literalOf(\"B\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tStatement statement;\n\t\t\tStatement[] statements = { statement1, statement2 };\n\t\t\tstatement = Cypher.unionAll(Arrays.asList(statements));\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (b:`Bike`) WHERE b.a = 'A' RETURN b UNION ALL MATCH (b:`Bike`) WHERE b.b = 'B' RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldAppendToExistingUnions() {\n\n\t\t\tStatement statement1 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"a\").isEqualTo(Cypher.literalOf(\"A\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tStatement statement2 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"b\").isEqualTo(Cypher.literalOf(\"B\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.unionAll(statement1, statement2);\n\n\t\t\tStatement statement3 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"c\").isEqualTo(Cypher.literalOf(\"C\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tStatement statement4 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"d\").isEqualTo(Cypher.literalOf(\"D\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tstatement = Cypher.unionAll(statement, statement3, statement4);\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (b:`Bike`) WHERE b.a = 'A' RETURN b UNION ALL MATCH (b:`Bike`) WHERE b.b = 'B' RETURN b UNION ALL MATCH (b:`Bike`) WHERE b.c = 'C' RETURN b UNION ALL MATCH (b:`Bike`) WHERE b.d = 'D' RETURN b\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldNotMix() {\n\n\t\t\tStatement statement1 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"a\").isEqualTo(Cypher.literalOf(\"A\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tStatement statement2 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"b\").isEqualTo(Cypher.literalOf(\"B\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher.unionAll(statement1, statement2);\n\n\t\t\tStatement statement3 = Cypher.match(BIKE_NODE)\n\t\t\t\t.where(BIKE_NODE.property(\"c\").isEqualTo(Cypher.literalOf(\"C\")))\n\t\t\t\t.returning(BIKE_NODE)\n\t\t\t\t.build();\n\n\t\t\t// noinspection ResultOfMethodCallIgnored\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.union(statement, statement3))\n\t\t\t\t.withMessage(\"Cannot mix union and union all!\");\n\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass MapProjections {\n\n\t\t@Test\n\t\tvoid asterisk() {\n\n\t\t\tStatement statement;\n\t\t\tNode n = Cypher.anyNode(\"n\");\n\n\t\t\tstatement = Cypher.match(n).returning(n.project(Cypher.asterisk())).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (n) RETURN n{.*}\");\n\t\t}\n\n\t\t@SuppressWarnings(\"ResultOfMethodCallIgnored\")\n\t\t@Test\n\t\tvoid invalid() {\n\n\t\t\tString expectedMessage = \"FunctionInvocation{cypher=elementId(n)} of type class org.neo4j.cypherdsl.core.FunctionInvocation cannot be used with an implicit name as map entry.\";\n\t\t\tNode n = Cypher.anyNode(\"n\");\n\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> n.project(Cypher.elementId(n)))\n\t\t\t\t.withMessage(expectedMessage);\n\t\t\tassertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> n.project(\"a\", Cypher.mapOf(\"a\", Cypher.literalOf(\"b\")), Cypher.elementId(n)))\n\t\t\t\t.withMessage(expectedMessage);\n\t\t}\n\n\t\t@Nested\n\t\tclass OnNodes {\n\n\t\t\t@Test\n\t\t\tvoid simple() {\n\n\t\t\t\tStatement statement;\n\t\t\t\tNode n = Cypher.anyNode(\"n\");\n\n\t\t\t\tstatement = Cypher.match(n)\n\t\t\t\t\t.returning(n.project(\"__internalNeo4jId__\", Cypher.elementId(n), \"name\"))\n\t\t\t\t\t.build();\n\t\t\t\tvar renderer = Renderer.getRenderer(NEO5J_CONFIG);\n\t\t\t\tassertThat(renderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (n) RETURN n{__internalNeo4jId__: elementId(n), .name}\");\n\n\t\t\t\tstatement = Cypher.match(n)\n\t\t\t\t\t.returning(n.project(\"name\", \"__internalNeo4jId__\", Cypher.elementId(n)))\n\t\t\t\t\t.build();\n\t\t\t\tassertThat(renderer.render(statement))\n\t\t\t\t\t.isEqualTo(\"MATCH (n) RETURN n{.name, __internalNeo4jId__: elementId(n)}\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid doc21221() {\n\n\t\t\t\tString expected = \"MATCH (actor:`Person` {name: 'Tom Hanks'})-[:`ACTED_IN`]->(movie:`Movie`) RETURN actor{.name, .realName, movies: collect(movie{.title, .released})}\";\n\n\t\t\t\tStatement statement;\n\t\t\t\tNode actor = Cypher.node(\"Person\").named(\"actor\");\n\t\t\t\tNode movie = Cypher.node(\"Movie\").named(\"movie\");\n\n\t\t\t\tstatement = Cypher\n\t\t\t\t\t.match(actor.withProperties(\"name\", Cypher.literalOf(\"Tom Hanks\"))\n\t\t\t\t\t\t.relationshipTo(movie, \"ACTED_IN\"))\n\t\t\t\t\t.returning(actor.project(\"name\", \"realName\", \"movies\",\n\t\t\t\t\t\t\tCypher.collect(movie.project(\"title\", \"released\"))))\n\t\t\t\t\t.build();\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\t\tstatement = Cypher\n\t\t\t\t\t.match(actor.withProperties(\"name\", Cypher.literalOf(\"Tom Hanks\"))\n\t\t\t\t\t\t.relationshipTo(movie, \"ACTED_IN\"))\n\t\t\t\t\t.returning(actor.project(\"name\", \"realName\", \"movies\",\n\t\t\t\t\t\t\tCypher.collect(movie.project(movie.property(\"title\"), movie.property(\"released\")))))\n\t\t\t\t\t.build();\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\t\tstatement = Cypher\n\t\t\t\t\t.match(actor.withProperties(\"name\", Cypher.literalOf(\"Tom Hanks\"))\n\t\t\t\t\t\t.relationshipTo(movie, \"ACTED_IN\"))\n\t\t\t\t\t.returning(actor.project(\"name\", \"realName\", \"movies\",\n\t\t\t\t\t\t\tCypher.collect(movie.project(\"title\", \"year\", movie.property(\"released\")))))\n\t\t\t\t\t.build();\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH (actor:`Person` {name: 'Tom Hanks'})-[:`ACTED_IN`]->(movie:`Movie`) RETURN actor{.name, .realName, movies: collect(movie{.title, year: movie.released})}\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid nested() {\n\n\t\t\t\tStatement statement;\n\t\t\t\tNode n = Cypher.node(\"Person\").named(\"p\");\n\t\t\t\tNode m = Cypher.node(\"Movie\").named(\"m\");\n\n\t\t\t\tstatement = Cypher.match(n.relationshipTo(m, \"ACTED_IN\"))\n\t\t\t\t\t.returning(n.project(\"__internalNeo4jId__\", Cypher.elementId(n), \"name\", \"nested\",\n\t\t\t\t\t\t\tm.project(\"title\", \"__internalNeo4jId__\", Cypher.elementId(m))))\n\t\t\t\t\t.build();\n\t\t\t\tassertThat(Renderer.getRenderer(NEO5J_CONFIG).render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH (p:`Person`)-[:`ACTED_IN`]->(m:`Movie`) RETURN p{__internalNeo4jId__: elementId(p), .name, nested: m{.title, __internalNeo4jId__: elementId(m)}}\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid requiredSymbolicNameShouldBeGenerated() {\n\n\t\t\t\tNode person = Cypher.node(\"Person\");\n\t\t\t\tStatement statement = Cypher.match(person).returning(person.project(\"something\")).build();\n\t\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t\t.matches(\"MATCH \\\\([a-zA-Z].*\\\\d{3}:`Person`\\\\) RETURN [a-zA-Z].*\\\\d{3}\\\\{\\\\.something}\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid generatedSymbolicNameMustPreventNodeContentDoubleRenderingAswWell() {\n\n\t\t\t\tNode person = Cypher.node(\"Person\");\n\t\t\t\tassertThat(person.getRequiredSymbolicName()).isNotNull();\n\t\t\t\tNode movie = Cypher.node(\"Movie\");\n\t\t\t\tassertThat(movie.getRequiredSymbolicName()).isNotNull();\n\t\t\t\tRelationship directed = person.relationshipTo(movie, \"DIRECTED\");\n\t\t\t\tRelationship actedIn = person.relationshipTo(movie, \"ACTED_IN\");\n\t\t\t\tStatement statement = Cypher.match(directed).match(actedIn).returning(directed, actedIn).build();\n\n\t\t\t\tassertThat(cypherRenderer.render(statement)).matches(\n\t\t\t\t\t\t\"MATCH \\\\(\\\\w+:`Person`\\\\)-\\\\[\\\\w+:`DIRECTED`]->\\\\(\\\\w+:`Movie`\\\\) MATCH \\\\(\\\\w+\\\\)-\\\\[\\\\w+:`ACTED_IN`]->\\\\(\\\\w+\\\\) RETURN \\\\w+, \\\\w+\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid addedProjections() {\n\n\t\t\t\tStatement statement;\n\t\t\t\tNode p = Cypher.node(\"Person\").named(\"p\");\n\t\t\t\tNode m = Cypher.node(\"Movie\").named(\"m\");\n\t\t\t\tRelationship rel = p.relationshipTo(m, \"ACTED_IN\").named(\"r\");\n\n\t\t\t\tstatement = Cypher.match(rel)\n\t\t\t\t\t.returning(p.project(\"__internalNeo4jId__\", Cypher.elementId(p), \"name\")\n\t\t\t\t\t\t.and(rel)\n\t\t\t\t\t\t.and(m)\n\t\t\t\t\t\t.and(p.property(\"foo\"))\n\t\t\t\t\t\t.and(\"a\", p.property(\"x\")))\n\t\t\t\t\t.build();\n\t\t\t\tassertThat(Renderer.getRenderer(NEO5J_CONFIG).render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH (p:`Person`)-[r:`ACTED_IN`]->(m:`Movie`) RETURN p{__internalNeo4jId__: elementId(p), .name, r, m, .foo, a: p.x}\");\n\t\t\t}\n\n\t\t}\n\n\t\t@Nested\n\t\tclass OnRelationShips {\n\n\t\t\t@Test\n\t\t\tvoid simple() {\n\n\t\t\t\tStatement statement;\n\t\t\t\tNode n = Cypher.node(\"Person\").named(\"p\");\n\t\t\t\tNode m = Cypher.node(\"Movie\").named(\"m\");\n\t\t\t\tRelationship rel = n.relationshipTo(m, \"ACTED_IN\").named(\"r\");\n\n\t\t\t\tstatement = Cypher.match(rel)\n\t\t\t\t\t.returning(rel.project(\"__internalNeo4jId__\", Cypher.elementId(rel), \"roles\"))\n\t\t\t\t\t.build();\n\t\t\t\tassertThat(Renderer.getRenderer(NEO5J_CONFIG).render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH (p:`Person`)-[r:`ACTED_IN`]->(m:`Movie`) RETURN r{__internalNeo4jId__: elementId(r), .roles}\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid nested() {\n\n\t\t\t\tStatement statement;\n\t\t\t\tNode n = Cypher.node(\"Person\").named(\"p\");\n\t\t\t\tNode m = Cypher.node(\"Movie\").named(\"m\");\n\t\t\t\tRelationship rel = n.relationshipTo(m, \"ACTED_IN\").named(\"r\");\n\n\t\t\t\tstatement = Cypher.match(rel)\n\t\t\t\t\t.returning(m.project(\"title\", \"roles\",\n\t\t\t\t\t\t\trel.project(\"__internalNeo4jId__\", Cypher.elementId(rel), \"roles\")))\n\t\t\t\t\t.build();\n\t\t\t\tassertThat(Renderer.getRenderer(NEO5J_CONFIG).render(statement)).isEqualTo(\n\t\t\t\t\t\t\"MATCH (p:`Person`)-[r:`ACTED_IN`]->(m:`Movie`) RETURN m{.title, roles: r{__internalNeo4jId__: elementId(r), .roles}}\");\n\t\t\t}\n\n\t\t\t@Test\n\t\t\tvoid requiredSymbolicNameShouldBeGenerated() {\n\n\t\t\t\tNode n = Cypher.node(\"Person\");\n\t\t\t\tNode m = Cypher.node(\"Movie\");\n\t\t\t\tRelationship rel = n.relationshipTo(m, \"ACTED_IN\");\n\n\t\t\t\tStatement statement = Cypher.match(rel).returning(rel.project(\"something\")).build();\n\t\t\t\tassertThat(cypherRenderer.render(statement)).matches(\n\t\t\t\t\t\t\"MATCH \\\\(:`Person`\\\\)-\\\\[[a-zA-Z]*\\\\d{3}:`ACTED_IN`]->\\\\(:`Movie`\\\\) RETURN [a-zA-Z]*\\\\d{3}\\\\{\\\\.something}\");\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass WithAndOrder {\n\n\t\t@Test\n\t\tvoid orderOnWithShouldWork() {\n\n\t\t\tSortItem byTitle = Cypher.sort(Cypher.property(\"m\", \"title\"));\n\t\t\tSortItem byName = Cypher.sort(Cypher.property(\"p\", \"name\"));\n\n\t\t\tSupplier<StatementBuilder.OrderableOngoingReadingAndWithWithoutWhere> baseStatementSupplier = () -> Cypher\n\t\t\t\t.match(Cypher.node(\"Movie\")\n\t\t\t\t\t.named(\"m\")\n\t\t\t\t\t.relationshipFrom(Cypher.node(\"Person\").named(\"p\"), \"ACTED_IN\")\n\t\t\t\t\t.named(\"r\"))\n\t\t\t\t.with(Cypher.name(\"m\"), Cypher.name(\"p\"));\n\n\t\t\tfor (StatementBuilder.OrderableOngoingReadingAndWithWithWhere orderedStatement : new StatementBuilder.OrderableOngoingReadingAndWithWithWhere[] {\n\t\t\t\t\tbaseStatementSupplier.get().orderBy(byTitle, byName),\n\t\t\t\t\tbaseStatementSupplier.get().orderBy(Arrays.asList(byTitle, byName)) }) {\n\t\t\t\tStatement statement = orderedStatement\n\t\t\t\t\t.returning(Cypher.property(\"m\", \"title\").as(\"movie\"),\n\t\t\t\t\t\t\tCypher.collect(Cypher.property(\"p\", \"name\")).as(\"actors\"))\n\t\t\t\t\t.build();\n\t\t\t\tString expected = \"MATCH (m:`Movie`)<-[r:`ACTED_IN`]-(p:`Person`) WITH m, p ORDER BY m.title, p.name RETURN m.title AS movie, collect(p.name) AS actors\";\n\t\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t\t}\n\t\t}\n\n\t\t@Test\n\t\tvoid concatenatedOrdering() {\n\t\t\tStatement statement;\n\t\t\tstatement = Cypher\n\t\t\t\t.match(Cypher.node(\"Movie\")\n\t\t\t\t\t.named(\"m\")\n\t\t\t\t\t.relationshipFrom(Cypher.node(\"Person\").named(\"p\"), \"ACTED_IN\")\n\t\t\t\t\t.named(\"r\"))\n\t\t\t\t.with(Cypher.name(\"m\"), Cypher.name(\"p\"))\n\t\t\t\t.orderBy(Cypher.property(\"m\", \"title\"))\n\t\t\t\t.ascending()\n\t\t\t\t.and(Cypher.property(\"p\", \"name\"))\n\t\t\t\t.ascending()\n\t\t\t\t.returning(Cypher.property(\"m\", \"title\").as(\"movie\"),\n\t\t\t\t\t\tCypher.collect(Cypher.property(\"p\", \"name\")).as(\"actors\"))\n\t\t\t\t.build();\n\n\t\t\tString expected = \"MATCH (m:`Movie`)<-[r:`ACTED_IN`]-(p:`Person`) WITH m, p ORDER BY m.title ASC, p.name ASC RETURN m.title AS movie, collect(p.name) AS actors\";\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass ListComprehensions {\n\n\t\t@Test\n\t\tvoid simple() {\n\n\t\t\tSymbolicName name = Cypher.name(\"a\");\n\t\t\tStatement statement = Cypher\n\t\t\t\t.returning(Cypher.listWith(name)\n\t\t\t\t\t.in(Cypher.listOf(Cypher.literalOf(1), Cypher.literalOf(2), Cypher.literalOf(3),\n\t\t\t\t\t\t\tCypher.literalOf(4)))\n\t\t\t\t\t.returning())\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN [a IN [1, 2, 3, 4]]\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withReturning() {\n\n\t\t\tSymbolicName name = Cypher.name(\"a\");\n\t\t\tStatement statement = Cypher\n\t\t\t\t.returning(Cypher.listWith(name)\n\t\t\t\t\t.in(Cypher.listOf(Cypher.literalOf(1), Cypher.literalOf(2), Cypher.literalOf(3),\n\t\t\t\t\t\t\tCypher.literalOf(4)))\n\t\t\t\t\t.returning(name.remainder(Cypher.literalOf(2))))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN [a IN [1, 2, 3, 4] | (a % 2)]\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withWhere() {\n\n\t\t\tSymbolicName name = Cypher.name(\"a\");\n\t\t\tStatement statement = Cypher\n\t\t\t\t.returning(Cypher.listWith(name)\n\t\t\t\t\t.in(Cypher.listOf(Cypher.literalOf(1), Cypher.literalOf(2), Cypher.literalOf(3),\n\t\t\t\t\t\t\tCypher.literalOf(4)))\n\t\t\t\t\t.where(name.gt(Cypher.literalOf(2)))\n\t\t\t\t\t.returning())\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN [a IN [1, 2, 3, 4] WHERE a > 2]\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withWhereAndReturning() {\n\n\t\t\tSymbolicName name = Cypher.name(\"a\");\n\t\t\tStatement statement = Cypher\n\t\t\t\t.returning(Cypher.listWith(name)\n\t\t\t\t\t.in(Cypher.listOf(Cypher.literalOf(1), Cypher.literalOf(2), Cypher.literalOf(3),\n\t\t\t\t\t\t\tCypher.literalOf(4)))\n\t\t\t\t\t.where(name.gt(Cypher.literalOf(2)))\n\t\t\t\t\t.returning(name.remainder(Cypher.literalOf(2))))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN [a IN [1, 2, 3, 4] WHERE a > 2 | (a % 2)]\");\n\t\t}\n\n\t\t@Test // GH-189\n\t\tvoid simpleWithCollection() {\n\n\t\t\tSymbolicName name = Cypher.name(\"a\");\n\t\t\tExpression[] expressions = { Cypher.literalOf(1), Cypher.literalOf(2), Cypher.literalOf(3),\n\t\t\t\t\tCypher.literalOf(4) };\n\t\t\tStatement statement = Cypher\n\t\t\t\t.returning(Cypher.listWith(name).in(Cypher.listOf(Arrays.asList(expressions))).returning())\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN [a IN [1, 2, 3, 4]]\");\n\t\t}\n\n\t\t@Test\n\t\tvoid docsExample() {\n\n\t\t\tSymbolicName name = Cypher.name(\"x\");\n\t\t\tStatement statement;\n\n\t\t\tstatement = Cypher\n\t\t\t\t.returning(Cypher.listWith(name)\n\t\t\t\t\t.in(Cypher.range(Cypher.literalOf(0), Cypher.literalOf(10)))\n\t\t\t\t\t.where(name.remainder(Cypher.literalOf(2)).isEqualTo(Cypher.literalOf(0)))\n\t\t\t\t\t.returning(name.pow(Cypher.literalOf(3)))\n\t\t\t\t\t.as(\"result\"))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"RETURN [x IN range(0, 10) WHERE (x % 2) = 0 | x^3] AS result\");\n\n\t\t\tstatement = Cypher\n\t\t\t\t.returning(Cypher.listWith(name)\n\t\t\t\t\t.in(Cypher.range(Cypher.literalOf(0), Cypher.literalOf(10)))\n\t\t\t\t\t.where(name.remainder(Cypher.literalOf(2)).isEqualTo(Cypher.literalOf(0)))\n\t\t\t\t\t.returning()\n\t\t\t\t\t.as(\"result\"))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"RETURN [x IN range(0, 10) WHERE (x % 2) = 0] AS result\");\n\n\t\t\tstatement = Cypher\n\t\t\t\t.returning(Cypher.listWith(name)\n\t\t\t\t\t.in(Cypher.range(Cypher.literalOf(0), Cypher.literalOf(10)))\n\t\t\t\t\t.returning(name.pow(Cypher.literalOf(3)))\n\t\t\t\t\t.as(\"result\"))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN [x IN range(0, 10) | x^3] AS result\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass PatternComprehensions {\n\n\t\t@Test\n\t\tvoid simple() {\n\n\t\t\tStatement statement;\n\t\t\tNode a = Cypher.node(\"Person\").withProperties(\"name\", Cypher.literalOf(\"Keanu Reeves\")).named(\"a\");\n\t\t\tNode b = Cypher.anyNode(\"b\");\n\n\t\t\tstatement = Cypher.match(a)\n\t\t\t\t.returning(Cypher.listBasedOn(a.relationshipBetween(b)).returning(b.property(\"released\")).as(\"years\"))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) | b.released] AS years\");\n\t\t}\n\n\t\t@Test\n\t\tvoid simpleWithWhere() {\n\n\t\t\tStatement statement;\n\t\t\tNode a = Cypher.node(\"Person\").withProperties(\"name\", Cypher.literalOf(\"Keanu Reeves\")).named(\"a\");\n\t\t\tNode b = Cypher.anyNode(\"b\");\n\n\t\t\tstatement = Cypher.match(a)\n\t\t\t\t.returning(Cypher.listBasedOn(a.relationshipBetween(b))\n\t\t\t\t\t.where(b.hasLabels(\"Movie\"))\n\t\t\t\t\t.returning(b.property(\"released\"))\n\t\t\t\t\t.as(\"years\"))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) WHERE b:`Movie` | b.released] AS years\");\n\t\t}\n\n\t\t@Test\n\t\tvoid nested() {\n\n\t\t\tStatement statement;\n\n\t\t\tNode n = Cypher.node(\"Person\").named(\"n\");\n\t\t\tNode o1 = Cypher.node(\"Organisation\").named(\"o1\");\n\t\t\tNode l1 = Cypher.node(\"Location\").named(\"l1\");\n\t\t\tNode p2 = Cypher.node(\"Person\").named(\"p2\");\n\n\t\t\tRelationship r_f1 = n.relationshipTo(o1, \"FOUNDED\").named(\"r_f1\");\n\t\t\tRelationship r_e1 = n.relationshipTo(o1, \"EMPLOYED_BY\").named(\"r_e1\");\n\t\t\tRelationship r_l1 = n.relationshipTo(l1, \"LIVES_AT\").named(\"r_l1\");\n\t\t\tRelationship r_l2 = l1.relationshipFrom(p2, \"LIVES_AT\").named(\"r_l2\");\n\n\t\t\tstatement = Cypher.match(n)\n\t\t\t\t.returning(n.getRequiredSymbolicName(),\n\t\t\t\t\t\tCypher.listOf(Cypher.listBasedOn(r_f1).returning(r_f1, o1),\n\t\t\t\t\t\t\t\tCypher.listBasedOn(r_e1).returning(r_e1, o1),\n\t\t\t\t\t\t\t\tCypher.listBasedOn(r_l1)\n\t\t\t\t\t\t\t\t\t.returning(r_l1.getRequiredSymbolicName(), l1.getRequiredSymbolicName(),\n\t\t\t\t\t\t\t\t\t\t\t// The building of the statement works with\n\t\t\t\t\t\t\t\t\t\t\t// and without the outer list,\n\t\t\t\t\t\t\t\t\t\t\t// I'm not sure if it would be necessary for\n\t\t\t\t\t\t\t\t\t\t\t// the result, but as I took the query from\n\t\t\t\t\t\t\t\t\t\t\t// Neo4j-OGM, I'd like to keep it\n\t\t\t\t\t\t\t\t\t\t\tCypher.listOf(Cypher.listBasedOn(r_l2).returning(r_l2, p2)))))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n:`Person`) RETURN n, [[(n)-[r_f1:`FOUNDED`]->(o1:`Organisation`) | [r_f1, o1]], [(n)-[r_e1:`EMPLOYED_BY`]->(o1:`Organisation`) | [r_e1, o1]], [(n)-[r_l1:`LIVES_AT`]->(l1:`Location`) | [r_l1, l1, [[(l1)<-[r_l2:`LIVES_AT`]-(p2:`Person`) | [r_l2, p2]]]]]]\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass MultipleLabels {\n\n\t\t@Test\n\t\tvoid matchWithMultipleLabels() {\n\t\t\tNode node = Cypher.node(\"a\", \"b\", \"c\").named(\"n\");\n\t\t\tStatement statement = Cypher.match(node).returning(node).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (n:`a`:`b`:`c`) RETURN n\");\n\t\t}\n\n\t\t@Test\n\t\tvoid createWithMultipleLabels() {\n\t\t\tNode node = Cypher.node(\"a\", \"b\", \"c\").named(\"n\");\n\t\t\tStatement statement = Cypher.create(node).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"CREATE (n:`a`:`b`:`c`)\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass Case {\n\n\t\t@Test\n\t\tvoid simpleCase() {\n\t\t\tNode node = Cypher.node(\"a\").named(\"n\");\n\t\t\tStatement statement = Cypher.match(node)\n\t\t\t\t.where(Cypher.caseExpression(node.property(\"value\"))\n\t\t\t\t\t.when(Cypher.literalOf(\"blubb\"))\n\t\t\t\t\t.then(Cypher.literalTrue())\n\t\t\t\t\t.asCondition())\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (n:`a`) WHERE CASE n.value WHEN 'blubb' THEN true END RETURN n\");\n\t\t}\n\n\t\t@Test\n\t\tvoid simpleCaseWithElse() {\n\t\t\tNode node = Cypher.node(\"a\").named(\"n\");\n\t\t\tStatement statement = Cypher.match(node)\n\t\t\t\t.where(Cypher.caseExpression(node.property(\"value\"))\n\t\t\t\t\t.when(Cypher.literalOf(\"blubb\"))\n\t\t\t\t\t.then(Cypher.literalTrue())\n\t\t\t\t\t.elseDefault(Cypher.literalFalse())\n\t\t\t\t\t.asCondition())\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (n:`a`) WHERE CASE n.value WHEN 'blubb' THEN true ELSE false END RETURN n\");\n\t\t}\n\n\t\t@Test\n\t\tvoid simpleCaseWithMultipleWhenThen() {\n\t\t\tNode node = Cypher.node(\"a\").named(\"n\");\n\t\t\tStatement statement = Cypher.match(node)\n\t\t\t\t.where(Cypher.caseExpression(node.property(\"value\"))\n\t\t\t\t\t.when(Cypher.literalOf(\"blubb\"))\n\t\t\t\t\t.then(Cypher.literalTrue())\n\t\t\t\t\t.when(Cypher.literalOf(\"bla\"))\n\t\t\t\t\t.then(Cypher.literalFalse())\n\t\t\t\t\t.asCondition())\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n:`a`) WHERE CASE n.value WHEN 'blubb' THEN true WHEN 'bla' THEN false END RETURN n\");\n\t\t}\n\n\t\t@Test\n\t\tvoid simpleCaseWithMultipleWhenThenAndElse() {\n\t\t\tNode node = Cypher.node(\"a\").named(\"n\");\n\t\t\tStatement statement = Cypher.match(node)\n\t\t\t\t.where(Cypher.caseExpression(node.property(\"value\"))\n\t\t\t\t\t.when(Cypher.literalOf(\"blubb\"))\n\t\t\t\t\t.then(Cypher.literalTrue())\n\t\t\t\t\t.when(Cypher.literalOf(\"bla\"))\n\t\t\t\t\t.then(Cypher.literalFalse())\n\t\t\t\t\t.elseDefault(Cypher.literalOf(1))\n\t\t\t\t\t.asCondition())\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n:`a`) WHERE CASE n.value WHEN 'blubb' THEN true WHEN 'bla' THEN false ELSE 1 END RETURN n\");\n\t\t}\n\n\t\t@Test\n\t\tvoid genericCase() {\n\t\t\tNode node = Cypher.node(\"a\").named(\"n\");\n\t\t\tStatement statement = Cypher.match(node)\n\t\t\t\t.where(Cypher.caseExpression()\n\t\t\t\t\t.when(node.property(\"value\").isEqualTo(Cypher.literalOf(\"blubb\")))\n\t\t\t\t\t.then(Cypher.literalTrue())\n\t\t\t\t\t.asCondition())\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (n:`a`) WHERE CASE WHEN n.value = 'blubb' THEN true END RETURN n\");\n\t\t}\n\n\t\t@Test\n\t\tvoid genericCaseWithElse() {\n\t\t\tNode node = Cypher.node(\"a\").named(\"n\");\n\t\t\tStatement statement = Cypher.match(node)\n\t\t\t\t.where(Cypher.caseExpression()\n\t\t\t\t\t.when(node.property(\"value\").isEqualTo(Cypher.literalOf(\"blubb\")))\n\t\t\t\t\t.then(Cypher.literalTrue())\n\t\t\t\t\t.elseDefault(Cypher.literalFalse())\n\t\t\t\t\t.asCondition())\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (n:`a`) WHERE CASE WHEN n.value = 'blubb' THEN true ELSE false END RETURN n\");\n\t\t}\n\n\t\t@Test\n\t\tvoid genericCaseWithMultipleWhenThen() {\n\t\t\tNode node = Cypher.node(\"a\").named(\"n\");\n\t\t\tStatement statement = Cypher.match(node)\n\t\t\t\t.where(Cypher.caseExpression()\n\t\t\t\t\t.when(node.property(\"value\").isEqualTo(Cypher.literalOf(\"blubb\")))\n\t\t\t\t\t.then(Cypher.literalTrue())\n\t\t\t\t\t.when(node.property(\"value\").isEqualTo(Cypher.literalOf(\"bla\")))\n\t\t\t\t\t.then(Cypher.literalFalse())\n\t\t\t\t\t.asCondition())\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n:`a`) WHERE CASE WHEN n.value = 'blubb' THEN true WHEN n.value = 'bla' THEN false END RETURN n\");\n\t\t}\n\n\t\t@Test\n\t\tvoid genericCaseWithMultipleWhenThenAndElse() {\n\t\t\tNode node = Cypher.node(\"a\").named(\"n\");\n\t\t\tStatement statement = Cypher.match(node)\n\t\t\t\t.where(Cypher.caseExpression()\n\t\t\t\t\t.when(node.property(\"value\").isEqualTo(Cypher.literalOf(\"blubb\")))\n\t\t\t\t\t.then(Cypher.literalTrue())\n\t\t\t\t\t.when(node.property(\"value\").isEqualTo(Cypher.literalOf(\"bla\")))\n\t\t\t\t\t.then(Cypher.literalFalse())\n\t\t\t\t\t.elseDefault(Cypher.literalOf(1))\n\t\t\t\t\t.asCondition())\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n:`a`) WHERE CASE WHEN n.value = 'blubb' THEN true WHEN n.value = 'bla' THEN false ELSE 1 END RETURN n\");\n\t\t}\n\n\t\t// from\n\t\t// https://neo4j.com/docs/cypher-manual/current/syntax/expressions/#syntax-simple-case\n\t\t@Test\n\t\tvoid canGetAliasedInReturn() {\n\t\t\tNode node = Cypher.anyNode(\"n\");\n\t\t\tStatement statement = Cypher.match(node)\n\t\t\t\t.returning(Cypher.caseExpression(node.property(\"eyes\"))\n\t\t\t\t\t.when(Cypher.literalOf(\"blue\"))\n\t\t\t\t\t.then(Cypher.literalOf(1))\n\t\t\t\t\t.when(Cypher.literalOf(\"brown\"))\n\t\t\t\t\t.then(Cypher.literalOf(2))\n\t\t\t\t\t.elseDefault(Cypher.literalOf(3))\n\t\t\t\t\t.as(\"result\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (n) RETURN CASE n.eyes WHEN 'blue' THEN 1 WHEN 'brown' THEN 2 ELSE 3 END AS result\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass NamedPaths {\n\n\t\t@Test\n\t\tvoid selectorShouldBeSensible() {\n\t\t\tvar patternElement = Cypher.node(\"M\").relationshipFrom(Cypher.node(\"N\")).named(\"r\");\n\t\t\tvar namedPath = NamedPath.select(PatternSelector.any(), patternElement);\n\t\t\tassertThat(RendererBridge.render(namedPath))\n\t\t\t\t.matches(\"NamedPath\\\\{cypher=.+ = ANY \\\\(:M\\\\)<-\\\\[r]-\\\\(:N\\\\)}\");\n\t\t}\n\n\t\t@Test\n\t\tvoid doc3148() {\n\n\t\t\t// See docs\n\t\t\tNamedPath p = Cypher.path(\"p\")\n\t\t\t\t.definedBy(Cypher.anyNode(\"michael\")\n\t\t\t\t\t.withProperties(\"name\", Cypher.literalOf(\"Michael Douglas\"))\n\t\t\t\t\t.relationshipTo(Cypher.anyNode()));\n\t\t\tStatement statement = Cypher.match(p).returning(p).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH p = (michael {name: 'Michael Douglas'})-->() RETURN p\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldWorkInListComprehensions() {\n\n\t\t\tNamedPath p = Cypher.path(\"p\")\n\t\t\t\t.definedBy(Cypher.anyNode(\"n\").relationshipTo(Cypher.anyNode(), \"LIKES\", \"OWNS\").unbounded());\n\t\t\tStatement statement = Cypher.returning(Cypher.listBasedOn(p).returning(p)).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN [p = (n)-[:`LIKES`|`OWNS`*]->() | p]\");\n\t\t}\n\n\t\t@Test // GH-200\n\t\tvoid shouldWorkWithRelationshipPatterns() {\n\t\t\tRelationshipPattern relationshipPattern = Cypher.anyNode(\"n\").relationshipTo(Cypher.anyNode(\"m\"));\n\t\t\tNamedPath p = Cypher.path(\"p\").definedBy(relationshipPattern);\n\t\t\tStatement statement = Cypher.match(p).returning(p).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH p = (n)-->(m) RETURN p\");\n\t\t}\n\n\t\t@Test // GH-200\n\t\tvoid shouldWorkWithNodes() {\n\t\t\tNamedPath p = Cypher.path(\"p\").definedBy(Cypher.anyNode(\"n\"));\n\t\t\tStatement statement = Cypher.match(p).returning(p).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH p = (n) RETURN p\");\n\t\t}\n\n\t\t@Test // GH-200\n\t\tvoid shouldDirectlyUseProvidedNamedPaths() {\n\t\t\tNamedPath p = Cypher.path(\"p\").definedBy(Cypher.anyNode(\"n\"));\n\t\t\tNamedPath x = Cypher.path(\"x\").definedBy(p);\n\t\t\tStatement statement = Cypher.match(x).returning(p).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH p = (n) RETURN p\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass Predicatez {\n\n\t\t@Test\n\t\tvoid allShouldWork() {\n\n\t\t\tNamedPath p = Cypher.path(\"p\")\n\t\t\t\t.definedBy(Cypher.anyNode(\"a\").relationshipTo(Cypher.anyNode(\"b\")).min(1).max(3));\n\t\t\tStatement statement = Cypher.match(p)\n\t\t\t\t.where(Cypher.property(\"a\", \"name\").isEqualTo(Cypher.literalOf(\"Alice\")))\n\t\t\t\t.and(Cypher.property(\"b\", \"name\").isEqualTo(Cypher.literalOf(\"Daniel\")))\n\t\t\t\t.and(Cypher.all(\"x\").in(Cypher.nodes(p)).where(Cypher.property(\"x\", \"age\").gt(Cypher.literalOf(30))))\n\t\t\t\t.returning(p)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH p = (a)-[*1..3]->(b) WHERE (a.name = 'Alice' AND b.name = 'Daniel' AND all(x IN nodes(p) WHERE x.age > 30)) RETURN p\");\n\t\t}\n\n\t\t@Test\n\t\tvoid anyShouldWork() {\n\n\t\t\tNode a = Cypher.anyNode(\"a\");\n\t\t\tStatement statement = Cypher.match(a)\n\t\t\t\t.where(Cypher.property(\"a\", \"name\").isEqualTo(Cypher.literalOf(\"Eskil\")))\n\t\t\t\t.and(Cypher.any(\"x\").in(a.property(\"array\")).where(Cypher.name(\"x\").isEqualTo(Cypher.literalOf(\"one\"))))\n\t\t\t\t.returning(a.property(\"name\"), a.property(\"array\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (a) WHERE (a.name = 'Eskil' AND any(x IN a.array WHERE x = 'one')) RETURN a.name, a.array\");\n\t\t}\n\n\t\t@Test\n\t\tvoid noneShouldWork() {\n\n\t\t\tNamedPath p = Cypher.path(\"p\")\n\t\t\t\t.definedBy(Cypher.anyNode(\"a\").relationshipTo(Cypher.anyNode(\"b\")).min(1).max(3));\n\t\t\tStatement statement = Cypher.match(p)\n\t\t\t\t.where(Cypher.property(\"a\", \"name\").isEqualTo(Cypher.literalOf(\"Alice\")))\n\t\t\t\t.and(Cypher.none(\"x\")\n\t\t\t\t\t.in(Cypher.nodes(p))\n\t\t\t\t\t.where(Cypher.property(\"x\", \"age\").isEqualTo(Cypher.literalOf(25))))\n\t\t\t\t.returning(p)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH p = (a)-[*1..3]->(b) WHERE (a.name = 'Alice' AND none(x IN nodes(p) WHERE x.age = 25)) RETURN p\");\n\t\t}\n\n\t\t@Test\n\t\tvoid singleShouldWork() {\n\n\t\t\tNamedPath p = Cypher.path(\"p\").definedBy(Cypher.anyNode(\"n\").relationshipTo(Cypher.anyNode(\"b\")));\n\t\t\tStatement statement = Cypher.match(p)\n\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(Cypher.literalOf(\"Alice\")))\n\t\t\t\t.and(Cypher.single(\"var\")\n\t\t\t\t\t.in(Cypher.nodes(p))\n\t\t\t\t\t.where(Cypher.property(\"var\", \"eyes\").isEqualTo(Cypher.literalOf(\"blue\"))))\n\t\t\t\t.returning(p)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH p = (n)-->(b) WHERE (n.name = 'Alice' AND single(var IN nodes(p) WHERE var.eyes = 'blue')) RETURN p\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass ListOperator {\n\n\t\t@Test\n\t\tvoid valueAtShouldWork() {\n\n\t\t\tStatement statement = Cypher.returning(Cypher.valueAt(Cypher.range(0, 10), 3)).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN range(0, 10)[3]\");\n\t\t}\n\n\t\t@Test\n\t\tvoid subListUntilShouldWork() {\n\n\t\t\tStatement statement = Cypher.returning(Cypher.subListUntil(Cypher.range(0, 10), 3)).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN range(0, 10)[..3]\");\n\t\t}\n\n\t\t@Test\n\t\tvoid subListFromShouldWork() {\n\n\t\t\tStatement statement = Cypher.returning(Cypher.subListFrom(Cypher.range(0, 10), -3)).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN range(0, 10)[-3..]\");\n\t\t}\n\n\t\t@Test\n\t\tvoid subListShouldWork() {\n\n\t\t\tStatement statement = Cypher.returning(Cypher.subList(Cypher.range(0, 10), 2, 4)).build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN range(0, 10)[2..4]\");\n\t\t}\n\n\t\t@Test\n\t\tvoid subListUntilExpressionShouldWork() {\n\n\t\t\tStatement statement = Cypher.returning(Cypher.subListUntil(Cypher.range(0, 10), Cypher.parameter(\"end\")))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN range(0, 10)[..$end]\");\n\t\t}\n\n\t\t@Test\n\t\tvoid subListFromExpressionShouldWork() {\n\t\t\tStatement statement = Cypher.returning(Cypher.subListFrom(Cypher.range(0, 10), Cypher.parameter(\"start\")))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN range(0, 10)[$start..]\");\n\t\t}\n\n\t\t@Test\n\t\tvoid subListExpressionShouldWork() {\n\n\t\t\tStatement statement = Cypher\n\t\t\t\t.returning(Cypher.subList(Cypher.range(0, 10), Cypher.parameter(\"start\"), Cypher.parameter(\"end\")))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN range(0, 10)[$start..$end]\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldWorkWithMapProjections() {\n\n\t\t\tNode person = Cypher.node(\"Person\").named(\"person\");\n\t\t\tNode location = Cypher.node(\"Location\").named(\"personLivesIn\");\n\n\t\t\tStatement statement = Cypher.match(person)\n\t\t\t\t.returning(person.project(\"livesIn\",\n\t\t\t\t\t\tCypher.valueAt(Cypher.listBasedOn(person.relationshipTo(location, \"LIVES_IN\"))\n\t\t\t\t\t\t\t.returning(location.project(\"name\")), 0)))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`) RETURN person{livesIn: [(person)-[:`LIVES_IN`]->(personLivesIn:`Location`) | personLivesIn{.name}][0]}\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldSupportExpressions() {\n\n\t\t\tNode person = Cypher.node(\"Person\").named(\"person\");\n\t\t\tNode location = Cypher.node(\"Location\").named(\"personLivesIn\");\n\t\t\tStatement statement = Cypher.match(person)\n\t\t\t\t.returning(person.project(\"livesIn\",\n\t\t\t\t\t\tCypher.subList(\n\t\t\t\t\t\t\t\tCypher.listBasedOn(person.relationshipTo(location, \"LIVES_IN\"))\n\t\t\t\t\t\t\t\t\t.returning(location.project(\"name\")),\n\t\t\t\t\t\t\t\tCypher.parameter(\"personLivedInOffset\"),\n\t\t\t\t\t\t\t\tCypher.parameter(\"personLivedInOffset\").add(Cypher.parameter(\"personLivedInFirst\")))))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`) RETURN person{livesIn: [(person)-[:`LIVES_IN`]->(personLivesIn:`Location`) | personLivesIn{.name}][$personLivedInOffset..($personLivedInOffset + $personLivedInFirst)]}\");\n\t\t}\n\n\t\t@Test\n\t\tvoid propertiesShouldBeAccessibleOnResolvedNodes() {\n\n\t\t\tvar nodes = Cypher.name(\"nodes\");\n\t\t\tvar cypher = Cypher.match(Cypher.node(\"Foo\").named(\"n\"))\n\t\t\t\t.with(Cypher.collect(Cypher.name(\"n\")).as(\"nodes\"))\n\t\t\t\t.returning(Cypher.property(Cypher.valueAt(nodes, 0), \"foo\"))\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\"MATCH (n:`Foo`) WITH collect(n) AS nodes RETURN nodes[0].foo\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass DoubleRendering {\n\n\t\t@Test\n\t\tvoid fragmentOfStatementShouldBeReusable() {\n\n\t\t\tNode personNode = Cypher.node(\"Person\").named(\"p\");\n\t\t\tProperty ageProperty = personNode.property(\"age\");\n\n\t\t\tStatementBuilder.OngoingReadingAndReturn returning = Cypher.match(personNode).returning(\"p\");\n\t\t\tStatement s1 = returning.orderBy(ageProperty.ascending()).limit(1).build();\n\t\t\tStatement s2 = returning.orderBy(ageProperty.descending()).limit(1).build();\n\n\t\t\tassertThat(cypherRenderer.render(s1)).isEqualTo(\"MATCH (p:`Person`) RETURN p ORDER BY p.age ASC LIMIT 1\");\n\t\t\tassertThat(cypherRenderer.render(s2)).isEqualTo(\"MATCH (p:`Person`) RETURN p ORDER BY p.age DESC LIMIT 1\");\n\t\t}\n\n\t\t@Test\n\t\tvoid aliasedFunctionsShouldNotBeRenderedTwiceInProjection() {\n\n\t\t\tNode o = Cypher.node(\"Order\").named(\"o\");\n\t\t\tNode li = Cypher.node(\"LineItem\").named(\"li\");\n\t\t\tRelationship hasLineItems = o.relationshipTo(li).named(\"h\");\n\n\t\t\tvar netAmount = Cypher.sum(li.property(\"price\").multiply(li.property(\"quantity\"))).as(\"netAmount\");\n\t\t\tvar totalAmount = netAmount.multiply(Cypher.literalOf(1).add(Cypher.parameter(\"taxRate\")))\n\t\t\t\t.as(\"totalAmount\");\n\t\t\tStatement statement = Cypher.match(hasLineItems)\n\t\t\t\t.where(o.property(\"id\").isEqualTo(Cypher.parameter(\"id\")))\n\t\t\t\t.with(o.getRequiredSymbolicName(), netAmount, totalAmount)\n\t\t\t\t.returning(o.project(o.property(\"x\"), netAmount, totalAmount,\n\t\t\t\t\t\tnetAmount.multiply(Cypher.parameter(\"taxRate\")).as(\"taxAmount\")))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (o:`Order`)-[h]->(li:`LineItem`) WHERE o.id = $id WITH o, sum((li.price * li.quantity)) AS netAmount, (netAmount * (1 + $taxRate)) AS totalAmount RETURN o{.x, netAmount: netAmount, totalAmount: totalAmount, taxAmount: (netAmount * $taxRate)}\");\n\t\t}\n\n\t\t@Test\n\t\tvoid aliasedFunctionsShouldNotBeRenderedTwiceInReturn() {\n\n\t\t\tNode o = Cypher.node(\"Order\").named(\"o\");\n\t\t\tNode li = Cypher.node(\"LineItem\").named(\"li\");\n\t\t\tRelationship hasLineItems = o.relationshipTo(li).named(\"h\");\n\n\t\t\tvar netAmount = Cypher.sum(li.property(\"price\").multiply(li.property(\"quantity\"))).as(\"netAmount\");\n\t\t\tvar totalAmount = netAmount.multiply(Cypher.literalOf(1).add(Cypher.parameter(\"taxRate\")))\n\t\t\t\t.as(\"totalAmount\");\n\t\t\tStatement statement = Cypher.match(hasLineItems)\n\t\t\t\t.where(o.property(\"id\").isEqualTo(Cypher.parameter(\"id\")))\n\t\t\t\t.with(o.getRequiredSymbolicName(), netAmount, totalAmount)\n\t\t\t\t.returning(netAmount, totalAmount)\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (o:`Order`)-[h]->(li:`LineItem`) WHERE o.id = $id WITH o, sum((li.price * li.quantity)) AS netAmount, (netAmount * (1 + $taxRate)) AS totalAmount RETURN netAmount, totalAmount\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass Foreach {\n\n\t\t@Test\n\t\tvoid basic() {\n\n\t\t\tvar start = Cypher.anyNode(\"start\");\n\t\t\tvar finish = Cypher.anyNode(\"finish\");\n\t\t\tvar p = Cypher.path(\"p\").definedBy(start.relationshipTo(finish).unbounded());\n\t\t\tvar n = Cypher.name(\"n\");\n\t\t\tvar stmnt = Cypher.match(p)\n\t\t\t\t.where(start.property(\"name\")\n\t\t\t\t\t.eq(Cypher.literalOf(\"A\"))\n\t\t\t\t\t.and(finish.property(\"name\").eq(Cypher.literalOf(\"D\"))))\n\t\t\t\t.foreach(n)\n\t\t\t\t.in(Cypher.nodes(p))\n\t\t\t\t.apply(Set.set(n.property(\"marked\").to(Cypher.literalTrue())))\n\t\t\t\t.build();\n\t\t\tassertThat(stmnt.getCypher())\n\t\t\t\t.isEqualTo(\"MATCH p = (start)-[*]->(finish) \" + \"WHERE (start.name = 'A' AND finish.name = 'D') \"\n\t\t\t\t\t\t+ \"FOREACH (n IN nodes(p) | SET n.marked = true)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid mixedWithOtherClauses() {\n\n\t\t\tvar start = Cypher.anyNode(\"start\");\n\t\t\tvar finish = Cypher.anyNode(\"finish\");\n\t\t\tvar p = Cypher.path(\"p\").definedBy(start.relationshipTo(finish).unbounded());\n\t\t\tvar n = Cypher.name(\"n\");\n\t\t\tvar stmnt = Cypher.match(p)\n\t\t\t\t.where(start.property(\"name\")\n\t\t\t\t\t.eq(Cypher.literalOf(\"A\"))\n\t\t\t\t\t.and(finish.property(\"name\").eq(Cypher.literalOf(\"D\"))))\n\t\t\t\t.set(start.property(\"x\").to(Cypher.literalTrue()))\n\t\t\t\t.foreach(n)\n\t\t\t\t.in(Cypher.nodes(p))\n\t\t\t\t.apply(Set.set(n.property(\"marked\").to(Cypher.literalTrue()),\n\t\t\t\t\t\tn.property(\"foo\").to(Cypher.literalOf(\"bar\"))))\n\t\t\t\t.delete(finish)\n\t\t\t\t.build();\n\t\t\tassertThat(stmnt.getCypher()).isEqualTo(\"MATCH p = (start)-[*]->(finish) \"\n\t\t\t\t\t+ \"WHERE (start.name = 'A' AND finish.name = 'D') \" + \"SET start.x = true \"\n\t\t\t\t\t+ \"FOREACH (n IN nodes(p) | SET n.marked = true, n.foo = 'bar') \" + \"DELETE finish\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withWith() {\n\n\t\t\tvar start = Cypher.anyNode(\"start\");\n\t\t\tvar n = Cypher.name(\"n\");\n\t\t\tvar stmnt = Cypher.match(start)\n\t\t\t\t.with(start)\n\t\t\t\t.foreach(n)\n\t\t\t\t.in(Cypher.listOf(start.asExpression()))\n\t\t\t\t.apply(Delete.delete(n))\n\t\t\t\t.build();\n\t\t\t// Probably the worst way to delete a graph I ever wrote down\n\t\t\tassertThat(stmnt.getCypher()).isEqualTo(\"MATCH (start) WITH start FOREACH (n IN [start] | DELETE n)\");\n\t\t}\n\n\t\t@Test\n\t\tvoid inComplexStatement() {\n\n\t\t\tvar configNode = Cypher.node(\"confignode\").withProperties(\"oid\", Cypher.parameter(\"oid\")).named(\"p\");\n\t\t\tvar nodes = Cypher.name(\"nodes\");\n\t\t\tvar node = Cypher.name(\"node\");\n\t\t\tvar relationships = Cypher.name(\"relationships\");\n\t\t\tvar stmnt = Cypher.match(configNode)\n\t\t\t\t.call(\"apoc.path.subgraphAll\")\n\t\t\t\t.withArgs(configNode.getRequiredSymbolicName(),\n\t\t\t\t\t\tCypher.mapOf(\"relationshipFilter\", Cypher.literalOf(\"BELONGS_TO_ARRAY|IN|IN_ARRAY\"), \"minLevel\",\n\t\t\t\t\t\t\t\tCypher.literalOf(1), \"maxLevel\", Cypher.literalOf(3)))\n\t\t\t\t.yield(nodes, relationships)\n\t\t\t\t.foreach(node)\n\t\t\t\t.in(nodes)\n\t\t\t\t.apply(Delete.detachDelete(node))\n\t\t\t\t.returning(nodes)\n\t\t\t\t.build();\n\n\t\t\tvar prettyPrintingRenderer = Renderer.getRenderer(Configuration.prettyPrinting());\n\t\t\tassertThat(prettyPrintingRenderer.render(stmnt)).isEqualTo(\"\"\"\n\t\t\t\t\tMATCH (p:confignode {\n\t\t\t\t\t  oid: $oid\n\t\t\t\t\t}) CALL apoc.path.subgraphAll(p, {\n\t\t\t\t\t  relationshipFilter: 'BELONGS_TO_ARRAY|IN|IN_ARRAY',\n\t\t\t\t\t  minLevel: 1,\n\t\t\t\t\t  maxLevel: 3\n\t\t\t\t\t}) YIELD nodes, relationships FOREACH (node IN nodes | DETACH DELETE node)\n\t\t\t\t\tRETURN nodes\"\"\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass PrettyPrinting {\n\n\t\tprivate final Statement statement;\n\n\t\tPrettyPrinting() {\n\t\t\tNode otherNode = Cypher.anyNode(\"other\");\n\t\t\tthis.statement = Cypher.match(USER_NODE)\n\t\t\t\t.where(USER_NODE.property(\"name\").isEqualTo(Cypher.literalOf(\"Max\")))\n\t\t\t\t.and(USER_NODE.property(\"lastName\").isEqualTo(Cypher.literalOf(\"Mustermann\")))\n\t\t\t\t.and(Cypher.match(USER_NODE.relationshipTo(BIKE_NODE, \"LIKES\"))\n\t\t\t\t\t.where(BIKE_NODE.relationshipTo(Cypher.anyNode(), \"LINK\"))\n\t\t\t\t\t.or(Cypher.match(BIKE_NODE.relationshipTo(Cypher.anyNode(), \"LINK\")).asCondition())\n\t\t\t\t\t.asCondition())\n\t\t\t\t.set(USER_NODE.property(\"lastName\").to(Cypher.parameter(\"newName\")))\n\t\t\t\t.with(USER_NODE)\n\t\t\t\t.match(BIKE_NODE)\n\t\t\t\t.create(USER_NODE.relationshipTo(BIKE_NODE, \"LIKES\"))\n\t\t\t\t.with(USER_NODE)\n\t\t\t\t.call(Cypher.with(USER_NODE)\n\t\t\t\t\t.match(USER_NODE.relationshipTo(Cypher.anyNode(\"x\"), \"SOMETHING\"))\n\t\t\t\t\t.call(Cypher.with(Cypher.anyNode(\"x\"))\n\t\t\t\t\t\t.match(Cypher.anyNode(\"x\").relationshipTo(Cypher.anyNode(\"y\"), \"DEEPER\"))\n\t\t\t\t\t\t.returning(Cypher.anyNode(\"y\").project(\"bar\").as(\"bar\"))\n\t\t\t\t\t\t.build())\n\t\t\t\t\t.returning(Cypher.anyNode(\"x\").project(\"foo\", \"bar\", Cypher.name(\"bar\")).as(\"anyThing\"))\n\t\t\t\t\t.build())\n\t\t\t\t.with(USER_NODE)\n\t\t\t\t.call(Cypher.use(\"movies.actors\",\n\t\t\t\t\t\tCypher.match(Cypher.node(\"Person\").named(\"person\")).returning(\"person\").build()))\n\t\t\t\t.with(USER_NODE)\n\t\t\t\t.returning(USER_NODE.project(\"name\", USER_NODE.property(\"name\"), \"anyThing\", Cypher.name(\"anyThing\"),\n\t\t\t\t\t\t\"nesting1\",\n\t\t\t\t\t\tCypher.mapOf(\"name\", USER_NODE.property(\"name\"), \"nesting2\",\n\t\t\t\t\t\t\t\tCypher.mapOf(\"name\", BIKE_NODE.property(\"name\"), \"pattern\",\n\t\t\t\t\t\t\t\t\t\tCypher.listBasedOn(USER_NODE.relationshipTo(otherNode, \"LIKES\"))\n\t\t\t\t\t\t\t\t\t\t\t.where(otherNode.property(\"foo\").isEqualTo(Cypher.parameter(\"foo\")))\n\t\t\t\t\t\t\t\t\t\t\t.returning(otherNode.project(\"x\", \"y\"))))))\n\t\t\t\t.build();\n\t\t}\n\n\t\t@Test\n\t\tvoid escapingNamesShouldBeOptionalInNonPrettyPrintToo() {\n\n\t\t\tRenderer renderer = Renderer.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).build());\n\t\t\tassertThat(renderer.render(Cypher.match(Cypher.node(\"Fine\").named(\"a\")).returning(\"a\").build()))\n\t\t\t\t.isEqualTo(\"MATCH (a:Fine) RETURN a\");\n\t\t\tassertThat(renderer.render(Cypher.match(Cypher.node(\"Not Fine\").named(\"a\")).returning(\"a\").build()))\n\t\t\t\t.isEqualTo(\"MATCH (a:`Not Fine`) RETURN a\");\n\t\t}\n\n\t\t@Test\n\t\tvoid configurationOfIndentWithShouldWork() {\n\n\t\t\tassertThat(Renderer.getRenderer(Configuration.newConfig().withPrettyPrint(true).withIndentSize(5).build())\n\t\t\t\t.render(Cypher.match(Cypher.node(\"Node\"))\n\t\t\t\t\t.where(Cypher.isTrue())\n\t\t\t\t\t.and(Cypher.isFalse())\n\t\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t\t.build()))\n\t\t\t\t.isEqualTo(\"\"\"\n\t\t\t\t\t\tMATCH (:Node)\n\t\t\t\t\t\tWHERE (true\n\t\t\t\t\t\t     AND false)\n\t\t\t\t\t\tRETURN *\"\"\");\n\t\t}\n\n\t\t@Test\n\t\tvoid prettyPrintingWithDefaultSettingShouldWork() {\n\n\t\t\tassertThat(Renderer.getRenderer(Configuration.prettyPrinting()).render(this.statement)).isEqualTo(\"\"\"\n\t\t\t\t\tMATCH (u:User)\n\t\t\t\t\tWHERE (u.name = 'Max'\n\t\t\t\t\t  AND u.lastName = 'Mustermann'\n\t\t\t\t\t  AND EXISTS {\n\t\t\t\t\t    MATCH (u)-[:LIKES]->(b:Bike)\n\t\t\t\t\t    WHERE ((b)-[:LINK]->()\n\t\t\t\t\t      OR EXISTS {\n\t\t\t\t\t        MATCH (b)-[:LINK]->()\n\t\t\t\t\t      })\n\t\t\t\t\t  })\n\t\t\t\t\tSET u.lastName = $newName\n\t\t\t\t\tWITH u\n\t\t\t\t\tMATCH (b:Bike)\n\t\t\t\t\tCREATE (u)-[:LIKES]->(b)\n\t\t\t\t\tWITH u\n\t\t\t\t\tCALL (u) {\n\t\t\t\t\t  MATCH (u)-[:SOMETHING]->(x)\n\t\t\t\t\t  CALL (x) {\n\t\t\t\t\t    MATCH (x)-[:DEEPER]->(y)\n\t\t\t\t\t    RETURN y {\n\t\t\t\t\t      .bar\n\t\t\t\t\t    } AS bar\n\t\t\t\t\t  }\n\t\t\t\t\t  RETURN x {\n\t\t\t\t\t    .foo,\n\t\t\t\t\t    bar: bar\n\t\t\t\t\t  } AS anyThing\n\t\t\t\t\t}\n\t\t\t\t\tWITH u\n\t\t\t\t\tCALL (*) {\n\t\t\t\t\t  USE movies.actors\n\t\t\t\t\t  MATCH (person:Person)\n\t\t\t\t\t  RETURN person\n\t\t\t\t\t}\n\t\t\t\t\tWITH u\n\t\t\t\t\tRETURN u {\n\t\t\t\t\t  name: u.name,\n\t\t\t\t\t  anyThing: anyThing,\n\t\t\t\t\t  nesting1: {\n\t\t\t\t\t    name: u.name,\n\t\t\t\t\t    nesting2: {\n\t\t\t\t\t      name: b.name,\n\t\t\t\t\t      pattern: [(u)-[:LIKES]->(other) WHERE other.foo = $foo | other {\n\t\t\t\t\t        .x,\n\t\t\t\t\t        .y\n\t\t\t\t\t      }]\n\t\t\t\t\t    }\n\t\t\t\t\t  }\n\t\t\t\t\t}\"\"\");\n\t\t}\n\n\t\t@Test\n\t\tvoid prettyPrintingWithTabsShouldWork() {\n\n\t\t\tassertThat(Renderer\n\t\t\t\t.getRenderer(Configuration.newConfig()\n\t\t\t\t\t.withPrettyPrint(true)\n\t\t\t\t\t.withIndentStyle(Configuration.IndentStyle.TAB)\n\t\t\t\t\t.build())\n\t\t\t\t.render(this.statement)).isEqualTo(\"\"\"\n\t\t\t\t\t\tMATCH (u:User)\n\t\t\t\t\t\tWHERE (u.name = 'Max'\n\t\t\t\t\t\t\\tAND u.lastName = 'Mustermann'\n\t\t\t\t\t\t\\tAND EXISTS {\n\t\t\t\t\t\t\\t\\tMATCH (u)-[:LIKES]->(b:Bike)\n\t\t\t\t\t\t\\t\\tWHERE ((b)-[:LINK]->()\n\t\t\t\t\t\t\\t\\t\\tOR EXISTS {\n\t\t\t\t\t\t\\t\\t\\t\\tMATCH (b)-[:LINK]->()\n\t\t\t\t\t\t\\t\\t\\t})\n\t\t\t\t\t\t\\t})\n\t\t\t\t\t\tSET u.lastName = $newName\n\t\t\t\t\t\tWITH u\n\t\t\t\t\t\tMATCH (b:Bike)\n\t\t\t\t\t\tCREATE (u)-[:LIKES]->(b)\n\t\t\t\t\t\tWITH u\n\t\t\t\t\t\tCALL (u) {\n\t\t\t\t\t\t\\tMATCH (u)-[:SOMETHING]->(x)\n\t\t\t\t\t\t\\tCALL (x) {\n\t\t\t\t\t\t\\t\\tMATCH (x)-[:DEEPER]->(y)\n\t\t\t\t\t\t\\t\\tRETURN y {\n\t\t\t\t\t\t\\t\\t\\t.bar\n\t\t\t\t\t\t\\t\\t} AS bar\n\t\t\t\t\t\t\\t}\n\t\t\t\t\t\t\\tRETURN x {\n\t\t\t\t\t\t\\t\\t.foo,\n\t\t\t\t\t\t\\t\\tbar: bar\n\t\t\t\t\t\t\\t} AS anyThing\n\t\t\t\t\t\t}\n\t\t\t\t\t\tWITH u\n\t\t\t\t\t\tCALL (*) {\n\t\t\t\t\t\t\\tUSE movies.actors\n\t\t\t\t\t\t\\tMATCH (person:Person)\n\t\t\t\t\t\t\\tRETURN person\n\t\t\t\t\t\t}\n\t\t\t\t\t\tWITH u\n\t\t\t\t\t\tRETURN u {\n\t\t\t\t\t\t\\tname: u.name,\n\t\t\t\t\t\t\\tanyThing: anyThing,\n\t\t\t\t\t\t\\tnesting1: {\n\t\t\t\t\t\t\\t\\tname: u.name,\n\t\t\t\t\t\t\\t\\tnesting2: {\n\t\t\t\t\t\t\\t\\t\\tname: b.name,\n\t\t\t\t\t\t\\t\\t\\tpattern: [(u)-[:LIKES]->(other) WHERE other.foo = $foo | other {\n\t\t\t\t\t\t\\t\\t\\t\\t.x,\n\t\t\t\t\t\t\\t\\t\\t\\t.y\n\t\t\t\t\t\t\\t\\t\\t}]\n\t\t\t\t\t\t\\t\\t}\n\t\t\t\t\t\t\\t}\n\t\t\t\t\t\t}\"\"\");\n\t\t}\n\n\t\t/**\n\t\t * See\n\t\t * https://neo4j.com/docs/cypher-manual/current/styleguide/#cypher-styleguide-indentation-and-line-breaks\n\t\t */\n\t\t@Test\n\t\tvoid onClauses() {\n\t\t\tNode n = Cypher.anyNode(\"n\");\n\t\t\tNode a = Cypher.node(\"A\").named(\"a\");\n\t\t\tNode b = Cypher.node(\"B\").named(\"b\");\n\n\t\t\tStatement mergeStatement = Cypher.merge(n)\n\t\t\t\t.onCreate()\n\t\t\t\t.set(n.property(\"prop\").to(Cypher.literalOf(0)))\n\t\t\t\t.merge(a.relationshipBetween(b, \"T\"))\n\t\t\t\t.onCreate()\n\t\t\t\t.set(a.property(\"name\").to(Cypher.literalOf(\"me\")))\n\t\t\t\t.onMatch()\n\t\t\t\t.set(b.property(\"name\").to(Cypher.literalOf(\"you\")))\n\t\t\t\t.returning(a.property(\"prop\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(Renderer.getRenderer(Configuration.prettyPrinting()).render(mergeStatement)).isEqualTo(\"\"\"\n\t\t\t\t\tMERGE (n)\n\t\t\t\t\t  ON CREATE SET n.prop = 0\n\t\t\t\t\tMERGE (a:A)-[:T]-(b:B)\n\t\t\t\t\t  ON CREATE SET a.name = 'me'\n\t\t\t\t\t  ON MATCH SET b.name = 'you'\n\t\t\t\t\tRETURN a.prop\"\"\");\n\t\t}\n\n\t\t@Test\n\t\tvoid singleExistsSubquery() {\n\t\t\tNode a = Cypher.node(\"A\").named(\"a\");\n\t\t\tNode b = Cypher.node(\"B\").named(\"b\");\n\n\t\t\tStatement mergeStatement = Cypher.match(a)\n\t\t\t\t.where(Cypher.match(a.relationshipTo(b)).asCondition())\n\t\t\t\t.returning(a)\n\t\t\t\t.build();\n\n\t\t\tassertThat(Renderer.getRenderer(Configuration.prettyPrinting()).render(mergeStatement)).isEqualTo(\"\"\"\n\t\t\t\t\tMATCH (a:A)\n\t\t\t\t\tWHERE EXISTS {\n\t\t\t\t\t  MATCH (a)-->(b:B)\n\t\t\t\t\t}\n\t\t\t\t\tRETURN a\"\"\");\n\t\t}\n\n\t\t@Test\n\t\tvoid multipleSubQueries() {\n\t\t\tNode a = Cypher.node(\"A\").named(\"a\");\n\t\t\tNode b = Cypher.node(\"B\").named(\"b\");\n\t\t\tSymbolicName c = Cypher.name(\"c\");\n\n\t\t\tStatement mergeStatement = Cypher.call(Cypher.create(a).returning(a).build())\n\t\t\t\t.call(Cypher.create(b).returning(b).build())\n\t\t\t\t.unwind(Cypher.listOf(a.getRequiredSymbolicName(), b.getRequiredSymbolicName()))\n\t\t\t\t.as(c)\n\t\t\t\t.returning(c.project(\"name\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(Renderer.getRenderer(Configuration.prettyPrinting()).render(mergeStatement)).isEqualTo(\"\"\"\n\t\t\t\t\tCALL () {\n\t\t\t\t\t  CREATE (a:A)\n\t\t\t\t\t  RETURN a\n\t\t\t\t\t}\n\t\t\t\t\tCALL (*) {\n\t\t\t\t\t  CREATE (b:B)\n\t\t\t\t\t  RETURN b\n\t\t\t\t\t}\n\t\t\t\t\tUNWIND [a, b] AS c\n\t\t\t\t\tRETURN c {\n\t\t\t\t\t  .name\n\t\t\t\t\t}\"\"\");\n\t\t}\n\n\t\t@Test\n\t\tvoid prettyPrintingQueryStartingWithSubquery() {\n\t\t\tString rawQuery = \"MATCH (node) RETURN node\";\n\t\t\tSymbolicName node = Cypher.name(\"node\");\n\t\t\tResultStatement resultStatement = Cypher.call(Cypher.returningRaw(Cypher.raw(rawQuery).as(node)).build())\n\t\t\t\t.returning(node)\n\t\t\t\t.build();\n\n\t\t\tassertThat(Renderer.getRenderer(Configuration.prettyPrinting()).render(resultStatement)).isEqualTo(\"\"\"\n\t\t\t\t\tCALL () {\n\t\t\t\t\t  MATCH (node) RETURN node AS node\n\t\t\t\t\t}\n\t\t\t\t\tRETURN node\"\"\");\n\t\t}\n\n\t}\n\n\t// GH-858\n\t@Nested\n\tclass ConditionalPatterns {\n\n\t\t@Test\n\t\tvoid nodesWithWhere() {\n\n\t\t\tvar node = Cypher.node(\"Movie\").withProperties(Map.of(\"title\", \"The Matrix\")).named(\"n\");\n\t\t\tvar cypher = Cypher.match(node.where(node.property(\"released\").eq(Cypher.literalOf(1999))))\n\t\t\t\t.returning(node)\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\"MATCH (n:`Movie` {title: 'The Matrix'} WHERE n.released = 1999) RETURN n\");\n\t\t}\n\n\t\t@Test\n\t\tvoid relationshipsWithWhere() {\n\n\t\t\tvar node = Cypher.node(\"Movie\").withProperties(Map.of(\"title\", \"The Matrix\")).named(\"n\");\n\t\t\tvar actor = Cypher.node(\"Actor\");\n\t\t\tvar cypher = Cypher\n\t\t\t\t.match(node.relationshipFrom(actor, \"ACTED_IN\")\n\t\t\t\t\t.named(\"r\")\n\t\t\t\t\t.where(Cypher.property(\"r\", \"role\").eq(Cypher.literalOf(\"Neo4j\"))))\n\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\t\"MATCH (n:`Movie` {title: 'The Matrix'})<-[r:`ACTED_IN` WHERE r.role = 'Neo4j']-(:`Actor`) RETURN *\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass QuantifiedPathPatterns {\n\n\t\tRelationshipPattern relationshipPattern = Cypher.node(\"A\")\n\t\t\t.named(\"a\")\n\t\t\t.relationshipTo(Cypher.node(\"B\").named(\"b\"), \"X\");\n\n\t\t@Test\n\t\tvoid quantifyShouldWork() {\n\n\t\t\tvar cypher = Cypher.match(this.relationshipPattern.quantify(QuantifiedPathPattern.interval(1, 3)))\n\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\"MATCH ((a:`A`)-[:`X`]->(b:`B`)){1,3} RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid nestingInBooleanExpressionIsAllowed() {\n\n\t\t\tvar pattern = Cypher.anyNode(\"n\")\n\t\t\t\t.relationshipTo(Cypher.node(\"X\"))\n\t\t\t\t.quantifyRelationship(QuantifiedPathPattern.plus());\n\t\t\tvar innerRel = Cypher.node(\"A\")\n\t\t\t\t.named(\"n\")\n\t\t\t\t.relationshipTo(Cypher.anyNode().withProperties(Map.of(\"p\", 30)), \"R\")\n\t\t\t\t.quantify(QuantifiedPathPattern.interval(2, 3))\n\t\t\t\t.where(Cypher.exists(pattern));\n\t\t\tvar cypher = Cypher.match(innerRel).returning(Cypher.asterisk()).build().getCypher();\n\t\t\tassertThat(cypher)\n\t\t\t\t.isEqualTo(\"MATCH ((n:`A`)-[:`R`]->( {p: 30}) WHERE EXISTS { (n)-->+(:`X`) }){2,3} RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid betweenMAndNIterations() {\n\n\t\t\tvar cypher = Cypher\n\t\t\t\t.match(this.relationshipPattern.quantifyRelationship(QuantifiedPathPattern.interval(1, 3)))\n\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\"MATCH (a:`A`)-[:`X`]->{1,3}(b:`B`) RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid oneOrMoreIterations() {\n\n\t\t\tvar cypher = Cypher\n\t\t\t\t.match(this.relationshipPattern.quantifyRelationship(QuantifiedPathPattern.interval(1, null)))\n\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\"MATCH (a:`A`)-[:`X`]->{1,}(b:`B`) RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid zeroOrMoreIterations() {\n\n\t\t\tvar cypher = Cypher\n\t\t\t\t.match(this.relationshipPattern.quantifyRelationship(QuantifiedPathPattern.interval(0, null)))\n\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\"MATCH (a:`A`)-[:`X`]->{0,}(b:`B`) RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid nIterations() {\n\n\t\t\tvar cypher = Cypher\n\t\t\t\t.match(this.relationshipPattern.quantifyRelationship(QuantifiedPathPattern.interval(1, 1)))\n\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\"MATCH (a:`A`)-[:`X`]->{1,1}(b:`B`) RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid zeroOrMore() {\n\n\t\t\tvar cypher = Cypher\n\t\t\t\t.match(this.relationshipPattern.quantifyRelationship(QuantifiedPathPattern.interval(null, null)))\n\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\"MATCH (a:`A`)-[:`X`]->{0,}(b:`B`) RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid between0AndNIterations() {\n\n\t\t\tvar cypher = Cypher\n\t\t\t\t.match(this.relationshipPattern.quantifyRelationship(QuantifiedPathPattern.interval(null, 3)))\n\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\"MATCH (a:`A`)-[:`X`]->{0,3}(b:`B`) RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid invalidLower() {\n\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> QuantifiedPathPattern.interval(-1, null))\n\t\t\t\t.withMessage(\"Lower bound must be greater than or equal to zero\");\n\t\t}\n\n\t\t@Test\n\t\tvoid invalidLower1() {\n\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> QuantifiedPathPattern.interval(null, 0))\n\t\t\t\t.withMessage(\"Upper bound must be greater than zero\");\n\t\t}\n\n\t\t@Test\n\t\tvoid invalidLower2() {\n\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> QuantifiedPathPattern.interval(2, 1))\n\t\t\t\t.withMessage(\"Upper bound must be greater than or equal to 2\");\n\t\t\tassertThatNoException().isThrownBy(() -> QuantifiedPathPattern.interval(2, 2));\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass Call {\n\n\t\t@Test\n\t\tvoid simpleCallRawCypher() {\n\t\t\tvar cypher = Cypher.callRawCypher(\"MATCH (n:Test) WHERE n.id = $id RETURN id(n) as a, n.id as b\")\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\"CALL () {MATCH (n:Test) WHERE n.id = $id RETURN id(n) as a, n.id as b}\");\n\t\t}\n\n\t\t@Test\n\t\tvoid rawCypherWithWhereAndReturn() {\n\t\t\tvar cypher = Cypher.callRawCypher(\"MATCH (n:Test) RETURN id(n) as a, n.id as b, n.timestamp as timestamp\")\n\t\t\t\t.with(Cypher.asterisk())\n\t\t\t\t.where(Cypher.gt(Cypher.raw(\"timestamp\"), Cypher.parameter(\"from\"))\n\t\t\t\t\t.and(Cypher.lte(Cypher.raw(\"timestamp\"), Cypher.parameter(\"to\"))))\n\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\n\t\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\t\"CALL () {MATCH (n:Test) RETURN id(n) as a, n.id as b, n.timestamp as timestamp} WITH * WHERE (timestamp > $from AND timestamp <= $to) RETURN *\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/CypherTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\nimport static org.assertj.core.api.Assertions.fail;\n\n/**\n * @author Michael J. Simons\n */\nclass CypherTests {\n\n\t@Test\n\tvoid sortDirectionShouldBeSpecified() {\n\n\t\tSortItem sortItem = Cypher.sort(Cypher.literalFalse(), SortItem.Direction.ASC);\n\t\tsortItem.accept(segment -> {\n\n\t\t\tif (segment instanceof SortItem.Direction direction) {\n\t\t\t\tassertThat(direction).extracting(SortItem.Direction::getSymbol).isEqualTo(\"ASC\");\n\t\t\t}\n\t\t});\n\t}\n\n\t@Test\n\t@SuppressWarnings(\"ResultOfMethodCallIgnored\")\n\tvoid shouldNotCreateIllegalLiterals() {\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.literalOf(new CypherTests()))\n\t\t\t.withMessageStartingWith(\"Unsupported literal type: \");\n\t}\n\n\t@Test\n\tvoid nullLiteralShouldBeSameInstance() {\n\n\t\tassertThat(Cypher.literalNull()).isSameAs(NullLiteral.INSTANCE);\n\t}\n\n\t@Test\n\tvoid shouldCreateListLiterals() {\n\n\t\tList<Literal<?>> params = new ArrayList<>();\n\t\tparams.add(Cypher.literalFalse());\n\t\tparams.add(Cypher.literalTrue());\n\n\t\tLiteral<?> listLiteral = Cypher.literalOf(params);\n\n\t\tassertThat(listLiteral).isInstanceOf(ListLiteral.class).returns(\"[false, true]\", Literal::asString);\n\t}\n\n\t@Test\n\tvoid shouldCreateMapLiterals() {\n\n\t\tMap<Object, Literal<?>> params = new LinkedHashMap<>();\n\n\t\tMap<String, Object> mapValue = new LinkedHashMap<>();\n\t\tmapValue.put(\"m1\", 1);\n\t\tmapValue.put(\"m2\", \"m2\");\n\n\t\tparams.put('k', Cypher.literalFalse()); // Character key also valid\n\t\tparams.put(\"k2\", Cypher.literalTrue());\n\t\tparams.put(\"k3\", Cypher.literalOf(Arrays.asList(\"a\", \"b\", \"c\")));\n\t\tparams.put(\"k4\", Cypher.literalOf(mapValue));\n\n\t\tLiteral<?> mapLiteral = Cypher.literalOf(params);\n\n\t\tassertThat(mapLiteral).isInstanceOf(MapLiteral.class)\n\t\t\t.returns(\"{k: false, k2: true, k3: ['a', 'b', 'c'], k4: {m1: 1, m2: 'm2'}}\", Literal::asString);\n\t}\n\n\t@Test\n\tvoid shouldQuoteStrings() {\n\n\t\tassertThat(Cypher.quote(\"foo\")).isEqualTo(\"'foo'\");\n\t\tassertThat(Cypher.quote(\"fo`o\")).isEqualTo(\"'fo`o'\");\n\t}\n\n\t@Test\n\tvoid shouldCreatePropertyPointingToSymbolicName() {\n\t\tProperty property = Cypher.property(\"a\", \"b\");\n\t\tAtomicInteger counter = new AtomicInteger(0);\n\t\tproperty.accept(segment -> {\n\t\t\tint cnt = counter.incrementAndGet();\n\t\t\tswitch (cnt) {\n\t\t\t\tcase 1 -> assertThat(segment).isInstanceOf(Property.class);\n\t\t\t\tcase 2 -> assertThat(segment).isInstanceOf(SymbolicName.class).extracting(\"value\").isEqualTo(\"a\");\n\t\t\t\tcase 3 -> assertThat(segment).isInstanceOf(PropertyLookup.class);\n\t\t\t\tcase 4 -> assertThat(segment).isInstanceOf(SymbolicName.class).extracting(\"value\").isEqualTo(\"b\");\n\t\t\t\tdefault -> fail(\"Unexpected segment: \" + segment.getClass());\n\t\t\t}\n\t\t});\n\t}\n\n\t@Test // GH-189\n\tvoid shouldCreatePropertyWithNameFromCollectionPointingToSymbolicName() {\n\t\tProperty property = Cypher.property(\"a\", Collections.singleton(\"b\"));\n\t\tAtomicInteger counter = new AtomicInteger(0);\n\t\tproperty.accept(segment -> {\n\t\t\tint cnt = counter.incrementAndGet();\n\t\t\tswitch (cnt) {\n\t\t\t\tcase 1 -> assertThat(segment).isInstanceOf(Property.class);\n\t\t\t\tcase 2 -> assertThat(segment).isInstanceOf(SymbolicName.class).extracting(\"value\").isEqualTo(\"a\");\n\t\t\t\tcase 3 -> assertThat(segment).isInstanceOf(PropertyLookup.class);\n\t\t\t\tcase 4 -> assertThat(segment).isInstanceOf(SymbolicName.class).extracting(\"value\").isEqualTo(\"b\");\n\t\t\t\tdefault -> fail(\"Unexpected segment: \" + segment.getClass());\n\t\t\t}\n\t\t});\n\t}\n\n\t@Test // GH-189\n\tvoid shouldCreateAdditionalLabelsFromCollection() {\n\t\tNode node = Cypher.node(\"Primary\", MapExpression.create(false), Collections.singleton(\"Secondary\"));\n\t\tassertThat(node.getLabels()).extracting(\"value\").containsExactly(\"Primary\", \"Secondary\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/DefaultStatementBuilderTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Collection;\n\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n */\nclass DefaultStatementBuilderTests {\n\n\t@Test\n\tvoid matchPreconditionsShouldBeAsserted() {\n\n\t\tDefaultStatementBuilder builder = new DefaultStatementBuilder();\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> builder.match((PatternElement[]) null))\n\t\t\t.withMessage(\"Patterns to match are required.\");\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> builder.match())\n\t\t\t.withMessage(\"At least one pattern to match is required.\");\n\t}\n\n\t@Nested\n\tclass MessageBundles {\n\n\t\t@Test\n\t\tvoid shouldUseMessageBundleOnNullExpressions() {\n\t\t\tDefaultStatementBuilder builder = new DefaultStatementBuilder();\n\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> builder.returning((Collection<Expression>) null))\n\t\t\t\t.withMessage(\"Expressions to return are required.\");\n\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> builder.with((Collection<IdentifiableElement>) null))\n\t\t\t\t.withMessage(\"Expressions to return are required.\");\n\n\t\t\tStatementBuilder.BuildableMatchAndUpdate update = builder.set(Cypher.node(\"N\").named(\"n\"), \"x\");\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> update.returning((Collection<Expression>) null))\n\t\t\t\t.withMessage(\"Expressions to return are required.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldUseMessageBundleOnEmptyExpressions() {\n\t\t\tDefaultStatementBuilder builder = new DefaultStatementBuilder();\n\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> builder.returning((Expression) null))\n\t\t\t\t.withMessage(\"At least one expressions to return is required.\");\n\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> builder.with((IdentifiableElement) null))\n\t\t\t\t.withMessage(\"At least one expressions to return is required.\");\n\n\t\t\tStatementBuilder.BuildableMatchAndUpdate update = builder.set(Cypher.node(\"N\").named(\"n\"), \"x\");\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> update.returning((Expression) null))\n\t\t\t\t.withMessage(\"At least one expressions to return is required.\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass ReturningPreconditionsShouldBeAsserted {\n\n\t\t@Test\n\t\tvoid forExpressions() {\n\n\t\t\tDefaultStatementBuilder builder = new DefaultStatementBuilder();\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> builder.returning((Expression[]) null))\n\t\t\t\t.withMessage(\"Expressions to return are required.\");\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> builder.returning(new Expression[0]))\n\t\t\t\t.withMessage(\"At least one expressions to return is required.\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/DeleteTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass DeleteTests {\n\n\t@Test\n\tvoid buildingDeleteClauseWithMultipleElements() {\n\n\t\tvar delete = Delete.delete(Cypher.name(\"n\"), Cypher.name(\"b\"));\n\t\tassertThat(delete).hasToString(\"Delete{cypher=DELETE n, b}\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/DialectIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.CsvSource;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Dialect;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n */\n\n// tag::dialect-example[]\nclass DialectIT {\n\n\t// end::dialect-example[]\n\n\tstatic Stream<Arguments> nPropExists() {\n\t\treturn Stream.of(Arguments.of(Dialect.NEO4J_4, false, \"MATCH (n:`Movie`) WHERE exists(n.title) RETURN n\"),\n\t\t\t\tArguments.of(Dialect.NEO4J_4, true, \"MATCH (n:`Movie`) WHERE NOT (exists(n.title)) RETURN n\"),\n\t\t\t\tArguments.of(Dialect.NEO4J_5, false, \"MATCH (n:`Movie`) WHERE n.title IS NOT NULL RETURN n\"),\n\t\t\t\tArguments.of(Dialect.NEO4J_5, true, \"MATCH (n:`Movie`) WHERE n.title IS NULL RETURN n\"));\n\t}\n\n\tstatic Stream<Arguments> distanceFunction() {\n\t\treturn Stream.of(Arguments.of(Dialect.NEO4J_4, \"MATCH (n) RETURN distance(n.a, n.b)\"),\n\t\t\t\tArguments.of(Dialect.NEO4J_5, \"MATCH (n) RETURN point.distance(n.a, n.b)\"));\n\t}\n\n\tstatic Stream<Arguments> elementId() {\n\t\treturn Stream.of(Arguments.of(Dialect.NEO4J_4, \"MATCH (n) RETURN toString(id(n))\"),\n\t\t\t\tArguments.of(Dialect.NEO4J_5, \"MATCH (n) RETURN elementId(n)\"));\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource\n\tvoid nPropExists(Dialect dialect, boolean negate, String expected) {\n\n\t\tNode n = Cypher.node(\"Movie\").named(\"n\");\n\t\tRenderer renderer = Renderer.getRenderer(Configuration.newConfig().withDialect(dialect).build());\n\t\tCondition condition = Cypher.exists(n.property(\"title\"));\n\t\tif (negate) {\n\t\t\tcondition = condition.not();\n\t\t}\n\t\tString cypher = renderer.render(Cypher.match(n).where(condition).returning(n).build());\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource\n\tvoid distanceFunction(Dialect dialect, String expected) {\n\n\t\tNode n = Cypher.anyNode(\"n\");\n\t\tRenderer renderer = Renderer.getRenderer(Configuration.newConfig().withDialect(dialect).build());\n\t\tString cypher = renderer\n\t\t\t.render(Cypher.match(n).returning(Cypher.distance(n.property(\"a\"), n.property(\"b\"))).build());\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource\n\tvoid elementId(Dialect dialect, String expected) {\n\n\t\tNode n = Cypher.anyNode(\"n\");\n\n\t\tRenderer renderer = Renderer.getRenderer(Configuration.newConfig().withDialect(dialect).build());\n\t\tString cypher = renderer.render(Cypher.match(n).returning(n.elementId()).build());\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@ParameterizedTest\n\t@CsvSource(textBlock = \"\"\"\n\t\t\tNEO4J_4,MATCH p = shortestPath((wos:`Station`)-[:`LINK`]->(bmv:`Station`)) RETURN p\n\t\t\tNEO4J_5,MATCH p = shortestPath((wos:`Station`)-[:`LINK`]->(bmv:`Station`)) RETURN p\n\t\t\tNEO4J_5_23,MATCH p = SHORTEST 1 (wos:`Station`)-[:`LINK`]->(bmv:`Station`) RETURN p\n\t\t\tNEO4J_5_26,CYPHER 5 MATCH p = SHORTEST 1 (wos:`Station`)-[:`LINK`]->(bmv:`Station`) RETURN p\n\t\t\tNEO4J_5_DEFAULT_CYPHER,MATCH p = SHORTEST 1 (wos:`Station`)-[:`LINK`]->(bmv:`Station`) RETURN p\n\t\t\tNEO4J_5_CYPHER_5,CYPHER 5 MATCH p = SHORTEST 1 (wos:`Station`)-[:`LINK`]->(bmv:`Station`) RETURN p\n\t\t\tNEO4J_5_CYPHER_25,CYPHER 25 MATCH p = SHORTEST 1 (wos:`Station`)-[:`LINK`]->(bmv:`Station`) RETURN p\n\t\t\t\"\"\")\n\tvoid shortestPath(Dialect dialect, String expected) {\n\n\t\tvar stmt = Cypher.match(Cypher.shortestK(1)\n\t\t\t.named(\"p\")\n\t\t\t.definedBy(Cypher.node(\"Station\").named(\"wos\").relationshipTo(Cypher.node(\"Station\").named(\"bmv\"), \"LINK\")))\n\t\t\t.returning(Cypher.name(\"p\"))\n\t\t\t.build();\n\t\tvar renderer = Renderer.getRenderer(Configuration.newConfig().withDialect(dialect).build());\n\t\tassertThat(renderer.render(stmt)).isEqualTo(expected);\n\t}\n\n\t@ParameterizedTest\n\t@CsvSource(textBlock = \"\"\"\n\t\t\tNEO4J_4,MATCH p = allShortestPaths((wos:`Station`)-[:`LINK`]->(bmv:`Station`)) RETURN p\n\t\t\tNEO4J_5,MATCH p = allShortestPaths((wos:`Station`)-[:`LINK`]->(bmv:`Station`)) RETURN p\n\t\t\tNEO4J_5_23,MATCH p = ALL SHORTEST (wos:`Station`)-[:`LINK`]->(bmv:`Station`) RETURN p\n\t\t\tNEO4J_5_26,CYPHER 5 MATCH p = ALL SHORTEST (wos:`Station`)-[:`LINK`]->(bmv:`Station`) RETURN p\n\t\t\tNEO4J_5_DEFAULT_CYPHER,MATCH p = ALL SHORTEST (wos:`Station`)-[:`LINK`]->(bmv:`Station`) RETURN p\n\t\t\tNEO4J_5_CYPHER_5,CYPHER 5 MATCH p = ALL SHORTEST (wos:`Station`)-[:`LINK`]->(bmv:`Station`) RETURN p\n\t\t\tNEO4J_5_CYPHER_25,CYPHER 25 MATCH p = ALL SHORTEST (wos:`Station`)-[:`LINK`]->(bmv:`Station`) RETURN p\n\t\t\t\"\"\")\n\tvoid allShortestPath(Dialect dialect, String expected) {\n\t\tvar stmt = Cypher.match(Cypher.allShortest()\n\t\t\t.named(\"p\")\n\t\t\t.definedBy(Cypher.node(\"Station\").named(\"wos\").relationshipTo(Cypher.node(\"Station\").named(\"bmv\"), \"LINK\")))\n\t\t\t.returning(Cypher.name(\"p\"))\n\t\t\t.build();\n\t\tvar renderer = Renderer.getRenderer(Configuration.newConfig().withDialect(dialect).build());\n\t\tassertThat(renderer.render(stmt)).isEqualTo(expected);\n\t}\n\n\t@ParameterizedTest\n\t@CsvSource(quoteCharacter = '@',\n\t\t\ttextBlock = \"\"\"\n\t\t\t\t\tfalse, NEO4J_4,                MATCH (m:`Movie`) SET m:`a`:`b`:`c`:`d`:`e`:`f`:`g`:`h`:`i`:`j`:`k`:`l`:`m` RETURN *\n\t\t\t\t\tfalse, NEO4J_5,                MATCH (m:`Movie`) SET m:`a`:`b`:`c`:`d`:`e`:`f`:`g`:`h`:`i`:`j`:`k`:`l`:`m` RETURN *\n\t\t\t\t\tfalse, NEO4J_5_23,             MATCH (m:`Movie`) SET m:`a`:`b`:`c`:`d`:`e`:`f`:`g`:`h`:`i`:`j`:`k`:`l`:`m` RETURN *\n\t\t\t\t\tfalse, NEO4J_5_26,             @CYPHER 5 MATCH (m:`Movie`) SET m:$($x):$($y):$($z):$(['f', 'g']):$('h'):$(['i', 'j']):$($foo):$($bar) RETURN *@\n\t\t\t\t\tfalse, NEO4J_5_CYPHER_5,       @CYPHER 5 MATCH (m:`Movie`) SET m:$($x):$($y):$($z):$(['f', 'g']):$('h'):$(['i', 'j']):$($foo):$($bar) RETURN *@\n\t\t\t\t\tfalse, NEO4J_5_DEFAULT_CYPHER, @MATCH (m:`Movie`) SET m:$($x):$($y):$($z):$(['f', 'g']):$('h'):$(['i', 'j']):$($foo):$($bar) RETURN *@\n\t\t\t\t\tfalse, NEO4J_5_CYPHER_25,      @CYPHER 25 MATCH (m:`Movie`) SET m:$($x):$($y):$($z):$(['f', 'g']):$('h'):$(['i', 'j']):$($foo):$($bar) RETURN *@\n\t\t\t\t\ttrue, NEO4J_4,                 MATCH (m:`Movie`) SET m:`a`:`b`:`c`:`d`:`e`:`f`:`g`:`h`:`i`:`j`:`k`:`l`:`m` RETURN *\n\t\t\t\t\ttrue, NEO4J_5,                 MATCH (m:`Movie`) SET m:`a`:`b`:`c`:`d`:`e`:`f`:`g`:`h`:`i`:`j`:`k`:`l`:`m` RETURN *\n\t\t\t\t\ttrue, NEO4J_5_23,              MATCH (m:`Movie`) SET m:`a`:`b`:`c`:`d`:`e`:`f`:`g`:`h`:`i`:`j`:`k`:`l`:`m` RETURN *\n\t\t\t\t\ttrue, NEO4J_5_26,              CYPHER 5 MATCH (m:`Movie`) SET m:`a`:`b`:`c`:`d`:`e`:`f`:`g`:`h`:`i`:`j`:`k`:`l`:`m` RETURN *\n\t\t\t\t\ttrue, NEO4J_5_CYPHER_5,        CYPHER 5 MATCH (m:`Movie`) SET m:`a`:`b`:`c`:`d`:`e`:`f`:`g`:`h`:`i`:`j`:`k`:`l`:`m` RETURN *\n\t\t\t\t\ttrue, NEO4J_5_DEFAULT_CYPHER,  MATCH (m:`Movie`) SET m:`a`:`b`:`c`:`d`:`e`:`f`:`g`:`h`:`i`:`j`:`k`:`l`:`m` RETURN *\n\t\t\t\t\ttrue, NEO4J_5_CYPHER_25,       CYPHER 25 MATCH (m:`Movie`) SET m:`a`:`b`:`c`:`d`:`e`:`f`:`g`:`h`:`i`:`j`:`k`:`l`:`m` RETURN *\n\t\t\t\t\t\"\"\")\n\tvoid labelRenderingShouldWork(boolean disableDynamicLabels, Dialect dialect, String expected) {\n\t\tvar m = Cypher.node(Cypher.exactlyLabel(\"Movie\")).named(\"m\");\n\t\tvar parameterWithListOfStrings = Cypher.parameter(\"x\",\n\t\t\t\tCypher.listOf(Cypher.literalOf(\"a\"), Cypher.literalOf(\"b\")));\n\t\tvar parameterWithASingleString = Cypher.parameter(\"y\", Cypher.literalOf(\"c\"));\n\t\tvar parameterWithListLiteral = Cypher.parameter(\"z\",\n\t\t\t\tCypher.literalOf(List.of(Cypher.literalOf(\"d\"), Cypher.literalOf(\"e\"))));\n\t\tvar parameterWithAListOfJavaStrings = Cypher.parameter(\"foo\", List.of(\"k\", \"l\"));\n\n\t\tvar stmt = Cypher.match(m)\n\t\t\t.set(m, Labels.all(parameterWithListOfStrings)\n\t\t\t\t.conjunctionWith(Labels.all(parameterWithASingleString))\n\t\t\t\t.conjunctionWith(Labels.all(parameterWithListLiteral))\n\t\t\t\t.conjunctionWith(Labels.all(Cypher.listOf(Cypher.literalOf(\"f\"), Cypher.literalOf(\"g\"))))\n\t\t\t\t.conjunctionWith(Labels.all(Cypher.literalOf(\"h\")))\n\t\t\t\t.conjunctionWith(Labels.all(Cypher.literalOf(List.of(Cypher.literalOf(\"i\"), Cypher.literalOf(\"j\")))))\n\t\t\t\t.conjunctionWith(Labels.all(parameterWithAListOfJavaStrings))\n\t\t\t\t.conjunctionWith(Labels.all(Cypher.parameter(\"bar\", \"m\"))))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build();\n\n\t\tvar renderer = Renderer.getRenderer(\n\t\t\t\tConfiguration.newConfig().disableDynamicLabels(disableDynamicLabels).withDialect(dialect).build());\n\t\tassertThat(renderer.render(stmt)).isEqualTo(expected);\n\t}\n\n\t@Test\n\tvoid expressionsMightNotBeRenderedInLabels() {\n\t\tvar m = Cypher.node(\"Movie\").named(\"m\");\n\t\tvar stmt = Cypher.match(m).set(m, Labels.all(m.property(\"x\"))).returning(Cypher.asterisk()).build();\n\n\t\tvar renderer = Renderer.getRenderer(Configuration.newConfig().withDialect(Dialect.NEO4J_4).build());\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> renderer.render(stmt))\n\t\t\t.withMessage(\"Cannot render the given Labels in a Cypher pre 5.26 compatible way\");\n\t}\n\n\t@Test // GH-539\n\t// tag::dialect-example[]\n\tvoid shouldRenderElementId() {\n\t\tvar screen = Cypher.node(\"ScreenStateNode\").named(\"screen\");\n\t\tvar id = Cypher.literalOf(\"4:d32903f5-48ef-40fb-9ce5-9a3039852c46:2\");\n\t\tvar statement = Cypher.match(screen)\n\t\t\t.where(Cypher.elementId(screen).eq(id))\n\t\t\t.returning(Cypher.elementId(screen))\n\t\t\t.build();\n\t\t// Config and renderer is thread safe, you can store it somewhere global\n\t\tvar rendererConfig = Configuration.newConfig().withDialect(Dialect.NEO4J_5).build();\n\t\tvar renderer = Renderer.getRenderer(rendererConfig);\n\t\tvar cypher = renderer.render(statement);\n\t\tassertThat(cypher).isEqualTo(\"MATCH (screen:`ScreenStateNode`) \"\n\t\t\t\t+ \"WHERE elementId(screen) = '4:d32903f5-48ef-40fb-9ce5-9a3039852c46:2' \" + \"RETURN elementId(screen)\");\n\t}\n\n}\n// end::dialect-example[]\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/DurationLiteralTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.time.Duration;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass DurationLiteralTests {\n\n\tstatic Stream<Arguments> asStringShouldWork() {\n\t\treturn Stream.of(Arguments.of(Duration.ofDays(1), \"duration('PT24H')\"),\n\t\t\t\tArguments.of(Duration.ofHours(1), \"duration('PT1H')\"),\n\t\t\t\tArguments.of(Duration.ofMinutes(61), \"duration('PT1H1M')\"),\n\t\t\t\tArguments.of(Duration.ofSeconds(61), \"duration('PT1M1S')\"),\n\t\t\t\tArguments.of(Duration.ofSeconds(61).plusMillis(1123), \"duration('PT1M2.123S')\"),\n\t\t\t\tArguments.of(Duration.ofSeconds(61).plusNanos(1123), \"duration('PT1M1.000001123S')\"),\n\t\t\t\tArguments.of(Duration.ofHours(23).plusMinutes(61).plusSeconds(120), \"duration('PT24H3M')\"),\n\t\t\t\tArguments.of(Duration.ofDays(364).plusHours(47).plusMinutes(59).plusSeconds(61).plusMillis(1001),\n\t\t\t\t\t\t\"duration('PT8784H2.001S')\"));\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource\n\tvoid asStringShouldWork(Duration value, String expected) {\n\n\t\tvar literal = DurationLiteral.of(value);\n\t\tassertThat(literal.asString()).isEqualTo(expected);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/ExpressionTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.stream.Stream;\n\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass ExpressionTests {\n\n\t@SuppressWarnings(\"unused\")\n\tprivate static Stream<Arguments> mathematicalOperators() {\n\t\treturn Stream.of(Arguments.of(Cypher.literalOf(1).add(Cypher.literalOf(2)), Operator.ADDITION),\n\t\t\t\tArguments.of(Cypher.literalOf(1).subtract(Cypher.literalOf(2)), Operator.SUBTRACTION),\n\t\t\t\tArguments.of(Cypher.literalOf(1).multiply(Cypher.literalOf(2)), Operator.MULTIPLICATION),\n\t\t\t\tArguments.of(Cypher.literalOf(1).divide(Cypher.literalOf(2)), Operator.DIVISION),\n\t\t\t\tArguments.of(Cypher.literalOf(1).remainder(Cypher.literalOf(2)), Operator.MODULO_DIVISION),\n\t\t\t\tArguments.of(Cypher.literalOf(1).pow(Cypher.literalOf(2)), Operator.EXPONENTIATION));\n\t}\n\n\t@SuppressWarnings(\"unused\")\n\tprivate static Stream<Arguments> stringOperators() {\n\t\treturn Stream.of(Arguments.of(Cypher.literalOf(\"a\").concat(Cypher.literalOf(\"b\")), Operator.CONCAT),\n\t\t\t\tArguments.of(Cypher.literalOf(\"a\").matches(Cypher.literalOf(\"b\")), Operator.MATCHES));\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource(\"mathematicalOperators\")\n\tvoid correctMathematicalOperatorsShouldBeUsed(Operation operation, Operator expectedOperator) {\n\n\t\tAtomicInteger counter = new AtomicInteger(0);\n\n\t\toperation.accept(segment -> {\n\t\t\tint i = counter.getAndIncrement();\n\t\t\tswitch (i) {\n\t\t\t\tcase 0 -> assertThat(segment).isInstanceOf(Operation.class);\n\t\t\t\tcase 1 -> assertThat(segment).isInstanceOfSatisfying(NumberLiteral.class,\n\t\t\t\t\t\tv -> assertThat(v.getContent()).isEqualTo(1));\n\t\t\t\tcase 2 -> assertThat(segment).isInstanceOfSatisfying(Operator.class, Assertions::assertThat)\n\t\t\t\t\t.isEqualTo(expectedOperator);\n\t\t\t\tcase 3 -> assertThat(segment).isInstanceOfSatisfying(NumberLiteral.class,\n\t\t\t\t\t\tv -> assertThat(v.getContent()).isEqualTo(2));\n\t\t\t\tdefault -> throw new IllegalArgumentException(\"Too many segments to visit.\");\n\t\t\t}\n\t\t});\n\t\tassertThat(counter.get()).isEqualTo(4);\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource(\"stringOperators\")\n\tvoid correctStringOperatorsShouldBeUsed(Visitable visitable, Operator expectedOperator) {\n\n\t\tAtomicInteger counter = new AtomicInteger(0);\n\n\t\tvisitable.accept(segment -> {\n\t\t\tint i = counter.getAndIncrement();\n\t\t\tswitch (i) {\n\t\t\t\tcase 0:\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tassertThat(segment).isInstanceOfSatisfying(StringLiteral.class,\n\t\t\t\t\t\t\tv -> assertThat(v.getContent()).isEqualTo(\"a\"));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tassertThat(segment).isInstanceOfSatisfying(Operator.class, Assertions::assertThat)\n\t\t\t\t\t\t.isEqualTo(expectedOperator);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tassertThat(segment).isInstanceOfSatisfying(StringLiteral.class,\n\t\t\t\t\t\t\tv -> assertThat(v.getContent()).isEqualTo(\"b\"));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new IllegalArgumentException(\"Too many segments to visit.\");\n\t\t\t}\n\t\t});\n\t\tassertThat(counter.get()).isEqualTo(4);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/ExpressionsIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\nclass ExpressionsIT {\n\n\t@Test\n\tvoid simpleCountSubquery() {\n\n\t\tvar person = Cypher.node(\"Person\").named(\"person\");\n\t\tvar cypher = Cypher.match(person)\n\t\t\t.where(Cypher.count(person.relationshipTo(Cypher.node(\"Dog\"), \"HAS_DOG\")).gt(Cypher.literalOf(1)))\n\t\t\t.returning(person.property(\"name\").as(\"name\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (person:`Person`) \" + \"WHERE COUNT { (person)-[:`HAS_DOG`]->(:`Dog`) } > 1 \"\n\t\t\t\t+ \"RETURN person.name AS name\");\n\t}\n\n\t@Test\n\tvoid countSubqueryWithWhereClause() {\n\n\t\tvar person = Cypher.node(\"Person\").named(\"person\");\n\t\tvar dog = Cypher.node(\"Dog\").named(\"dog\");\n\t\tvar cypher = Cypher.match(person)\n\t\t\t.where(Cypher.count(person.relationshipTo(dog, \"HAS_DOG\"))\n\t\t\t\t.where(person.property(\"name\").eq(dog.property(\"name\")))\n\t\t\t\t.gt(Cypher.literalOf(1)))\n\t\t\t.returning(person.property(\"name\").as(\"name\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (person:`Person`) \"\n\t\t\t\t+ \"WHERE COUNT { (person)-[:`HAS_DOG`]->(dog:`Dog`) WHERE person.name = dog.name } > 1 \"\n\t\t\t\t+ \"RETURN person.name AS name\");\n\t}\n\n\t@Test\n\tvoid countSubqueryWithUnion() {\n\n\t\tvar person = Cypher.node(\"Person\").named(\"person\");\n\t\tvar dog = Cypher.node(\"Dog\").named(\"dog\");\n\t\tvar cat = Cypher.node(\"Cat\").named(\"cat\");\n\t\tvar inner = Cypher.union(\n\t\t\t\tCypher.match(person.relationshipTo(dog, \"HAS_DOG\"))\n\t\t\t\t\t.returning(dog.property(\"name\").as(\"petName\"))\n\t\t\t\t\t.build(),\n\t\t\t\tCypher.match(person.relationshipTo(cat, \"HAS_CAT\"))\n\t\t\t\t\t.returning(cat.property(\"name\").as(\"petName\"))\n\t\t\t\t\t.build());\n\n\t\tvar cypher = Cypher.match(person)\n\t\t\t.returning(person.property(\"name\").as(\"name\"), Cypher.count(inner).as(\"numPets\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (person:`Person`) \" + \"RETURN \" + \"person.name AS name, \" + \"COUNT { \"\n\t\t\t\t+ \"MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`) \" + \"RETURN dog.name AS petName \" + \"UNION \"\n\t\t\t\t+ \"MATCH (person)-[:`HAS_CAT`]->(cat:`Cat`) \" + \"RETURN cat.name AS petName \" + \"} AS numPets\");\n\t}\n\n\t@Test\n\tvoid countSubqueryWithWith() {\n\n\t\tvar person = Cypher.node(\"Person\").named(\"person\");\n\t\tvar dog = Cypher.node(\"Dog\").named(\"d\");\n\n\t\tvar dogName = Cypher.literalOf(\"Ozzy\").as(\"dogName\");\n\t\tvar cypher = Cypher.match(person)\n\t\t\t.where(Cypher.subqueryWith(dogName)\n\t\t\t\t.count(person.relationshipTo(dog, \"HAS_DOG\"))\n\t\t\t\t.where(dog.property(\"name\").eq(dogName))\n\t\t\t\t.eq(Cypher.literalOf(1)))\n\t\t\t.returning(person.property(\"name\").as(\"name\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\"MATCH (person:`Person`) \" + \"WHERE COUNT { \" + \"WITH 'Ozzy' AS dogName \"\n\t\t\t\t+ \"MATCH (person)-[:`HAS_DOG`]->(d:`Dog`) \" + \"WHERE d.name = dogName \" + \"} = 1 \"\n\t\t\t\t+ \"RETURN person.name AS name\");\n\t}\n\n\t@Test\n\tvoid countSubqueryInReturn() {\n\n\t\tvar person = Cypher.node(\"Person\").named(\"person\");\n\t\tvar dog = Cypher.node(\"Dog\");\n\n\t\tvar cypher = Cypher.match(person)\n\t\t\t.returning(person.property(\"name\"), Cypher.count(person.relationshipTo(dog, \"HAS_DOG\")).as(\"howManyDogs\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (person:`Person`) RETURN person.name, COUNT { (person)-[:`HAS_DOG`]->(:`Dog`) } AS howManyDogs\");\n\t}\n\n\t@Test\n\tvoid countSubqueryInSet() {\n\n\t\tvar person = Cypher.node(\"Person\").named(\"person\");\n\t\tvar dog = Cypher.node(\"Dog\");\n\t\tvar howManyDogs = person.property(\"howManyDogs\");\n\n\t\tvar cypher = Cypher.match(person)\n\t\t\t.where(person.property(\"name\").eq(Cypher.literalOf(\"Andy\")))\n\t\t\t.set(howManyDogs.to(Cypher.count(person.relationshipTo(dog, \"HAS_DOG\"))))\n\t\t\t.returning(howManyDogs.as(\"howManyDogs\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\"MATCH (person:`Person`) WHERE person.name = 'Andy' \"\n\t\t\t\t+ \"SET person.howManyDogs = COUNT { (person)-[:`HAS_DOG`]->(:`Dog`) } \"\n\t\t\t\t+ \"RETURN person.howManyDogs AS howManyDogs\");\n\t}\n\n\t@Test\n\tvoid countSubqueryInCase() {\n\n\t\tvar person = Cypher.node(\"Person\").named(\"person\");\n\t\tvar dog = Cypher.node(\"Dog\");\n\t\tvar dogCount = Cypher.count(person.relationshipTo(dog, \"HAS_DOG\"));\n\t\tvar personName = person.property(\"name\");\n\n\t\tvar cypher = Cypher.match(person)\n\t\t\t.returning(Cypher.caseExpression()\n\t\t\t\t.when(dogCount.gt(Cypher.literalOf(1)))\n\t\t\t\t.then(Cypher.literalOf(\"Doglover \").concat(personName))\n\t\t\t\t.elseDefault(personName)\n\t\t\t\t.as(\"result\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\"MATCH (person:`Person`) \" + \"RETURN \" + \"CASE \"\n\t\t\t\t+ \"WHEN COUNT { (person)-[:`HAS_DOG`]->(:`Dog`) } > 1 THEN ('Doglover ' + person.name) \"\n\t\t\t\t+ \"ELSE person.name \" + \"END AS result\");\n\t}\n\n\t@Test // GH-578\n\tvoid fullStatementsAsCountSubQuery() {\n\n\t\tNode p = Cypher.node(\"Person\").named(\"person\");\n\t\tStatement inner = Cypher.match(p.relationshipTo(Cypher.node(\"Dog\"), \"HAS_DOG\"))\n\t\t\t.returning(p.property(\"name\"))\n\t\t\t.build();\n\t\tStatement outer = Cypher.match(p)\n\t\t\t.where(Cypher.count(inner).eq(Cypher.literalOf(1)))\n\t\t\t.returning(p.property(\"name\").as(\"name\"))\n\t\t\t.build();\n\n\t\tString cypher = outer.getCypher();\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (person:`Person`) WHERE COUNT { MATCH (person)-[:`HAS_DOG`]->(:`Dog`) RETURN person.name } = 1 RETURN person.name AS name\");\n\t}\n\n\t@Test // GH-578\n\tvoid fullStatementsAsCountSubQueryWithImports() {\n\n\t\tNode p = Cypher.node(\"Person\").named(\"person\");\n\t\tNode d = Cypher.node(\"Dog\").named(\"d\");\n\t\tSymbolicName dogName = Cypher.name(\"dogName\");\n\t\tStatement inner = Cypher.match(p.relationshipTo(d, \"HAS_DOG\"))\n\t\t\t.where(d.property(\"name\").eq(dogName))\n\t\t\t.returning(p.property(\"name\"))\n\t\t\t.build();\n\t\tStatement outer = Cypher.match(p)\n\t\t\t.where(Cypher.count(inner, Cypher.literalOf(\"Ozzy\").as(dogName)).eq(Cypher.literalOf(1)))\n\t\t\t.returning(p.property(\"name\").as(\"name\"))\n\t\t\t.build();\n\n\t\tString cypher = outer.getCypher();\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (person:`Person`) WHERE COUNT { WITH 'Ozzy' AS dogName MATCH (person)-[:`HAS_DOG`]->(d:`Dog`) WHERE d.name = dogName RETURN person.name } = 1 RETURN person.name AS name\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/ForeignAdapterFactoryTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.condition.DisabledIf;\n\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n */\n@DisabledIf(\"requiredClassesAreMissing\")\nclass ForeignAdapterFactoryTests {\n\n\tstatic boolean requiredClassesAreMissing() {\n\t\ttry {\n\t\t\tClass.forName(\"com.querydsl.core.types.Expression\");\n\t\t}\n\t\tcatch (ClassNotFoundException ex) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Test\n\tvoid shouldNotAdaptNull() {\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.adapt(null))\n\t\t\t.withMessage(\"Cannot adapt literal NULL expressions.\");\n\t}\n\n\t@Test\n\tvoid shouldFailOnUnadaptableThings() {\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.adapt(23))\n\t\t\t.withMessageMatching(\"Cannot adapt expressions of .+ to Cypher-DSL expressions\\\\.\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/FunctionInvocationTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\n\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n */\nclass FunctionInvocationTests {\n\n\t@Test\n\tvoid argumentsShouldBeAsserted() {\n\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> FunctionInvocation.create(BuiltInFunctions.Aggregates.AVG, (Expression) null))\n\t\t\t.withMessage(\"The expression for avg() is required.\");\n\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> FunctionInvocation.createDistinct(BuiltInFunctions.Aggregates.AVG, (Expression) null))\n\t\t\t.withMessage(\"The expression for avg() is required.\");\n\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> FunctionInvocation.createDistinct(BuiltInFunctions.Scalars.HEAD, (Expression) null))\n\t\t\t.withMessage(\"The distinct operator can only be applied within aggregate functions.\");\n\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> FunctionInvocation.create(BuiltInFunctions.Aggregates.AVG, (PatternElement) null))\n\t\t\t.withMessage(\"The pattern for avg() is required.\");\n\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> FunctionInvocation.create(BuiltInFunctions.Aggregates.AVG, (TypedSubtree<?>) null))\n\t\t\t.withMessage(\"avg() requires at least one argument.\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/FunctionsIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.Locale;\nimport java.util.TimeZone;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.EnumSource;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Dialect;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n * @author Gerrit Meier\n */\nclass FunctionsIT {\n\n\tprivate static final Renderer cypherRenderer = Renderer\n\t\t.getRenderer(Configuration.newConfig().withDialect(Dialect.NEO4J_4).build());\n\n\tprivate static Stream<Arguments> neo5jSpecificFunctions() {\n\t\tNode n = Cypher.node(\"Node\").named(\"n\");\n\t\tNode m = Cypher.node(\"Node2\").named(\"m\");\n\t\tRelationship r = n.relationshipTo(m).named(\"r\");\n\n\t\treturn Stream.of(Arguments.of(Cypher.elementId(n), \"RETURN elementId(n)\"),\n\t\t\t\tArguments.of(Cypher.elementId(r), \"RETURN elementId(r)\"));\n\t}\n\n\tprivate static Stream<Arguments> functionsToTest() {\n\t\tNode n = Cypher.node(\"Node\").named(\"n\");\n\t\tNode m = Cypher.node(\"Node2\").named(\"m\");\n\t\tRelationship r = n.relationshipTo(m).named(\"r\");\n\t\tExpression e1 = Cypher.name(\"e1\");\n\t\tExpression e2 = Cypher.name(\"e2\");\n\t\tFunctionInvocation p1 = Cypher\n\t\t\t.point(Cypher.mapOf(\"latitude\", Cypher.literalOf(1), \"longitude\", Cypher.literalOf(2)));\n\t\tFunctionInvocation p2 = Cypher\n\t\t\t.point(Cypher.mapOf(\"latitude\", Cypher.literalOf(3), \"longitude\", Cypher.literalOf(4)));\n\n\t\t// NOTE: Not all of those return valid Cypher statements. They are used only for\n\t\t// integration testing the function calls so far.\n\t\t@SuppressWarnings(\"deprecation\")\n\t\tvar idOfRel = Functions.id(r);\n\t\treturn Stream.of(Arguments.of(Cypher.left(null, null), \"RETURN left(NULL, NULL)\"),\n\t\t\t\tArguments.of(Cypher.left(Cypher.literalOf(\"hello\"), Cypher.literalOf(3)), \"RETURN left('hello', 3)\"),\n\t\t\t\tArguments.of(Cypher.ltrim(Cypher.literalOf(\"   hello\")), \"RETURN ltrim('   hello')\"),\n\t\t\t\tArguments.of(Cypher.replace(Cypher.literalOf(\"hello\"), Cypher.literalOf(\"l\"), Cypher.literalOf(\"w\")),\n\t\t\t\t\t\t\"RETURN replace('hello', 'l', 'w')\"),\n\t\t\t\tArguments.of(Cypher.reverse(Cypher.literalOf(\"hello\")), \"RETURN reverse('hello')\"),\n\t\t\t\tArguments.of(Cypher.right(null, null), \"RETURN right(NULL, NULL)\"),\n\t\t\t\tArguments.of(Cypher.right(Cypher.literalOf(\"hello\"), Cypher.literalOf(3)), \"RETURN right('hello', 3)\"),\n\t\t\t\tArguments.of(Cypher.rtrim(Cypher.literalOf(\"   hello  \")), \"RETURN rtrim('   hello  ')\"),\n\t\t\t\tArguments.of(Cypher.substring(Cypher.literalOf(\"hello\"), Cypher.literalOf(1), Cypher.literalOf(3)),\n\t\t\t\t\t\t\"RETURN substring('hello', 1, 3)\"),\n\t\t\t\tArguments.of(Cypher.substring(Cypher.literalOf(\"hello\"), Cypher.literalOf(2), null),\n\t\t\t\t\t\t\"RETURN substring('hello', 2)\"),\n\t\t\t\tArguments.of(Cypher.toStringOrNull(Cypher.literalOf(\"hello\")), \"RETURN toStringOrNull('hello')\"),\n\t\t\t\tArguments.of(idOfRel, \"RETURN id(r)\"), Arguments.of(Cypher.elementId(n), \"RETURN toString(id(n))\"),\n\t\t\t\tArguments.of(Cypher.elementId(r), \"RETURN toString(id(r))\"),\n\t\t\t\tArguments.of(Cypher.keys(n), \"RETURN keys(n)\"), Arguments.of(Cypher.keys(r), \"RETURN keys(r)\"),\n\t\t\t\tArguments.of(Cypher.keys(e1), \"RETURN keys(e1)\"), Arguments.of(Cypher.labels(n), \"RETURN labels(n)\"),\n\t\t\t\tArguments.of(Cypher.type(r), \"RETURN type(r)\"), Arguments.of(Cypher.count(n), \"RETURN count(n)\"),\n\t\t\t\tArguments.of(Cypher.countDistinct(n), \"RETURN count(DISTINCT n)\"),\n\t\t\t\tArguments.of(Cypher.count(e1), \"RETURN count(e1)\"),\n\t\t\t\tArguments.of(Cypher.countDistinct(e1), \"RETURN count(DISTINCT e1)\"),\n\t\t\t\tArguments.of(Cypher.coalesce(e1, e2), \"RETURN coalesce(e1, e2)\"),\n\t\t\t\tArguments.of(Cypher.toLower(e1), \"RETURN toLower(e1)\"),\n\t\t\t\tArguments.of(Cypher.toUpper(e1), \"RETURN toUpper(e1)\"),\n\t\t\t\tArguments.of(Cypher.trim(e1), \"RETURN trim(e1)\"),\n\t\t\t\tArguments.of(Cypher.split(e1, Cypher.literalOf(\",\")), \"RETURN split(e1, ',')\"),\n\t\t\t\tArguments.of(Cypher.size(e1), \"RETURN size(e1)\"),\n\t\t\t\tArguments.of(Cypher.size(r), \"RETURN size((:`Node`)-[]->(:`Node2`))\"),\n\t\t\t\tArguments.of(Cypher.exists(e1), \"RETURN exists(e1)\"),\n\t\t\t\tArguments.of(Cypher.distance(p1, p2),\n\t\t\t\t\t\t\"RETURN distance(point({latitude: 1, longitude: 2}), point({latitude: 3, longitude: 4}))\"),\n\t\t\t\tArguments.of(Cypher.avg(e1), \"RETURN avg(e1)\"),\n\t\t\t\tArguments.of(Cypher.avgDistinct(e1), \"RETURN avg(DISTINCT e1)\"),\n\t\t\t\tArguments.of(Cypher.collect(e1), \"RETURN collect(e1)\"),\n\t\t\t\tArguments.of(Cypher.collectDistinct(e1), \"RETURN collect(DISTINCT e1)\"),\n\t\t\t\tArguments.of(Cypher.collect(n), \"RETURN collect(n)\"),\n\t\t\t\tArguments.of(Cypher.collectDistinct(n), \"RETURN collect(DISTINCT n)\"),\n\t\t\t\tArguments.of(Cypher.max(e1), \"RETURN max(e1)\"),\n\t\t\t\tArguments.of(Cypher.maxDistinct(e1), \"RETURN max(DISTINCT e1)\"),\n\t\t\t\tArguments.of(Cypher.min(e1), \"RETURN min(e1)\"),\n\t\t\t\tArguments.of(Cypher.minDistinct(e1), \"RETURN min(DISTINCT e1)\"),\n\t\t\t\tArguments.of(Cypher.percentileCont(e1, 0.4), \"RETURN percentileCont(e1, 0.4)\"),\n\t\t\t\tArguments.of(Cypher.percentileContDistinct(e1, 0.4), \"RETURN percentileCont(DISTINCT e1, 0.4)\"),\n\t\t\t\tArguments.of(Cypher.percentileDisc(e1, 0.4), \"RETURN percentileDisc(e1, 0.4)\"),\n\t\t\t\tArguments.of(Cypher.percentileDiscDistinct(e1, 0.4), \"RETURN percentileDisc(DISTINCT e1, 0.4)\"),\n\t\t\t\tArguments.of(Cypher.stDev(e1), \"RETURN stDev(e1)\"),\n\t\t\t\tArguments.of(Cypher.stDevDistinct(e1), \"RETURN stDev(DISTINCT e1)\"),\n\t\t\t\tArguments.of(Cypher.stDevP(e1), \"RETURN stDevP(e1)\"),\n\t\t\t\tArguments.of(Cypher.stDevPDistinct(e1), \"RETURN stDevP(DISTINCT e1)\"),\n\t\t\t\tArguments.of(Cypher.sum(e1), \"RETURN sum(e1)\"),\n\t\t\t\tArguments.of(Cypher.sumDistinct(e1), \"RETURN sum(DISTINCT e1)\"),\n\t\t\t\tArguments.of(Cypher.range(Cypher.literalOf(1), Cypher.literalOf(3)), \"RETURN range(1, 3)\"),\n\t\t\t\tArguments.of(Cypher.range(Cypher.literalOf(1), Cypher.literalOf(3), Cypher.literalOf(2)),\n\t\t\t\t\t\t\"RETURN range(1, 3, 2)\"),\n\t\t\t\tArguments.of(Cypher.head(e1), \"RETURN head(e1)\"), Arguments.of(Cypher.last(e1), \"RETURN last(e1)\"),\n\t\t\t\tArguments.of(Cypher.nodes(Cypher.path(\"p\").definedBy(r)), \"RETURN nodes(p)\"),\n\t\t\t\tArguments.of(Cypher.length(Cypher.path(\"p\").definedBy(r)), \"RETURN length(p)\"),\n\t\t\t\tArguments.of(Cypher.properties(n), \"RETURN properties(n)\"),\n\t\t\t\tArguments.of(Cypher.properties(r), \"RETURN properties(r)\"),\n\t\t\t\tArguments.of(Cypher.properties(Cypher.mapOf(\"a\", Cypher.literalOf(\"b\"))),\n\t\t\t\t\t\t\"RETURN properties({a: 'b'})\"),\n\t\t\t\tArguments.of(Cypher.relationships(Cypher.path(\"p\").definedBy(r)), \"RETURN relationships(p)\"),\n\t\t\t\tArguments.of(Cypher.startNode(r), \"RETURN startNode(r)\"),\n\t\t\t\tArguments.of(Cypher.endNode(r), \"RETURN endNode(r)\"), Arguments.of(Cypher.date(), \"RETURN date()\"),\n\t\t\t\tArguments.of(Cypher.calendarDate(2020, 9, 21), \"RETURN date({year: 2020, month: 9, day: 21})\"),\n\t\t\t\tArguments.of(Cypher.weekDate(1984, 10, 3), \"RETURN date({year: 1984, week: 10, dayOfWeek: 3})\"),\n\t\t\t\tArguments.of(Cypher.weekDate(1984, 10, null), \"RETURN date({year: 1984, week: 10})\"),\n\t\t\t\tArguments.of(Cypher.weekDate(1984, null, null), \"RETURN date({year: 1984})\"),\n\t\t\t\tArguments.of(Cypher.quarterDate(1984, 10, 45),\n\t\t\t\t\t\t\"RETURN date({year: 1984, quarter: 10, dayOfQuarter: 45})\"),\n\t\t\t\tArguments.of(Cypher.quarterDate(1984, 10, null), \"RETURN date({year: 1984, quarter: 10})\"),\n\t\t\t\tArguments.of(Cypher.quarterDate(1984, null, null), \"RETURN date({year: 1984})\"),\n\t\t\t\tArguments.of(Cypher.ordinalDate(1984, 202), \"RETURN date({year: 1984, ordinalDay: 202})\"),\n\t\t\t\tArguments.of(Cypher.ordinalDate(1984, null), \"RETURN date({year: 1984})\"),\n\t\t\t\tArguments.of(Cypher.date(Cypher.mapOf(\"year\", Cypher.literalOf(2020))), \"RETURN date({year: 2020})\"),\n\t\t\t\tArguments.of(Cypher.date(\"2020-09-15\"), \"RETURN date('2020-09-15')\"),\n\t\t\t\tArguments.of(Cypher.date(Cypher.parameter(\"$myDateParameter\")), \"RETURN date($myDateParameter)\"),\n\t\t\t\tArguments.of(Cypher.datetime(), \"RETURN datetime()\"), Arguments.of(\n\t\t\t\t\t\tCypher.datetime(Cypher.mapOf(\"year\", Cypher.literalOf(1984), \"month\", Cypher.literalOf(10),\n\t\t\t\t\t\t\t\t\"day\", Cypher.literalOf(11), \"hour\", Cypher\n\t\t\t\t\t\t\t\t\t.literalOf(12),\n\t\t\t\t\t\t\t\t\"minute\", Cypher.literalOf(31), \"timezone\", Cypher.literalOf(\"Europe/Stockholm\"))),\n\t\t\t\t\t\t\"RETURN datetime({year: 1984, month: 10, day: 11, hour: 12, minute: 31, timezone: 'Europe/Stockholm'})\"),\n\t\t\t\tArguments.of(Cypher.datetime(\"2015-07-21T21:40:32.142+0100\"),\n\t\t\t\t\t\t\"RETURN datetime('2015-07-21T21:40:32.142+0100')\"),\n\t\t\t\tArguments.of(Cypher.datetime(Cypher.parameter(\"$myDateParameter\")),\n\t\t\t\t\t\t\"RETURN datetime($myDateParameter)\"),\n\t\t\t\tArguments.of(Cypher.datetime(TimeZone.getTimeZone(\"America/Los_Angeles\")),\n\t\t\t\t\t\t\"RETURN datetime({timezone: 'America/Los_Angeles'})\"),\n\t\t\t\tArguments.of(Cypher.localdatetime(), \"RETURN localdatetime()\"), Arguments.of(\n\t\t\t\t\t\tCypher.localdatetime(Cypher.mapOf(\"year\", Cypher.literalOf(1984), \"month\", Cypher.literalOf(10),\n\t\t\t\t\t\t\t\t\"day\", Cypher.literalOf(11), \"hour\", Cypher.literalOf(12), \"minute\",\n\t\t\t\t\t\t\t\tCypher.literalOf(31), \"second\", Cypher.literalOf(14), \"millisecond\",\n\t\t\t\t\t\t\t\tCypher\n\t\t\t\t\t\t\t\t\t.literalOf(123),\n\t\t\t\t\t\t\t\t\"microsecond\", Cypher.literalOf(456), \"nanosecond\", Cypher.literalOf(789))),\n\t\t\t\t\t\t\"RETURN localdatetime({year: 1984, month: 10, day: 11, hour: 12, minute: 31, second: 14, millisecond: 123, microsecond: 456, nanosecond: 789})\"),\n\t\t\t\tArguments.of(Cypher.localdatetime(\"2015-07-21T21:40:32.142\"),\n\t\t\t\t\t\t\"RETURN localdatetime('2015-07-21T21:40:32.142')\"),\n\t\t\t\tArguments.of(Cypher.localdatetime(Cypher.parameter(\"$myDateParameter\")),\n\t\t\t\t\t\t\"RETURN localdatetime($myDateParameter)\"),\n\t\t\t\tArguments.of(Cypher.localdatetime(TimeZone.getTimeZone(\"America/Los_Angeles\")),\n\t\t\t\t\t\t\"RETURN localdatetime({timezone: 'America/Los_Angeles'})\"),\n\t\t\t\tArguments.of(Cypher.localtime(), \"RETURN localtime()\"), Arguments.of(\n\t\t\t\t\t\tCypher.localtime(Cypher.mapOf(\"hour\", Cypher.literalOf(12), \"minute\", Cypher.literalOf(31),\n\t\t\t\t\t\t\t\t\"second\", Cypher.literalOf(14), \"millisecond\", Cypher\n\t\t\t\t\t\t\t\t\t.literalOf(123),\n\t\t\t\t\t\t\t\t\"microsecond\", Cypher.literalOf(456), \"nanosecond\", Cypher.literalOf(789))),\n\t\t\t\t\t\t\"RETURN localtime({hour: 12, minute: 31, second: 14, millisecond: 123, microsecond: 456, nanosecond: 789})\"),\n\t\t\t\tArguments.of(Cypher.localtime(\"21:40:32.142\"), \"RETURN localtime('21:40:32.142')\"),\n\t\t\t\tArguments.of(Cypher.localtime(Cypher.parameter(\"$myDateParameter\")),\n\t\t\t\t\t\t\"RETURN localtime($myDateParameter)\"),\n\t\t\t\tArguments.of(Cypher.localtime(TimeZone.getTimeZone(\"America/Los_Angeles\")),\n\t\t\t\t\t\t\"RETURN localtime({timezone: 'America/Los_Angeles'})\"),\n\t\t\t\tArguments.of(Cypher.time(), \"RETURN time()\"),\n\t\t\t\tArguments.of(\n\t\t\t\t\t\tCypher.time(Cypher.mapOf(\"hour\", Cypher.literalOf(12), \"minute\", Cypher.literalOf(31), \"second\",\n\t\t\t\t\t\t\t\tCypher.literalOf(14), \"millisecond\", Cypher.literalOf(123), \"microsecond\",\n\t\t\t\t\t\t\t\tCypher.literalOf(456), \"nanosecond\", Cypher.literalOf(789))),\n\t\t\t\t\t\t\"RETURN time({hour: 12, minute: 31, second: 14, millisecond: 123, microsecond: 456, nanosecond: 789})\"),\n\t\t\t\tArguments.of(Cypher.time(\"21:40:32.142\"), \"RETURN time('21:40:32.142')\"),\n\t\t\t\tArguments.of(Cypher.time(Cypher.parameter(\"$myDateParameter\")), \"RETURN time($myDateParameter)\"),\n\t\t\t\tArguments.of(Cypher.time(TimeZone.getTimeZone(\"America/Los_Angeles\")),\n\t\t\t\t\t\t\"RETURN time({timezone: 'America/Los_Angeles'})\"),\n\t\t\t\tArguments.of(\n\t\t\t\t\t\tCypher.duration(Cypher.mapOf(\"days\", Cypher.literalOf(14), \"hours\", Cypher.literalOf(16),\n\t\t\t\t\t\t\t\t\"minutes\", Cypher.literalOf(12))),\n\t\t\t\t\t\t\"RETURN duration({days: 14, hours: 16, minutes: 12})\"),\n\t\t\t\tArguments.of(Cypher.duration(\"P14DT16H12M\"), \"RETURN duration('P14DT16H12M')\"),\n\t\t\t\tArguments.of(Cypher.duration(Cypher.parameter(\"$myDateParameter\")),\n\t\t\t\t\t\t\"RETURN duration($myDateParameter)\"),\n\t\t\t\tArguments.of(Cypher.toInteger(Cypher.literalOf(\"23\")), \"RETURN toInteger('23')\"),\n\t\t\t\tArguments.of(Cypher.toString(Cypher.literalOf(23)), \"RETURN toString(23)\"),\n\t\t\t\tArguments.of(Cypher.toFloat(Cypher.literalOf(\"23.42\")), \"RETURN toFloat('23.42')\"),\n\t\t\t\tArguments.of(Cypher.toBoolean(Cypher.literalOf(\"false\")), \"RETURN toBoolean('false')\"),\n\t\t\t\tArguments.of(Cypher.randomUUID(), \"RETURN randomUUID()\"),\n\t\t\t\tArguments.of(Cypher.cartesian(2.3, 4.5), \"RETURN point({x: 2.3, y: 4.5})\"),\n\t\t\t\tArguments.of(Cypher.coordinate(56.7, 12.78), \"RETURN point({longitude: 56.7, latitude: 12.78})\"));\n\t}\n\n\t@Test\n\tvoid propertiesInvocationShouldBeReusable() {\n\n\t\tNode source = Cypher.node(\"Movie\", Cypher.mapOf(\"title\", Cypher.literalOf(\"The Matrix\"))).named(\"src\");\n\t\tFunctionInvocation p = Cypher.properties(source);\n\t\tNode copy = Cypher.node(\"MovieCopy\").named(\"copy\");\n\n\t\tString query = cypherRenderer.render(Cypher.match(source).create(copy).set(copy, p).returning(copy).build());\n\t\tassertThat(query).isEqualTo(\n\t\t\t\t\"MATCH (src:`Movie` {title: 'The Matrix'}) CREATE (copy:`MovieCopy`) SET copy = properties(src) RETURN copy\");\n\t}\n\n\t@ParameterizedTest\n\t@EnumSource(BuiltInFunctions.MathematicalFunctions.class)\n\tvoid mathFunctionsShouldBeRenderedAsExpected(BuiltInFunctions.MathematicalFunctions function)\n\t\t\tthrows NoSuchMethodException, InvocationTargetException, IllegalAccessException {\n\n\t\tif (function.getMinArgs() != function.getMaxArgs()) {\n\t\t\tClass<?>[] argTypes = new Class<?>[2];\n\t\t\targTypes[0] = Expression.class;\n\t\t\targTypes[1] = Expression[].class;\n\t\t\tMethod m = Functions.class.getDeclaredMethod(function.name().toLowerCase(Locale.ROOT), argTypes);\n\t\t\tm.setAccessible(true);\n\n\t\t\tExpression arg1 = Cypher.literalOf(1);\n\t\t\tfor (int n = 0; n <= function.getMaxArgs() - function.getMinArgs(); ++n) {\n\t\t\t\tExpression[] vargs = new Expression[n];\n\t\t\t\tStringBuilder expected = new StringBuilder(\"RETURN \" + function.getImplementationName() + \"(1\");\n\t\t\t\tfor (int i = 0; i < n; ++i) {\n\t\t\t\t\tvargs[i] = Cypher.literalOf(i);\n\t\t\t\t\texpected.append(\", \");\n\t\t\t\t\texpected.append(i);\n\t\t\t\t}\n\t\t\t\tFunctionInvocation f = (FunctionInvocation) m.invoke(null, arg1, vargs);\n\t\t\t\texpected.append(\");\");\n\t\t\t\tassertThat(cypherRenderer.render(Cypher.returning(f).build()) + \";\").isEqualTo(expected.toString());\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tStringBuilder expected = new StringBuilder(\"RETURN \" + function.getImplementationName() + \"(\");\n\n\t\t\tint n = function.getMinArgs();\n\t\t\tClass<?>[] argTypes = new Class<?>[n];\n\t\t\tExpression[] args = new Expression[n];\n\n\t\t\tfor (int i = 0; i < n; ++i) {\n\t\t\t\targTypes[i] = Expression.class;\n\t\t\t\targs[i] = Cypher.literalOf(i);\n\t\t\t\tif (i > 0) {\n\t\t\t\t\texpected.append(\", \");\n\t\t\t\t}\n\t\t\t\texpected.append(i);\n\t\t\t}\n\t\t\texpected.append(\");\");\n\n\t\t\tMethod m = Functions.class.getDeclaredMethod(function.name().toLowerCase(Locale.ROOT), argTypes);\n\t\t\tm.setAccessible(true);\n\t\t\tFunctionInvocation f = (FunctionInvocation) m.invoke(null, (Object[]) args);\n\t\t\tassertThat(cypherRenderer.render(Cypher.returning(f).build()) + \";\").isEqualTo(expected.toString());\n\t\t}\n\t}\n\n\t@ParameterizedTest(name = \"{0}\")\n\t@MethodSource(\"functionsToTest\")\n\tvoid functionShouldBeRenderedAsExpected(FunctionInvocation functionInvocation, String expected) {\n\t\tassertThat(cypherRenderer.render(Cypher.returning(functionInvocation).build())).isEqualTo(expected);\n\t}\n\n\t@ParameterizedTest(name = \"{0}\")\n\t@MethodSource(\"neo5jSpecificFunctions\")\n\tvoid neo5jSpecificFunctionsShouldWork(FunctionInvocation functionInvocation, String expected) {\n\t\tRenderer renderer = Renderer.getRenderer(Configuration.newConfig().withDialect(Dialect.NEO4J_5).build());\n\t\tassertThat(renderer.render(Cypher.returning(functionInvocation).build())).isEqualTo(expected);\n\t}\n\n\t@Test\n\tvoid assortedErrors() {\n\t\tvar literalExpression = Cypher.literalOf(\"something\");\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.left(literalExpression, null))\n\t\t\t.withMessage(\"length might not be null when the expression is not null\");\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.right(literalExpression, null))\n\t\t\t.withMessage(\"length might not be null when the expression is not null\");\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.substring(literalExpression, null, null))\n\t\t\t.withMessage(\"start is required\");\n\t}\n\n\t@Test // GH-777\n\tvoid isEmptyShouldWork() {\n\n\t\tvar p = Cypher.node(\"Person\").named(\"p\");\n\t\tvar stmt = Cypher.match(p)\n\t\t\t.where(Cypher.not(Cypher.isEmpty(p.property(\"nationality\"))))\n\t\t\t.returning(p.property(\"name\"), p.property(\"nationality\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(stmt)\n\t\t\t.isEqualTo(\"MATCH (p:`Person`) \" + \"WHERE NOT (isEmpty(p.nationality)) \" + \"RETURN p.name, p.nationality\");\n\t}\n\n\t@Nested\n\tclass Reduction {\n\n\t\t@Test\n\t\tvoid reductionOfPaths() {\n\n\t\t\tRelationship r = Cypher.node(\"Node\").named(\"n\").relationshipTo(Cypher.node(\"Node2\").named(\"m\")).named(\"r\");\n\t\t\tNamedPath namedPath = Cypher.path(\"patternPath\").definedBy(r);\n\n\t\t\tSymbolicName x = Cypher.name(\"x\");\n\t\t\tListExpression emptyList = Cypher.listOf();\n\t\t\tFunctionInvocation listToReduce = Cypher.relationships(namedPath);\n\t\t\tSymbolicName n = Cypher.name(\"n\");\n\t\t\tStatement statement = Cypher\n\t\t\t\t.returning(\n\t\t\t\t\t\tCypher.reduce(n).in(listToReduce).map(x.add(n)).accumulateOn(x).withInitialValueOf(emptyList))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"RETURN reduce(x = [], n IN relationships(patternPath) | (x + n))\");\n\t\t}\n\n\t\t@Test\n\t\tvoid manual() {\n\n\t\t\tNode a = Cypher.anyNode().named(\"a\");\n\t\t\tNode b = Cypher.anyNode().named(\"b\");\n\t\t\tNode c = Cypher.anyNode().named(\"c\");\n\t\t\tNamedPath p = Cypher.path(\"p\").definedBy(a.relationshipTo(b).relationshipTo(c));\n\t\t\tSymbolicName n = Cypher.name(\"n\");\n\t\t\tSymbolicName totalAge = Cypher.name(\"totalAge\");\n\t\t\tStatement statement = Cypher.match(p)\n\t\t\t\t.where(a.property(\"name\").isEqualTo(Cypher.literalOf(\"Alice\")))\n\t\t\t\t.and(b.property(\"name\").isEqualTo(Cypher.literalOf(\"Bob\")))\n\t\t\t\t.and(c.property(\"name\").isEqualTo(Cypher.literalOf(\"Daniel\")))\n\t\t\t\t.returning(Cypher.reduce(n)\n\t\t\t\t\t.in(Cypher.nodes(p))\n\t\t\t\t\t.map(totalAge.add(Cypher.property(n, \"age\")))\n\t\t\t\t\t.accumulateOn(totalAge)\n\t\t\t\t\t.withInitialValueOf(Cypher.literalOf(0))\n\t\t\t\t\t.as(\"reduction\"))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH p = (a)-->(b)-->(c) \" + \"WHERE (a.name = 'Alice' AND b.name = 'Bob' AND c.name = 'Daniel') \"\n\t\t\t\t\t\t\t+ \"RETURN reduce(totalAge = 0, n IN nodes(p) | (totalAge + n.age)) AS reduction\");\n\t\t}\n\n\t\t@Test\n\t\tvoid ofListComprehension() {\n\n\t\t\tSymbolicName n = Cypher.name(\"n\");\n\t\t\tSymbolicName totalAge = Cypher.name(\"totalAge\");\n\t\t\tSymbolicName x = Cypher.name(\"x\");\n\t\t\tStatement statement = Cypher\n\t\t\t\t.returning(Cypher.reduce(n)\n\t\t\t\t\t.in(Cypher.listWith(x)\n\t\t\t\t\t\t.in(Cypher.range(0, 10))\n\t\t\t\t\t\t.where(x.remainder(Cypher.literalOf(2)).isEqualTo(Cypher.literalOf(0)))\n\t\t\t\t\t\t.returning(x.pow(Cypher.literalOf(3))))\n\t\t\t\t\t.map(totalAge.add(n))\n\t\t\t\t\t.accumulateOn(totalAge)\n\t\t\t\t\t.withInitialValueOf(Cypher.literalOf(0.0))\n\t\t\t\t\t.as(\"result\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"RETURN reduce(totalAge = 0.0, n IN [x IN range(0, 10) WHERE (x % 2) = 0 | x^3] | (totalAge + n)) AS result\");\n\t\t}\n\n\t}\n\n\t@Nested // GH-728\n\tclass Graphs {\n\n\t\t@Test\n\t\tvoid namesShouldWork() {\n\t\t\tassertThat(Cypher.returning(Cypher.graphNames().as(\"name\")).build().getCypher())\n\t\t\t\t.isEqualTo(\"RETURN graph.names() AS name\");\n\t\t}\n\n\t\t@Test\n\t\tvoid propertiesByNameShouldWork() {\n\t\t\tvar name = Cypher.name(\"name\");\n\t\t\tvar stmnt = Cypher.unwind(Cypher.graphNames())\n\t\t\t\t.as(name)\n\t\t\t\t.returning(name, Cypher.graphPropertiesByName(name).as(\"props\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmnt.getCypher())\n\t\t\t\t.isEqualTo(\"UNWIND graph.names() AS name RETURN name, graph.propertiesByName(name) AS props\");\n\t\t}\n\n\t\t@Test\n\t\tvoid byNameShouldWork() {\n\t\t\tvar name = Cypher.name(\"graphName\");\n\t\t\tvar stmnt = Cypher.unwind(Cypher.graphNames())\n\t\t\t\t.as(name)\n\t\t\t\t.call(Cypher.use(Cypher.graphByName(name),\n\t\t\t\t\t\tCypher.match(Cypher.anyNode(\"n\")).returning(Cypher.name(\"n\")).build()))\n\t\t\t\t.returning(Cypher.name(\"n\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmnt.getCypher()).isEqualTo(\n\t\t\t\t\t\"UNWIND graph.names() AS graphName CALL (*) {USE graph.byName(graphName) MATCH (n) RETURN n} RETURN n\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/FunctionsTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.lang.reflect.Method;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.api.Named;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.junit.platform.commons.util.ReflectionUtils;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\nimport static org.mockito.Mockito.mock;\n\n/**\n * @author Michael J. Simons\n */\nclass FunctionsTests {\n\n\tprivate static final String FUNCTION_NAME_FIELD = \"functionName\";\n\n\t@SuppressWarnings(\"deprecation\")\n\tprivate static Stream<Arguments> functionsToTest() {\n\n\t\treturn ReflectionUtils\n\t\t\t.findMethods(Functions.class,\n\t\t\t\t\tmethod -> method.getParameterCount() == 1\n\t\t\t\t\t\t\t&& (method.getParameterTypes()[0].isAssignableFrom(Expression.class)\n\t\t\t\t\t\t\t\t\t|| method.getParameterTypes()[0].isAssignableFrom(Node.class)\n\t\t\t\t\t\t\t\t\t|| method.getParameterTypes()[0].isAssignableFrom(Relationship.class)\n\t\t\t\t\t\t\t\t\t|| method.getParameterTypes()[0].isAssignableFrom(MapExpression.class))\n\t\t\t\t\t\t\t&& (!java.util.Set.of(\"properties\", \"expressionOrNullLit\").contains(method.getName())\n\t\t\t\t\t\t\t\t\t|| !method.getParameterTypes()[0].isAssignableFrom(MapExpression.class)),\n\t\t\t\t\tReflectionUtils.HierarchyTraversalMode.TOP_DOWN)\n\t\t\t.stream()\n\t\t\t.map(method -> Arguments.of(Named.of(method.getName(), method)));\n\t}\n\n\t@ParameterizedTest(name = \"{index}: {0}\")\n\t@MethodSource(\"functionsToTest\")\n\tvoid preconditionsShouldBeAsserted(Method method) {\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> TestUtils.invokeMethod(method, null, (Expression) null))\n\t\t\t.withMessageMatching(\n\t\t\t\t\t\"The (expression|node|relationship|temporalAmount|temporalValue|variable|pattern|components) (?:for .* )?(?:is|are) required.\");\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource(\"functionsToTest\")\n\tvoid functionInvocationsShouldBeCreated(Method method) {\n\n\t\tvar expectedValue = method.getName().replace(\"Distinct\", \"\");\n\t\tif (expectedValue.startsWith(\"graph\")) {\n\t\t\texpectedValue = \"graph.\" + expectedValue.substring(5, 6).toLowerCase(Locale.ROOT)\n\t\t\t\t\t+ expectedValue.substring(6);\n\t\t}\n\n\t\tClass<?> parameterType = method.getParameterTypes()[0];\n\t\tObject parameter;\n\t\tif (parameterType == SymbolicName.class) {\n\t\t\tparameter = SymbolicName.of(\"undef\");\n\t\t}\n\t\telse if (parameterType == MapExpression.class) {\n\t\t\tparameter = MapExpression.create(Map.of());\n\t\t}\n\t\telse if (parameterType == org.neo4j.cypherdsl.core.Named.class || parameterType == Node.class) {\n\t\t\tparameter = Cypher.node(\"Undef\");\n\t\t}\n\t\telse if (parameterType == Relationship.class || parameterType == RelationshipPattern.class) {\n\t\t\tparameter = Cypher.node(\"Undef\").relationshipTo(Cypher.anyNode()).named(\"r\");\n\t\t}\n\t\telse if (parameterType == Expression.class) {\n\t\t\tparameter = SymbolicName.of(\"Undef\");\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException(\"Cannot test a function with parameter type \" + parameterType);\n\t\t}\n\t\tFunctionInvocation invocation = (FunctionInvocation) TestUtils.invokeMethod(method, null, parameter);\n\t\tassertThat(invocation).hasFieldOrPropertyWithValue(FUNCTION_NAME_FIELD, expectedValue);\n\t}\n\n\t@Nested\n\tclass coalesce {\n\n\t\t@Test\n\t\tvoid preconditionsShouldBeAsserted() {\n\n\t\t\tString message = \"The expression for coalesce() is required.\";\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.coalesce((Expression[]) null))\n\t\t\t\t.withMessage(message);\n\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.coalesce(new Expression[0]))\n\t\t\t\t.withMessage(message);\n\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.coalesce(new Expression[] { null }))\n\t\t\t\t.withMessage(message);\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldCreateCorrectInvocation() {\n\n\t\t\tFunctionInvocation invocation = Cypher.coalesce(mock(Expression.class));\n\t\t\tassertThat(invocation).hasFieldOrPropertyWithValue(FUNCTION_NAME_FIELD, \"coalesce\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/HintsIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\nimport static org.assertj.core.api.Assertions.assertThatIllegalStateException;\n\n/**\n * @author Michael J. Simons\n *\n */\nclass HintsIT {\n\n\tprivate static final Renderer cypherRenderer = Renderer.getDefaultRenderer();\n\n\tprivate Node liskov = Cypher.node(\"Scientist\").named(\"liskov\").withProperties(\"name\", Cypher.literalOf(\"Liskov\"));\n\n\tprivate Node wing = Cypher.node(\"Scientist\").named(\"wing\");\n\n\tprivate Node conway = Cypher.node(\"Scientist\").named(\"conway\").withProperties(\"name\", Cypher.literalOf(\"Conway\"));\n\n\tprivate Node cs = Cypher.node(\"Science\").named(\"cs\").withProperties(\"name\", Cypher.literalOf(\"Computer Science\"));\n\n\t@Nested\n\tclass IndexHints {\n\n\t\t@Test\n\t\tvoid usingIndexShouldWork() {\n\n\t\t\tStatement statement = Cypher\n\t\t\t\t.match(HintsIT.this.liskov.relationshipTo(HintsIT.this.wing, \"KNOWS\")\n\t\t\t\t\t.relationshipTo(HintsIT.this.cs, \"RESEARCHED\")\n\t\t\t\t\t.relationshipFrom(HintsIT.this.conway, \"RESEARCHED\"))\n\t\t\t\t.usingIndex(HintsIT.this.liskov.property(\"name\"))\n\t\t\t\t.returning(HintsIT.this.liskov.property(\"born\").as(\"column\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (liskov:`Scientist` {name: 'Liskov'})-[:`KNOWS`]->(wing:`Scientist`)-[:`RESEARCHED`]->(cs:`Science` {name: 'Computer Science'})<-[:`RESEARCHED`]-(conway:`Scientist` {name: 'Conway'}) \"\n\t\t\t\t\t\t\t+ \"USING INDEX liskov:`Scientist`(name) \" + \"RETURN liskov.born AS column\");\n\t\t}\n\n\t\t@Test\n\t\tvoid usingIndexSeekShouldWork() {\n\n\t\t\tStatement statement = Cypher\n\t\t\t\t.match(HintsIT.this.liskov.relationshipTo(HintsIT.this.wing, \"KNOWS\")\n\t\t\t\t\t.relationshipTo(HintsIT.this.cs, \"RESEARCHED\")\n\t\t\t\t\t.relationshipFrom(HintsIT.this.conway, \"RESEARCHED\"))\n\t\t\t\t.usingIndexSeek(HintsIT.this.liskov.property(\"name\"))\n\t\t\t\t.returning(HintsIT.this.liskov.property(\"born\").as(\"column\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (liskov:`Scientist` {name: 'Liskov'})-[:`KNOWS`]->(wing:`Scientist`)-[:`RESEARCHED`]->(cs:`Science` {name: 'Computer Science'})<-[:`RESEARCHED`]-(conway:`Scientist` {name: 'Conway'}) \"\n\t\t\t\t\t\t\t+ \"USING INDEX SEEK liskov:`Scientist`(name) \" + \"RETURN liskov.born AS column\");\n\t\t}\n\n\t\t@Test\n\t\tvoid usingCompositeIndexesShouldWork() {\n\n\t\t\tNode m = Cypher.node(\"Method\")\n\t\t\t\t.named(\"m\")\n\t\t\t\t.withProperties(\"name\", Cypher.literalOf(\"Foo\"), \"type\", Cypher.literalOf(\"Bar\"));\n\t\t\tStatement statement = Cypher.match(m)\n\t\t\t\t.usingIndex(m.property(\"name\"), m.property(\"type\"))\n\t\t\t\t.returning(m)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (m:`Method` {name: 'Foo', type: 'Bar'}) \"\n\t\t\t\t\t+ \"USING INDEX m:`Method`(name, type) \" + \"RETURN m\");\n\t\t}\n\n\t\t@Test\n\t\tvoid propertiesOfDifferentNodesCannotBeUsedOnTheSameHInt() {\n\n\t\t\tNode m = Cypher.node(\"Method\")\n\t\t\t\t.named(\"m\")\n\t\t\t\t.withProperties(\"name\", Cypher.literalOf(\"Foo\"), \"type\", Cypher.literalOf(\"Bar\"));\n\n\t\t\tassertThatIllegalStateException()\n\t\t\t\t.isThrownBy(() -> Cypher.match(m)\n\t\t\t\t\t.usingIndex(m.property(\"name\"), Cypher.node(\"Method\").named(\"x\").property(\"type\"))\n\t\t\t\t\t.returning(m)\n\t\t\t\t\t.build())\n\t\t\t\t.withMessage(\n\t\t\t\t\t\t\"If you want to use more than one index on different nodes you must use multiple `USING INDEX` statements.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid nestedPropertiesAreNotAllowed() {\n\n\t\t\tNode m = Cypher.node(\"Method\")\n\t\t\t\t.named(\"m\")\n\t\t\t\t.withProperties(\"name\", Cypher.literalOf(\"Foo\"), \"type\", Cypher.literalOf(\"Bar\"));\n\n\t\t\tassertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> Cypher.match(m).usingIndex(m.property(\"a\", \"name\")).returning(m).build())\n\t\t\t\t.withMessage(\"One single property is required. Nested properties are not supported.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid multipleLabelsAreNotAllowed() {\n\n\t\t\tNode m = Cypher.node(\"Method\", \"Foo\")\n\t\t\t\t.named(\"m\")\n\t\t\t\t.withProperties(\"name\", Cypher.literalOf(\"Foo\"), \"type\", Cypher.literalOf(\"Bar\"));\n\n\t\t\tassertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> Cypher.match(m).usingIndex(m.property(\"name\")).returning(m).build())\n\t\t\t\t.withMessage(\"Exactly one label is required to define the index.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid propertiesMustReferenceANode() {\n\n\t\t\tNode m = Cypher.node(\"Method\")\n\t\t\t\t.named(\"m\")\n\t\t\t\t.withProperties(\"name\", Cypher.literalOf(\"Foo\"), \"type\", Cypher.literalOf(\"Bar\"));\n\n\t\t\tassertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> Cypher.match(m).usingIndex(Cypher.property(\"m\", \"name\")).returning(m).build())\n\t\t\t\t.withMessage(\"Cannot use a property without a reference to a container inside an index hint.\");\n\t\t}\n\n\t\t@Neo4jVersion(minimum = \"4.3\")\n\t\t@Test\n\t\tvoid indexesOnRelationshipsShouldWork() {\n\n\t\t\tNode m = Cypher.node(\"Method\")\n\t\t\t\t.named(\"m\")\n\t\t\t\t.withProperties(\"name\", Cypher.literalOf(\"Foo\"), \"type\", Cypher.literalOf(\"Bar\"));\n\n\t\t\tRelationship r = m.relationshipTo(Cypher.node(\"Method\"), \"CALLS\")\n\t\t\t\t.named(\"r\")\n\t\t\t\t.withProperties(\"whatever\", Cypher.literalTrue());\n\n\t\t\tStatement statement = Cypher.match(r).usingIndex(r.property(\"whatever\")).returning(m).build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (m:`Method` {name: 'Foo', type: 'Bar'})-[r:`CALLS` {whatever: true}]->(:`Method`) USING INDEX r:`CALLS`(whatever) RETURN m\");\n\t\t}\n\n\t\t@Test\n\t\tvoid multipleIndizesShouldWork() {\n\n\t\t\tStatement statement = Cypher\n\t\t\t\t.match(HintsIT.this.liskov.relationshipTo(HintsIT.this.wing, \"KNOWS\")\n\t\t\t\t\t.relationshipTo(HintsIT.this.cs, \"RESEARCHED\")\n\t\t\t\t\t.relationshipFrom(HintsIT.this.conway, \"RESEARCHED\"))\n\t\t\t\t.usingIndex(HintsIT.this.liskov.property(\"name\"))\n\t\t\t\t.usingIndex(HintsIT.this.conway.property(\"name\"))\n\t\t\t\t.returning(HintsIT.this.liskov.property(\"born\").as(\"column\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (liskov:`Scientist` {name: 'Liskov'})-[:`KNOWS`]->(wing:`Scientist`)-[:`RESEARCHED`]->(cs:`Science` {name: 'Computer Science'})<-[:`RESEARCHED`]-(conway:`Scientist` {name: 'Conway'}) \"\n\t\t\t\t\t\t\t+ \"USING INDEX liskov:`Scientist`(name) \" + \"USING INDEX conway:`Scientist`(name) \"\n\t\t\t\t\t\t\t+ \"RETURN liskov.born AS column\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass ScanHints {\n\n\t\t@Test\n\t\tvoid usingScanHintsShouldWork() {\n\n\t\t\tNode s = Cypher.node(\"Scientist\").named(\"s\");\n\t\t\tStatement statement = Cypher.match(s)\n\t\t\t\t.usingScan(s)\n\t\t\t\t.where(s.property(\"born\").lt(Cypher.literalOf(1939)))\n\t\t\t\t.returning(s.property(\"born\").as(\"column\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (s:`Scientist`) \"\n\t\t\t\t\t+ \"USING SCAN s:`Scientist` \" + \"WHERE s.born < 1939 \" + \"RETURN s.born AS column\");\n\t\t}\n\n\t\t@Test\n\t\tvoid scansCanNotBeUsedWithMultipleLabels() {\n\n\t\t\tAssertions.assertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> Cypher.match(Cypher.node(\"Scientist\").named(\"s\"))\n\t\t\t\t\t.usingScan(Cypher.node(\"Scientist\", \"Other\").named(\"s\"))\n\t\t\t\t\t.returning(SymbolicName.of(\"s\"))\n\t\t\t\t\t.build())\n\t\t\t\t.withMessage(\"Exactly one label is required for a SCAN hint.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid scansCanNotBeUsedWithoutLabels() {\n\n\t\t\tAssertions.assertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> Cypher.match(Cypher.node(\"Scientist\").named(\"s\"))\n\t\t\t\t\t.usingScan(Cypher.anyNode())\n\t\t\t\t\t.returning(SymbolicName.of(\"s\"))\n\t\t\t\t\t.build())\n\t\t\t\t.withMessage(\"Exactly one label is required for a SCAN hint.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid scansNeedANode() {\n\n\t\t\tAssertions.assertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> Cypher.match(Cypher.node(\"Scientist\").named(\"s\"))\n\t\t\t\t\t.usingScan(null)\n\t\t\t\t\t.returning(SymbolicName.of(\"s\"))\n\t\t\t\t\t.build())\n\t\t\t\t.withMessage(\"Cannot apply a SCAN hint without a node.\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass JoinHints {\n\n\t\t@Test\n\t\tvoid singleJoinHintShouldWork() {\n\t\t\tStatement statement = Cypher\n\t\t\t\t.match(HintsIT.this.liskov.relationshipTo(HintsIT.this.wing, \"KNOWS\")\n\t\t\t\t\t.relationshipTo(HintsIT.this.cs, \"RESEARCHED\")\n\t\t\t\t\t.relationshipFrom(HintsIT.this.conway, \"RESEARCHED\"))\n\t\t\t\t.usingIndex(HintsIT.this.liskov.property(\"name\"))\n\t\t\t\t.usingIndex(HintsIT.this.conway.property(\"name\"))\n\t\t\t\t.usingJoinOn(HintsIT.this.wing)\n\t\t\t\t.returning(HintsIT.this.liskov.property(\"born\").as(\"column\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (liskov:`Scientist` {name: 'Liskov'})-[:`KNOWS`]->(wing:`Scientist`)-[:`RESEARCHED`]->(cs:`Science` {name: 'Computer Science'})<-[:`RESEARCHED`]-(conway:`Scientist` {name: 'Conway'}) \"\n\t\t\t\t\t\t\t+ \"USING INDEX liskov:`Scientist`(name) \" + \"USING INDEX conway:`Scientist`(name) \"\n\t\t\t\t\t\t\t+ \"USING JOIN ON wing \" + \"RETURN liskov.born AS column\");\n\t\t}\n\n\t\t@Test\n\t\tvoid multipleJoinHintShouldWork() {\n\t\t\tStatement statement = Cypher\n\t\t\t\t.match(HintsIT.this.liskov\n\t\t\t\t\t.relationshipTo(\n\t\t\t\t\t\t\tCypher.node(\"Scientist\").named(\"wing\").withProperties(\"name\", Cypher.literalOf(\"Wing\")),\n\t\t\t\t\t\t\t\"KNOWS\")\n\t\t\t\t\t.relationshipTo(HintsIT.this.cs, \"RESEARCHED\")\n\t\t\t\t\t.relationshipFrom(HintsIT.this.liskov, \"RESEARCHED\"))\n\t\t\t\t.usingIndex(HintsIT.this.liskov.property(\"name\"))\n\t\t\t\t.usingJoinOn(HintsIT.this.liskov, HintsIT.this.cs)\n\t\t\t\t.returning(HintsIT.this.wing.property(\"born\").as(\"column\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (liskov:`Scientist` {name: 'Liskov'})-[:`KNOWS`]->(wing:`Scientist` {name: 'Wing'})-[:`RESEARCHED`]->(cs:`Science` {name: 'Computer Science'})<-[:`RESEARCHED`]-(liskov) \"\n\t\t\t\t\t\t\t+ \"USING INDEX liskov:`Scientist`(name) \" + \"USING JOIN ON liskov, cs \"\n\t\t\t\t\t\t\t+ \"RETURN wing.born AS column\");\n\t\t}\n\n\t\t@Test\n\t\tvoid joinWithoutOtherIndexesShouldWork() {\n\t\t\tStatement statement = Cypher\n\t\t\t\t.match(HintsIT.this.liskov.relationshipTo(HintsIT.this.wing, \"KNOWS\")\n\t\t\t\t\t.relationshipTo(HintsIT.this.cs, \"RESEARCHED\")\n\t\t\t\t\t.relationshipFrom(HintsIT.this.conway, \"RESEARCHED\"))\n\t\t\t\t.usingJoinOn(HintsIT.this.wing)\n\t\t\t\t.returning(HintsIT.this.liskov.property(\"born\").as(\"column\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (liskov:`Scientist` {name: 'Liskov'})-[:`KNOWS`]->(wing:`Scientist`)-[:`RESEARCHED`]->(cs:`Science` {name: 'Computer Science'})<-[:`RESEARCHED`]-(conway:`Scientist` {name: 'Conway'}) \"\n\t\t\t\t\t\t\t+ \"USING JOIN ON wing \" + \"RETURN liskov.born AS column\");\n\t\t}\n\n\t\t@Test\n\t\tvoid joinRequiresNodeName() {\n\n\t\t\tAssertions.assertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> Cypher\n\t\t\t\t\t.match(HintsIT.this.liskov.relationshipTo(HintsIT.this.wing, \"KNOWS\")\n\t\t\t\t\t\t.relationshipTo(HintsIT.this.cs, \"RESEARCHED\")\n\t\t\t\t\t\t.relationshipFrom(HintsIT.this.conway, \"RESEARCHED\"))\n\t\t\t\t\t.usingJoinOn(new Node[0])\n\t\t\t\t\t.returning(HintsIT.this.liskov.property(\"born\").as(\"column\"))\n\t\t\t\t\t.build())\n\t\t\t\t.withMessage(\"At least one node is required to define a JOIN hint.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid joinRequiresSymbolicName() {\n\n\t\t\tAssertions.assertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> Cypher\n\t\t\t\t\t.match(HintsIT.this.liskov.relationshipTo(HintsIT.this.wing, \"KNOWS\")\n\t\t\t\t\t\t.relationshipTo(HintsIT.this.cs, \"RESEARCHED\")\n\t\t\t\t\t\t.relationshipFrom(HintsIT.this.conway, \"RESEARCHED\"))\n\t\t\t\t\t.usingJoinOn(new SymbolicName[0])\n\t\t\t\t\t.returning(HintsIT.this.liskov.property(\"born\").as(\"column\"))\n\t\t\t\t\t.build())\n\t\t\t\t.withMessage(\"At least one name is required to define a JOIN hint.\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/IdentifiableExpressionsIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Collection;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\nclass IdentifiableExpressionsIT {\n\n\t@Test\n\tvoid simpleWith() {\n\t\tNode b = Cypher.anyNode(\"b\");\n\t\tCollection<Expression> variables = Cypher.match(Cypher.node(\"Label\").named(\"a\").relationshipTo(b))\n\t\t\t.with(Cypher.name(\"a\"), b)\n\t\t\t.getIdentifiableExpressions();\n\n\t\tassertThat(variables.stream().map(Cypher::format)).containsExactlyInAnyOrder(\"a\", \"b\");\n\t}\n\n\t@Test\n\tvoid multipleHops() {\n\t\tNode b = Cypher.anyNode(\"b\");\n\t\tSymbolicName a = Cypher.name(\"a\");\n\t\tCollection<Expression> variables = Cypher.match(Cypher.node(\"Label\").named(\"a\").relationshipTo(b))\n\t\t\t.with(a, b)\n\t\t\t.optionalMatch(b.relationshipTo(Cypher.anyNode(\"c\")))\n\t\t\t.with(a, Cypher.name(\"c\"))\n\t\t\t.getIdentifiableExpressions();\n\n\t\tassertThat(variables.stream().map(Cypher::format)).containsExactlyInAnyOrder(\"a\", \"c\");\n\t}\n\n\t@Test\n\tvoid complexWith() {\n\t\tNode b = Cypher.anyNode(\"b\");\n\t\tNode a = Cypher.node(\"Label\").named(\"a\");\n\t\tCollection<Expression> variables = Cypher.match(a.relationshipTo(b))\n\t\t\t.with(a, b)\n\t\t\t.optionalMatch(b.relationshipTo(Cypher.anyNode(\"c\")))\n\t\t\t.with(a, Cypher.name(\"c\"),\n\t\t\t\t\tCypher.caseExpression()\n\t\t\t\t\t\t.when(Cypher.name(\"c\").isNull().or(Cypher.hasLabelsOrType(Cypher.name(\"c\"), \"Label\")))\n\t\t\t\t\t\t.then(Cypher.literalTrue())\n\t\t\t\t\t\t.elseDefault(Cypher.literalFalse())\n\t\t\t\t\t\t.as(\"isNullOrLabel\"))\n\t\t\t.getIdentifiableExpressions();\n\n\t\tassertThat(variables.stream().map(Cypher::format)).containsExactlyInAnyOrder(\"a\", \"c\", \"isNullOrLabel\");\n\t}\n\n\t@Test\n\t@SuppressWarnings(\"deprecation\")\n\tvoid complexWithAsStatement() {\n\t\tNode b = Cypher.anyNode(\"b\");\n\t\tNode a = Cypher.node(\"Label\").named(\"a\");\n\t\tCollection<Expression> variables = Cypher.match(a.relationshipTo(b))\n\t\t\t.with(a, b)\n\t\t\t.optionalMatch(b.relationshipTo(Cypher.anyNode(\"c\")))\n\t\t\t.returning(a.getRequiredSymbolicName(), Cypher.name(\"c\"),\n\t\t\t\t\tCypher.caseExpression()\n\t\t\t\t\t\t.when(Cypher.name(\"c\").isNull().or(Cypher.hasLabelsOrType(Cypher.name(\"c\"), \"Label\")))\n\t\t\t\t\t\t.then(Cypher.literalTrue())\n\t\t\t\t\t\t.elseDefault(Cypher.literalFalse())\n\t\t\t\t\t\t.as(\"isNullOrLabel\"))\n\t\t\t.build()\n\t\t\t.getCatalog()\n\t\t\t.getIdentifiableExpressions();\n\n\t\tassertThat(variables.stream().map(Cypher::format)).containsExactlyInAnyOrder(\"a\", \"c\", \"isNullOrLabel\");\n\t}\n\n\t@Test\n\tvoid noneExpressionsInReturn() {\n\t\tNode b = Cypher.anyNode(\"b\");\n\t\tNode a = Cypher.node(\"Label\").named(\"a\");\n\t\tCollection<Expression> variables = Cypher.match(a.relationshipTo(b))\n\t\t\t.returning(a)\n\t\t\t.build()\n\t\t\t.getCatalog()\n\t\t\t.getIdentifiableExpressions();\n\n\t\tassertThat(variables.stream().map(Cypher::format)).containsExactlyInAnyOrder(\"a\");\n\t}\n\n\t@Test\n\tvoid nonIdentifiableItems() {\n\t\tNode b = Cypher.anyNode(\"b\");\n\t\tNode a = Cypher.node(\"Label\").named(\"a\");\n\t\tCollection<Expression> variables = Cypher.match(a.relationshipTo(b))\n\t\t\t.with(b.as(\"007\"))\n\t\t\t.getIdentifiableExpressions();\n\n\t\tassertThat(variables.stream().map(Cypher::format)).containsExactlyInAnyOrder(\"007\");\n\t}\n\n\t@Test\n\tvoid onReturn() {\n\t\tNode b = Cypher.anyNode(\"b\");\n\t\tCollection<Expression> variables = Cypher.returning(Cypher.literalOf(1), b.as(\"007\"), b.property(\"f\"))\n\t\t\t.getIdentifiableExpressions();\n\n\t\tassertThat(variables.stream().map(Cypher::format)).containsExactlyInAnyOrder(\"007\", \"b.f\");\n\t}\n\n\t@Test\n\tvoid returnedProperties() {\n\n\t\tNode b = Cypher.anyNode(\"b\");\n\t\tCollection<Expression> variables = Cypher.match(b)\n\t\t\t.returning(b.property(\"x\"), b.as(\"007\"))\n\t\t\t.getIdentifiableExpressions();\n\n\t\tassertThat(variables.stream().map(Cypher::format)).containsExactlyInAnyOrder(\"b.x\", \"007\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/InternalNodeImplTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.TestInstance;\nimport org.junit.jupiter.api.TestInstance.Lifecycle;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\nimport static org.assertj.core.api.Assertions.assertThatIllegalStateException;\n\n/**\n * This tests focus on the internal node implementation.\n *\n * @author Michael J. Simons\n */\nclass InternalNodeImplTests {\n\n\t@Test\n\tvoid preconditionsShouldBeAsserted() {\n\t\tString expectedMessage = \"A primary label is required.\";\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> new InternalNodeImpl(\"\")).withMessage(expectedMessage);\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> new InternalNodeImpl(\" \\t\")).withMessage(expectedMessage);\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.node(\"\")).withMessage(expectedMessage);\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.node(\" \\t\")).withMessage(expectedMessage);\n\t}\n\n\t@Test\n\tvoid shouldNotAddEmptyAdditionalLabels() {\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> new InternalNodeImpl(\"primary\", \" \", \"\\t \"))\n\t\t\t.withMessage(\"An empty label is not allowed.\");\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.node(\"primary\", \" \", \"\\t \"))\n\t\t\t.withMessage(\"An empty label is not allowed.\");\n\t}\n\n\t@Test\n\tvoid shouldCreateNodes() {\n\n\t\tNode node = new InternalNodeImpl(\"primary\", \"secondary\");\n\t\tList<String> labels = new ArrayList<>();\n\t\tnode.accept(new Visitor() {\n\t\t\t@Override\n\t\t\tpublic void enter(Visitable segment) {\n\n\t\t\t\tif (segment instanceof NodeLabel) {\n\t\t\t\t\tlabels.add(((NodeLabel) segment).getValue());\n\t\t\t\t}\n\n\t\t\t}\n\t\t});\n\t\tassertThat(labels).contains(\"primary\", \"secondary\");\n\t}\n\n\t@Nested\n\tclass MutationsAndSetShouldRequireName {\n\n\t\t@Test\n\t\tvoid mutationWithParameter() {\n\n\t\t\tNode node = Cypher.anyNode();\n\t\t\tParameter<?> parameter = Cypher.parameter(\"x\");\n\t\t\tassertThatIllegalStateException().isThrownBy(() -> node.mutate(parameter))\n\t\t\t\t.withMessage(\"A property container must be named to be mutated.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid mutationWithMap() {\n\n\t\t\tNode node = Cypher.anyNode();\n\t\t\tMapExpression mapExpression = Cypher.mapOf(\"a\", Cypher.literalTrue());\n\t\t\tassertThatIllegalStateException().isThrownBy(() -> node.mutate(mapExpression))\n\t\t\t\t.withMessage(\"A property container must be named to be mutated.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid setWithParameter() {\n\n\t\t\tNode node = Cypher.anyNode();\n\t\t\tParameter<?> parameter = Cypher.parameter(\"x\");\n\t\t\tassertThatIllegalStateException().isThrownBy(() -> node.set(parameter))\n\t\t\t\t.withMessage(\"A property container must be named to be mutated.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid setWithMap() {\n\n\t\t\tNode node = Cypher.anyNode();\n\t\t\tMapExpression mapExpression = Cypher.mapOf(\"a\", Cypher.literalTrue());\n\t\t\tassertThatIllegalStateException().isThrownBy(() -> node.set(mapExpression))\n\t\t\t\t.withMessage(\"A property container must be named to be mutated.\");\n\t\t}\n\n\t}\n\n\t@Nested\n\t@TestInstance(Lifecycle.PER_CLASS)\n\tclass PropertiesShouldBeHandled {\n\n\t\tprivate Stream<Arguments> createNodesWithProperties() {\n\t\t\treturn Stream.of(\n\t\t\t\t\tArguments.of(new InternalNodeImpl(\"N\").named(\"n\").withProperties(\"p\", Cypher.literalTrue())),\n\t\t\t\t\tArguments.of(new InternalNodeImpl(\"N\").named(\"n\")\n\t\t\t\t\t\t.withProperties(MapExpression.create(false, \"p\", Cypher.literalTrue()))));\n\t\t}\n\n\t\t@ParameterizedTest\n\t\t@MethodSource(\"createNodesWithProperties\")\n\t\tvoid shouldAddProperties(Node node) {\n\n\t\t\tAtomicBoolean failTest = new AtomicBoolean(true);\n\t\t\tnode.accept(new Visitor() {\n\t\t\t\tClass<?> expectedTypeOfNextSegment = null;\n\n\t\t\t\t@Override\n\t\t\t\tpublic void enter(Visitable segment) {\n\t\t\t\t\tif (segment instanceof SymbolicName) {\n\t\t\t\t\t\tassertThat(((SymbolicName) segment).getValue()).isEqualTo(\"n\");\n\t\t\t\t\t}\n\t\t\t\t\telse if (segment instanceof NodeLabel) {\n\t\t\t\t\t\tassertThat(((NodeLabel) segment).getValue()).isEqualTo(\"N\");\n\t\t\t\t\t}\n\t\t\t\t\telse if (segment instanceof KeyValueMapEntry) {\n\t\t\t\t\t\tassertThat(((KeyValueMapEntry) segment).getKey()).isEqualTo(\"p\");\n\t\t\t\t\t\tthis.expectedTypeOfNextSegment = BooleanLiteral.class;\n\t\t\t\t\t}\n\t\t\t\t\telse if (this.expectedTypeOfNextSegment != null) {\n\t\t\t\t\t\tassertThat(segment).isInstanceOf(this.expectedTypeOfNextSegment);\n\t\t\t\t\t\tfailTest.getAndSet(false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tassertThat(failTest).isFalse();\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldCreateProperty() {\n\n\t\t\tNode node = new InternalNodeImpl(\"N\").named(\"n\");\n\t\t\tProperty property = node.property(\"p\");\n\n\t\t\tjava.util.Set<Object> expected = new HashSet<>();\n\t\t\texpected.addAll(property.getNames());\n\t\t\texpected.add(node.getRequiredSymbolicName());\n\t\t\texpected.add(property);\n\n\t\t\tproperty.accept(expected::remove);\n\n\t\t\tassertThat(expected).isEmpty();\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/InternalPropertyImplTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass InternalPropertyImplTests {\n\n\t@Test\n\tvoid simplePropertyGetNameShouldWork() {\n\n\t\tassertThat(InternalPropertyImpl.create(SymbolicName.unresolved(), \"simple\").getName()).isEqualTo(\"simple\");\n\t}\n\n\t@Test\n\tvoid multiplePropertyGetNameShouldWork() {\n\n\t\tassertThat(InternalPropertyImpl.create(SymbolicName.unresolved(), \"foo\", \"bar\").getName()).isEqualTo(\"foo.bar\");\n\t}\n\n\t@Test\n\tvoid externalReferenceHasPriority() {\n\n\t\tassertThat(InternalPropertyImpl.create(SymbolicName.unresolved(), \"foo\", \"bar\")\n\t\t\t.referencedAs(\"something\")\n\t\t\t.getName()).isEqualTo(\"something\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/InternalRelationshipImplTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.HashSet;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.TestInstance;\nimport org.junit.jupiter.api.TestInstance.Lifecycle;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n */\nclass InternalRelationshipImplTests {\n\n\t@Test\n\tvoid preconditionsShouldBeAsserted() {\n\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> new InternalRelationshipImpl(null, null, null, null, Cypher.node(\"a\"), new String[0]))\n\t\t\t.withMessage(\"Left node is required.\");\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> new InternalRelationshipImpl(null, Cypher.node(\"a\"), null, null, null, new String[0]))\n\t\t\t.withMessage(\"Right node is required.\");\n\t}\n\n\t@Nested\n\t@TestInstance(Lifecycle.PER_CLASS)\n\tclass PropertiesShouldBeHandled {\n\n\t\tprivate Stream<Arguments> createNodesWithProperties() {\n\t\t\treturn Stream.of(\n\t\t\t\t\tArguments.of(Cypher.node(\"N\")\n\t\t\t\t\t\t.named(\"n\")\n\t\t\t\t\t\t.relationshipTo(Cypher.anyNode())\n\t\t\t\t\t\t.withProperties(\"p\", Cypher.literalTrue())),\n\t\t\t\t\tArguments.of(Cypher.node(\"N\")\n\t\t\t\t\t\t.named(\"n\")\n\t\t\t\t\t\t.relationshipTo(Cypher.anyNode())\n\t\t\t\t\t\t.withProperties(MapExpression.create(false, \"p\", Cypher.literalTrue()))));\n\t\t}\n\n\t\t@ParameterizedTest\n\t\t@MethodSource(\"createNodesWithProperties\")\n\t\tvoid shouldAddProperties(Relationship relationship) {\n\n\t\t\tAtomicBoolean failTest = new AtomicBoolean(true);\n\t\t\trelationship.accept(new Visitor() {\n\t\t\t\tClass<?> expectedTypeOfNextSegment = null;\n\n\t\t\t\t@Override\n\t\t\t\tpublic void enter(Visitable segment) {\n\t\t\t\t\tif (segment instanceof SymbolicName) {\n\t\t\t\t\t\tassertThat(((SymbolicName) segment).getValue()).isEqualTo(\"n\");\n\t\t\t\t\t}\n\t\t\t\t\telse if (segment instanceof NodeLabel) {\n\t\t\t\t\t\tassertThat(((NodeLabel) segment).getValue()).isEqualTo(\"N\");\n\t\t\t\t\t}\n\t\t\t\t\telse if (segment instanceof KeyValueMapEntry) {\n\t\t\t\t\t\tassertThat(((KeyValueMapEntry) segment).getKey()).isEqualTo(\"p\");\n\t\t\t\t\t\tthis.expectedTypeOfNextSegment = BooleanLiteral.class;\n\t\t\t\t\t}\n\t\t\t\t\telse if (this.expectedTypeOfNextSegment != null) {\n\t\t\t\t\t\tassertThat(segment).isInstanceOf(this.expectedTypeOfNextSegment);\n\t\t\t\t\t\tfailTest.getAndSet(false);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void leave(Visitable segment) {\n\t\t\t\t\tif (this.expectedTypeOfNextSegment == BooleanLiteral.class) {\n\t\t\t\t\t\tfailTest.getAndSet(true);\n\t\t\t\t\t\tthis.expectedTypeOfNextSegment = Node.class;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tassertThat(failTest).isFalse();\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldCreateProperty() {\n\n\t\t\tRelationship relationship = Cypher.node(\"N\").named(\"n\").relationshipTo(Cypher.anyNode()).named(\"r\");\n\t\t\tProperty property = relationship.property(\"p\");\n\n\t\t\tjava.util.Set<Object> expected = new HashSet<>();\n\t\t\texpected.addAll(property.getNames());\n\t\t\texpected.add(relationship.getRequiredSymbolicName());\n\t\t\texpected.add(property);\n\n\t\t\tproperty.accept(expected::remove);\n\n\t\t\tassertThat(expected).isEmpty();\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/IssueRelatedIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.time.ZonedDateTime;\nimport java.util.Collections;\nimport java.util.EnumSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.TreeMap;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.EnumSource;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Dialect;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n */\nclass IssueRelatedIT {\n\n\tprivate static final Renderer cypherRenderer = Renderer.getDefaultRenderer();\n\n\tprivate final Node person = Cypher.node(\"Person\").named(\"person\");\n\n\tstatic Stream<Arguments> relpatternChainingArgs() {\n\t\tStream.Builder<Arguments> arguments = Stream.builder();\n\t\targuments.add(Arguments.of(true, 1, false,\n\t\t\t\t\"MATCH (s)-[:`PART_OF`*0..1]->(:`Resume`)-[:`IS_PARALLEL`*0..1]->(:`Resume`)-[l:`LEADS_TO`]->(e) RETURN s, l, e\"));\n\t\targuments.add(Arguments.of(true, 2, false,\n\t\t\t\t\"MATCH (s)-[:`PART_OF`*0..1]->(:`Resume`)-[:`IS_PARALLEL`*0..1]->(:`Resume`)-[l:`LEADS_TO`*2..2]->(e) RETURN s, l, e\"));\n\t\targuments.add(Arguments.of(true, 1, true,\n\t\t\t\t\"MATCH (s)-[:`PART_OF`*0..1]->(:`Resume`)-[:`IS_PARALLEL`*0..1]->(:`Resume`)<-[l:`LEADS_TO`]-(e) RETURN s, l, e\"));\n\t\targuments.add(Arguments.of(true, 2, true,\n\t\t\t\t\"MATCH (s)-[:`PART_OF`*0..1]->(:`Resume`)-[:`IS_PARALLEL`*0..1]->(:`Resume`)<-[l:`LEADS_TO`*2..2]-(e) RETURN s, l, e\"));\n\n\t\targuments.add(Arguments.of(false, 1, false, \"MATCH (s)-[l:`LEADS_TO`]->(e) RETURN s, l, e\"));\n\t\targuments.add(Arguments.of(false, 2, false, \"MATCH (s)-[l:`LEADS_TO`*2..2]->(e) RETURN s, l, e\"));\n\t\targuments.add(Arguments.of(false, 1, true, \"MATCH (s)<-[l:`LEADS_TO`]-(e) RETURN s, l, e\"));\n\t\targuments.add(Arguments.of(false, 2, true, \"MATCH (s)<-[l:`LEADS_TO`*2..2]-(e) RETURN s, l, e\"));\n\n\t\treturn arguments.build();\n\t}\n\n\tstatic Statement createSomewhatComplexStatement() {\n\t\tNode this0 = Cypher.node(\"Movie\").named(\"this0\");\n\n\t\tCondition validationCondition = Cypher.any(\"r\")\n\t\t\t.in(Cypher.listOf(Cypher.literalOf(\"admin\")))\n\t\t\t.where(Cypher.any(\"rr\")\n\t\t\t\t.in(Cypher.parameter(\"$auth.roles\"))\n\t\t\t\t.where(SymbolicName.of(\"r\").eq(SymbolicName.of(\"rr\"))));\n\n\t\tNode g = Cypher.node(\"Genre\")\n\t\t\t.named(\"this0_genres_connectOrCreate0\")\n\t\t\t.withProperties(Cypher.mapOf(\"name\", Cypher.parameter(\"this0_genres_connectOrCreate0_node_name\")));\n\n\t\tStatement innerSubquery = Cypher.call(\"apoc.util.validate\")\n\t\t\t.withArgs(validationCondition.not(), Cypher.literalOf(\"@neo4j/graphql/FORBIDDEN\"),\n\t\t\t\t\tCypher.listOf(Cypher.literalOf(0)))\n\t\t\t.withoutResults()\n\t\t\t.merge(g)\n\t\t\t.onCreate()\n\t\t\t.set(g.property(\"name\").to(Cypher.parameter(\"this0_genres_connectOrCreate0_on_create_name\")))\n\t\t\t.merge(this0.relationshipTo(g, \"IN_GENRE\").named(\"this0_relationship_this0_genres_connectOrCreate0\"))\n\t\t\t.returning(Cypher.count(Cypher.asterisk()))\n\t\t\t.build();\n\n\t\tStatement subquery = Cypher.create(this0)\n\t\t\t.set(this0.property(\"title\").to(Cypher.parameter(\"this0_title\")))\n\t\t\t.with(this0)\n\t\t\t.call(innerSubquery, this0)\n\t\t\t.returning(this0)\n\t\t\t.build();\n\n\t\treturn Cypher.call(subquery)\n\t\t\t.returning(Cypher.listOf(Cypher.createProjection(this0.getRequiredSymbolicName(), \"title\")).as(\"data\"))\n\t\t\t.build();\n\t}\n\n\tstatic MapExpression toMap(ZonedDateTime value) {\n\t\treturn Cypher.mapOf(\"year\", Cypher.literalOf(value.getYear()), \"month\", Cypher.literalOf(value.getMonthValue()),\n\t\t\t\t\"day\", Cypher.literalOf(value.getDayOfMonth()), \"hour\", Cypher.literalOf(value.getHour()), \"minute\",\n\t\t\t\tCypher.literalOf(value.getMinute()), \"second\", Cypher.literalOf(value.getSecond()), \"nanosecond\",\n\t\t\t\tCypher.literalOf(value.getNano()), \"timezone\", Cypher.literalOf(value.getZone().toString()));\n\t}\n\n\tstatic Stream<Arguments> conditionExpressionShouldWorkInReturn() {\n\t\treturn Stream.of(\n\t\t\t\tArguments.of(Cypher.returning(Cypher.literalOf(1), Cypher.literalTrue().asCondition()).build(),\n\t\t\t\t\t\t\"RETURN 1, true\"),\n\t\t\t\tArguments.of(Cypher\n\t\t\t\t\t.returning(Cypher.literalOf(1),\n\t\t\t\t\t\t\tCypher.literalTrue().asCondition().and(Cypher.literalFalse().asCondition()))\n\t\t\t\t\t.build(), \"RETURN 1, (true AND false)\"),\n\t\t\t\tArguments.of(Cypher\n\t\t\t\t\t.returning(Cypher.literalOf(1),\n\t\t\t\t\t\t\tCypher.literalTrue().asCondition().or(Cypher.literalFalse().asCondition()))\n\t\t\t\t\t.build(), \"RETURN 1, (true OR false)\"));\n\t}\n\n\tstatic Stream<Arguments> reusingAliases() {\n\t\treturn Stream.of(\n\t\t\t\tArguments.of(EnumSet.complementOf(EnumSet.of(Configuration.GeneratedNames.REUSE_ALIASES)),\n\t\t\t\t\t\t\"MATCH (v0:`Movie`) RETURN v0{.a, .b} AS v1\"),\n\t\t\t\tArguments.of(EnumSet.allOf(Configuration.GeneratedNames.class),\n\t\t\t\t\t\t\"MATCH (v0:`Movie`) RETURN v0{.a, .b} AS v0\"));\n\t}\n\n\t@Test\n\tvoid gh266SizeShouldBeSupported() {\n\n\t\tNode node = Cypher.node(\"Node\").named(\"node\");\n\t\tString cypher = Cypher.match(node).returning(node.property(\"thing\").size()).build().getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (node:`Node`) RETURN size(node.thing)\");\n\t}\n\n\t@Test\n\tvoid gh266HasSizeUtilityShouldWork() {\n\n\t\tNode node = Cypher.node(\"Node\").named(\"node\");\n\t\tString cypher = Cypher.match(node)\n\t\t\t.where(node.property(\"thing\").hasSize(Cypher.literalOf(0)))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (node:`Node`) WHERE size(node.thing) = 0 RETURN *\");\n\t}\n\n\t@Test\n\tvoid gh115() {\n\t\tNode nodes = Cypher.node(\"Node\").named(\"node\").withProperties(\"id\", Cypher.literalOf(\"node_42\"));\n\t\tStatementBuilder.OngoingReadingWithoutWhere matchNodes = Cypher.match(nodes);\n\n\t\tNamedPath p = Cypher.path(Cypher.name(\"path\")).get();\n\t\tStatement statement = matchNodes.call(\"apoc.path.spanningTree\")\n\t\t\t.withArgs(nodes.getRequiredSymbolicName(),\n\t\t\t\t\tCypher.mapOf(\"relationshipFilter\", Cypher.literalOf(\"<rel_filter>\"), \"labelFilter\",\n\t\t\t\t\t\t\tCypher.literalOf(\"<label_filter>\")))\n\t\t\t.yield(p)\n\t\t\t.returningDistinct(nodes.getRequiredSymbolicName(), Cypher.collect(Cypher.relationships(p)).as(\"rels\"),\n\t\t\t\t\tCypher.collect(Cypher.nodes(p)).as(\"nodes\"))\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (node:`Node` {id: 'node_42'}) \"\n\t\t\t\t+ \"CALL apoc.path.spanningTree(node, {relationshipFilter: '<rel_filter>', labelFilter: '<label_filter>'}) YIELD path \"\n\t\t\t\t+ \"RETURN DISTINCT node, collect(relationships(path)) AS rels, collect(nodes(path)) AS nodes\");\n\t}\n\n\t@Test\n\tvoid gh70() {\n\t\tNode strawberry = Cypher.node(\"Fruit\", Cypher.mapOf(\"kind\", Cypher.literalOf(\"strawberry\")));\n\t\tStatement statement = Cypher.match(strawberry)\n\t\t\t.set(strawberry.property(\"color\").to(Cypher.literalOf(\"red\")))\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t.matches(\"MATCH \\\\([a-zA-Z]*\\\\d{3}:`Fruit` \\\\{kind: 'strawberry'}\\\\) SET [a-zA-Z]*\\\\d{3}\\\\.color = 'red'\");\n\t}\n\n\t@Test\n\tvoid gh167() {\n\t\tfinal Node app = Cypher.node(\"Location\").named(\"app\").withProperties(\"uuid\", Cypher.parameter(\"app_uuid\"));\n\t\tfinal Node locStart = Cypher.node(\"Location\").named(\"loc_start\");\n\t\tfinal Node resume = Cypher.node(\"Resume\").named(\"r\");\n\t\tfinal Node offer = Cypher.node(\"Offer\").named(\"o\");\n\t\tfinal Node startN = Cypher.node(\"ResumeNode\").named(\"start_n\");\n\n\t\tfinal Relationship aFl = app.relationshipFrom(locStart, \"PART_OF\").length(0, 3);\n\t\tfinal Relationship lFr = locStart.relationshipFrom(resume, \"IN\", \"IN_ANALYTICS\");\n\n\t\t@SuppressWarnings(\"deprecation\")\n\t\tStatement statement = Cypher.match(aFl, lFr)\n\t\t\t.withDistinct(resume, locStart, app)\n\t\t\t.match(resume.relationshipTo(offer.withProperties(\"is_valid\", Cypher.literalTrue()), \"IN_COHORT_OF\")\n\t\t\t\t.relationshipTo(Cypher.anyNode(\"app\"), \"IN\"))\n\t\t\t.withDistinct(resume, locStart, app, offer)\n\t\t\t.match(offer.relationshipTo(startN, \"FOR\"))\n\t\t\t.where(Functions.id(startN).in(Cypher.parameter(\"start_ids\")))\n\t\t\t.returningDistinct(resume, locStart, app, offer, startN)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"MATCH (app:`Location` {uuid: $app_uuid})<-[:`PART_OF`*0..3]-(loc_start:`Location`), (loc_start)<-[:`IN`|`IN_ANALYTICS`]-(r:`Resume`) WITH DISTINCT r, loc_start, app MATCH (r)-[:`IN_COHORT_OF`]->(o:`Offer` {is_valid: true})-[:`IN`]->(app) WITH DISTINCT r, loc_start, app, o MATCH (o)-[:`FOR`]->(start_n:`ResumeNode`) WHERE id(start_n) IN $start_ids RETURN DISTINCT r, loc_start, app, o, start_n\");\n\t}\n\n\t@Test\n\tvoid gh174() {\n\t\tfinal Node r = Cypher.node(\"Resume\").named(\"r\");\n\t\tfinal Node o = Cypher.node(\"Offer\").named(\"o\");\n\n\t\tStatement s = Cypher.match(r.relationshipTo(o, \"FOR\"))\n\t\t\t.where(r.hasLabels(\"LastResume\").not())\n\t\t\t.and(Cypher.coalesce(o.property(\"valid_only\"), Cypher.literalFalse())\n\t\t\t\t.isEqualTo(Cypher.literalFalse())\n\t\t\t\t.and(r.hasLabels(\"InvalidStatus\").not())\n\t\t\t\t.or(o.property(\"valid_only\").isTrue().and(r.hasLabels(\"InvalidStatus\"))))\n\t\t\t.returningDistinct(r, o)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(s)).isEqualTo(\n\t\t\t\t\"MATCH (r:`Resume`)-[:`FOR`]->(o:`Offer`) WHERE (NOT (r:`LastResume`) AND ((coalesce(o.valid_only, false) = false AND NOT (r:`InvalidStatus`)) OR (o.valid_only = true AND r:`InvalidStatus`))) RETURN DISTINCT r, o\");\n\t}\n\n\t@Test\n\tvoid gh184() {\n\t\tfinal Node r = Cypher.node(\"Resume\").named(\"r\");\n\t\tfinal Node u = Cypher.node(\"UserSearchable\").named(\"u\");\n\t\tfinal Node o = Cypher.node(\"Offer\").named(\"o\");\n\n\t\tStatement s = Cypher.match(r.relationshipFrom(u, \"HAS\"))\n\t\t\t.where(r.hasLabels(\"LastResume\").not())\n\t\t\t.and(Cypher.coalesce(o.property(\"valid_only\"), Cypher.literalFalse())\n\t\t\t\t.isEqualTo(Cypher.literalFalse())\n\t\t\t\t.and(r.hasLabels(\"InvalidStatus\").not())\n\t\t\t\t.or(o.property(\"valid_only\").isTrue().and(r.hasLabels(\"ValidStatus\"))))\n\t\t\t.and(r.property(\"is_internship\")\n\t\t\t\t.isTrue()\n\t\t\t\t.and(Cypher.size(r.relationshipTo(Cypher.anyNode(), \"PART_OF\")).isEmpty())\n\t\t\t\t.not())\n\t\t\t.and(r.property(\"is_sandwich_training\")\n\t\t\t\t.isTrue()\n\t\t\t\t.and(Cypher.size(r.relationshipTo(Cypher.anyNode(), \"PART_OF\")).isEmpty())\n\t\t\t\t.not())\n\t\t\t.returningDistinct(r, o)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(s)).isEqualTo(\"MATCH (r:`Resume`)<-[:`HAS`]-(u:`UserSearchable`) \"\n\t\t\t\t+ \"WHERE (NOT (r:`LastResume`) \" + \"AND ((coalesce(o.valid_only, false) = false \"\n\t\t\t\t+ \"AND NOT (r:`InvalidStatus`)) \" + \"OR (o.valid_only = true \" + \"AND r:`ValidStatus`)) \" + \"AND NOT (\"\n\t\t\t\t+ \"(r.is_internship = true AND size(size((r)-[:`PART_OF`]->())) = 0)\" + \") \" + \"AND NOT (\"\n\t\t\t\t+ \"(r.is_sandwich_training = true AND size(size((r)-[:`PART_OF`]->())) = 0)\" + \")\"\n\t\t\t\t+ \") RETURN DISTINCT r, o\");\n\t}\n\n\t@Test\n\tvoid gh185() {\n\t\tfinal Node r = Cypher.node(\"Resume\").named(\"r\");\n\t\tfinal Node u = Cypher.node(\"UserSearchable\").named(\"u\");\n\n\t\tStatement s = Cypher.match(r.relationshipFrom(u, \"HAS\"))\n\t\t\t.where(Cypher.not(Cypher.exists(r.relationshipTo(u, \"EXCLUDES\"))))\n\t\t\t.returningDistinct(r)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(s)).isEqualTo(\n\t\t\t\t\"MATCH (r:`Resume`)<-[:`HAS`]-(u:`UserSearchable`) WHERE NOT (exists((r)-[:`EXCLUDES`]->(u))) RETURN DISTINCT r\");\n\t}\n\n\t@Test\n\tvoid gh187() {\n\t\tfinal Node r = Cypher.node(\"Resume\").named(\"r\");\n\t\tfinal Node u = Cypher.node(\"User\").named(\"u\");\n\n\t\tStatement s = Cypher.match(r.relationshipFrom(u, \"HAS\"))\n\t\t\t.with(Cypher.head(Cypher.collect(r.getRequiredSymbolicName())).as(\"r\"))\n\t\t\t.returning(r)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(s))\n\t\t\t.isEqualTo(\"MATCH (r:`Resume`)<-[:`HAS`]-(u:`User`) WITH head(collect(r)) AS r RETURN r\");\n\t}\n\n\t@Test\n\tvoid gh188() {\n\t\tfinal Node r = Cypher.node(\"Resume\").named(\"r\");\n\t\tfinal Node u = Cypher.node(\"User\").named(\"u\");\n\n\t\tStatement s = Cypher.match(r.relationshipFrom(u, \"HAS\"))\n\t\t\t.returning(Cypher.countDistinct(r.getRequiredSymbolicName()).as(\"r\"))\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(s))\n\t\t\t.isEqualTo(\"MATCH (r:`Resume`)<-[:`HAS`]-(u:`User`) RETURN count(DISTINCT r) AS r\");\n\t}\n\n\t@Test\n\tvoid gh197() {\n\n\t\t// avg\n\t\tStatement s = Cypher.match(this.person).returning(Cypher.avg(this.person.property(\"age\"))).build();\n\t\tassertThat(cypherRenderer.render(s)).isEqualTo(\"MATCH (person:`Person`) RETURN avg(person.age)\");\n\n\t\t// max/min\n\t\tfinal ListExpression list = Cypher.listOf(Cypher.literalOf(1), Cypher.literalOf(\"a\"), Cypher.literalOf(null),\n\t\t\t\tCypher.literalOf(0.2), Cypher.literalOf(\"b\"), Cypher.literalOf(\"1\"), Cypher.literalOf(\"99\"));\n\t\ts = Cypher.unwind(list).as(\"val\").returning(Cypher.max(Cypher.name(\"val\"))).build();\n\t\tassertThat(cypherRenderer.render(s))\n\t\t\t.isEqualTo(\"UNWIND [1, 'a', NULL, 0.2, 'b', '1', '99'] AS val RETURN max(val)\");\n\t\ts = Cypher.unwind(list).as(\"val\").returning(Cypher.min(Cypher.name(\"val\"))).build();\n\t\tassertThat(cypherRenderer.render(s))\n\t\t\t.isEqualTo(\"UNWIND [1, 'a', NULL, 0.2, 'b', '1', '99'] AS val RETURN min(val)\");\n\n\t\t// percentileCont/percentileDisc\n\t\ts = Cypher.match(this.person).returning(Cypher.percentileCont(this.person.property(\"age\"), 0.4)).build();\n\t\tassertThat(cypherRenderer.render(s))\n\t\t\t.isEqualTo(\"MATCH (person:`Person`) RETURN percentileCont(person.age, 0.4)\");\n\t\ts = Cypher.match(this.person).returning(Cypher.percentileDisc(this.person.property(\"age\"), 0.5)).build();\n\t\tassertThat(cypherRenderer.render(s))\n\t\t\t.isEqualTo(\"MATCH (person:`Person`) RETURN percentileDisc(person.age, 0.5)\");\n\n\t\t// stDev/stDevP\n\t\ts = Cypher.match(this.person)\n\t\t\t.where(this.person.property(\"name\")\n\t\t\t\t.in(Cypher.listOf(Cypher.literalOf(\"A\"), Cypher.literalOf(\"B\"), Cypher.literalOf(\"C\"))))\n\t\t\t.returning(Cypher.stDev(this.person.property(\"age\")))\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(s))\n\t\t\t.isEqualTo(\"MATCH (person:`Person`) WHERE person.name IN ['A', 'B', 'C'] RETURN stDev(person.age)\");\n\t\ts = Cypher.match(this.person)\n\t\t\t.where(this.person.property(\"name\")\n\t\t\t\t.in(Cypher.listOf(Cypher.literalOf(\"A\"), Cypher.literalOf(\"B\"), Cypher.literalOf(\"C\"))))\n\t\t\t.returning(Cypher.stDevP(this.person.property(\"age\")))\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(s))\n\t\t\t.isEqualTo(\"MATCH (person:`Person`) WHERE person.name IN ['A', 'B', 'C'] RETURN stDevP(person.age)\");\n\n\t\t// sum\n\t\ts = Cypher.match(this.person)\n\t\t\t.with(Cypher.listOf(Cypher.mapOf(\"type\", this.person.getRequiredSymbolicName(), \"nb\",\n\t\t\t\t\tCypher.sum(this.person.getRequiredSymbolicName())))\n\t\t\t\t.as(\"counts\"))\n\t\t\t.returning(Cypher.sum(this.person.property(\"age\")))\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(s)).isEqualTo(\n\t\t\t\t\"MATCH (person:`Person`) WITH [{type: person, nb: sum(person)}] AS counts RETURN sum(person.age)\");\n\t}\n\n\t@Test\n\tvoid gh200() {\n\t\tfinal Node r = Cypher.node(\"Resume\").named(\"r\");\n\n\t\tStatement s = Cypher.match(r)\n\t\t\t.with(r.getRequiredSymbolicName())\n\t\t\t.returningDistinct(r.getRequiredSymbolicName())\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(s)).isEqualTo(\"MATCH (r:`Resume`) WITH r RETURN DISTINCT r\");\n\t}\n\n\t@Test\n\tvoid gh204() {\n\t\tfinal Node a = Cypher.node(\"A\").named(\"a\");\n\t\tfinal Node b = Cypher.node(\"B\").named(\"b\");\n\t\tfinal Node c = Cypher.node(\"C\").named(\"c\");\n\n\t\tStatement s = Cypher.match(a.relationshipTo(b).relationshipTo(c).max(2)).returning(a).build();\n\n\t\tassertThat(cypherRenderer.render(s)).isEqualTo(\"MATCH (a:`A`)-->(b:`B`)-[*..2]->(c:`C`) RETURN a\");\n\t}\n\n\t@Test\n\tvoid gh245() {\n\t\tString expected = \"MATCH (person:`Person`) RETURN person{alias: person.name}\";\n\n\t\tStatement statement;\n\t\tstatement = Cypher.match(this.person)\n\t\t\t.returning(this.person.project(\"alias\", this.person.property(\"name\")))\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\tstatement = Cypher.match(this.person)\n\t\t\t.returning(this.person.project(this.person.property(\"name\").as(\"alias\")))\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t}\n\n\t@Test\n\tvoid gh44() {\n\n\t\tNode n = Cypher.anyNode(\"n\");\n\t\tStatement statement = Cypher.match(n).returning(Cypher.collectDistinct(n).as(\"distinctNodes\")).build();\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (n) RETURN collect(DISTINCT n) AS distinctNodes\");\n\t}\n\n\t@Test\n\tvoid gh84() {\n\n\t\tNode parent = Cypher.node(\"Parent\").named(\"parent\");\n\t\tNode child = Cypher.node(\"Child\").named(\"child\");\n\t\tStatement statement = Cypher.call(\"apoc.create.relationship\")\n\t\t\t.withArgs(parent.getRequiredSymbolicName(), Cypher.literalOf(\"ChildEdge\"),\n\t\t\t\t\tCypher.mapOf(\"score\", Cypher.literalOf(0.33), \"weight\", Cypher.literalOf(1.7)),\n\t\t\t\t\tchild.getRequiredSymbolicName())\n\t\t\t.yield(\"rel\")\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"CALL apoc.create.relationship(parent, 'ChildEdge', {score: 0.33, weight: 1.7}, child) YIELD rel\");\n\n\t}\n\n\t@Test // GH-106\n\tvoid aliasesShouldBeEscapedIfNecessary() {\n\n\t\tAliasedExpression alias = Cypher.name(\"n\").as(\"das ist ein Alias\");\n\t\tStatement statement = Cypher.match(Cypher.anyNode().named(\"n\")).with(alias).returning(alias).build();\n\n\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t.isEqualTo(\"MATCH (n) WITH n AS `das ist ein Alias` RETURN `das ist ein Alias`\");\n\t}\n\n\t@Test // GH-106\n\tvoid projectedPropertiesShouldBeEscapedIfNecessary() {\n\n\t\tNode node = Cypher.anyNode().named(\"n\");\n\t\tStatement statement = Cypher.match(node).returning(node.project(\"property 1\", \"property 2\")).build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (n) RETURN n{.`property 1`, .`property 2`}\");\n\t}\n\n\t@Test // GH-106\n\tvoid mapKeysShouldBeEscapedIfNecessary() {\n\n\t\tStatement statement = Cypher\n\t\t\t.returning(Cypher.mapOf(\"key 1\", Cypher.literalTrue(), \"key 2\", Cypher.literalFalse()))\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN {`key 1`: true, `key 2`: false}\");\n\t}\n\n\t@Test // GH-121\n\tvoid aliasOnWrongPosition() {\n\n\t\tSymbolicName u = Cypher.name(\"u\");\n\t\tSymbolicName rn = Cypher.name(\"rn\");\n\t\tSymbolicName nn = Cypher.name(\"nn\");\n\n\t\tNode rnNode = Cypher.node(\"SomeLabel\").named(rn);\n\t\tvar rnAliasedAsNN = rnNode.as(\"nn\");\n\t\tStatement statement = Cypher.match(Cypher.node(\"User\").named(u), rnNode, Cypher.node(\"SomeLabel\").named(nn))\n\t\t\t.withDistinct(u, rn, rnAliasedAsNN)\n\t\t\t.returning(u, rn, rnAliasedAsNN)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"MATCH (u:`User`), (rn:`SomeLabel`), (nn:`SomeLabel`) WITH DISTINCT u, rn, rn AS nn RETURN u, rn, nn\");\n\t}\n\n\t@Test // GH-123\n\tvoid propertiesOfFunctions() {\n\n\t\tStatement statement = Cypher.returning(Cypher.property(Cypher.datetime(), \"epochSeconds\")).build();\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN datetime().epochSeconds\");\n\t}\n\n\t@Test // GH-123\n\tvoid propertiesOfFunctionsInsideQuery() {\n\n\t\tvar collectedThings = Cypher.collect(Cypher.name(\"n\")).as(\"collectedThings\");\n\t\tStatement statement = Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t.with(collectedThings)\n\t\t\t.returning(Cypher.property(Cypher.last(collectedThings), \"name\"))\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t.isEqualTo(\"MATCH (n) WITH collect(n) AS collectedThings RETURN last(collectedThings).name\");\n\t}\n\n\t@Test\n\tvoid gh127() {\n\n\t\tSymbolicName key = Cypher.name(\"key\");\n\t\tString dynamicPrefix = \"properties.\";\n\t\tStatement statement = Cypher.match(this.person)\n\t\t\t.returning(this.person.project(\"json\",\n\t\t\t\t\tCypher.call(\"apoc.map.fromPairs\")\n\t\t\t\t\t\t.withArgs(Cypher.listWith(key)\n\t\t\t\t\t\t\t.in(Cypher.call(\"keys\").withArgs(this.person.getRequiredSymbolicName()).asFunction())\n\t\t\t\t\t\t\t.where(key.startsWith(Cypher.literalOf(dynamicPrefix)))\n\t\t\t\t\t\t\t.returning(Cypher.call(\"substring\")\n\t\t\t\t\t\t\t\t.withArgs(key, Cypher.literalOf(dynamicPrefix.length()))\n\t\t\t\t\t\t\t\t.asFunction(), this.person.property(key)))\n\t\t\t\t\t\t.asFunction()))\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (person:`Person`) \" + \"RETURN person{\"\n\t\t\t\t+ \"json: apoc.map.fromPairs([key IN keys(person) WHERE key STARTS WITH 'properties.' | [substring(key, 11), \"\n\t\t\t\t+ \"person[key]]])\" + \"}\");\n\n\t}\n\n\t@Test // GH-133\n\tvoid allowSymbolicNamesAsCondition() {\n\n\t\tNode company = Cypher.node(\"Company\").named(\"company\");\n\t\tSymbolicName cond = Cypher.name(\"cond\");\n\t\tStatementBuilder.OngoingReadingAndReturn cypher = Cypher.match(company)\n\t\t\t.where(Cypher.any(cond)\n\t\t\t\t.in(Cypher.listBasedOn(company.relationshipTo(this.person, \"WORKS_AT\"))\n\t\t\t\t\t.returning(this.person.property(\"name\").isEqualTo(Cypher.parameter(\"name\"))))\n\t\t\t\t.where(cond.asCondition()))\n\t\t\t.returning(company);\n\n\t\tassertThat(cypherRenderer.render(cypher.build())).isEqualTo(\n\t\t\t\t\"MATCH (company:`Company`) WHERE any(cond IN [(company)-[:`WORKS_AT`]->(person:`Person`) | person.name = $name] WHERE cond) RETURN company\");\n\t}\n\n\t@Test // GH-131\n\tvoid projectSymbolicNames() {\n\n\t\tNode user = Cypher.node(\"User\").named(\"user\");\n\t\tNode userKnows = Cypher.node(\"User\").named(\"userKnows\");\n\t\tSymbolicName sortedElement = Cypher.name(\"sortedElement\");\n\n\t\tPatternComprehension innerPatternComprehension = Cypher.listBasedOn(user.relationshipTo(userKnows, \"KNOWS\"))\n\t\t\t.returning(userKnows.project(\"born\", userKnows.property(\"born\")));\n\t\tStatement statement = Cypher.match(user)\n\t\t\t.returning(user.project(\"knows\", Cypher.listWith(sortedElement)\n\t\t\t\t.in(innerPatternComprehension)\n\t\t\t\t.returning(sortedElement.project(\"born\", Cypher.mapOf(\"formatted\",\n\t\t\t\t\t\tCypher.call(\"toString\").withArgs(Cypher.property(sortedElement, \"born\")).asFunction())))))\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"MATCH (user:`User`) RETURN user{knows: [sortedElement IN [(user)-[:`KNOWS`]->(userKnows:`User`) | userKnows{born: userKnows.born}] | sortedElement{born: {formatted: toString(sortedElement.born)}}]}\");\n\t}\n\n\t@Test // GH-128\n\tvoid relationshipPatternsAsCondition() {\n\n\t\tStatement statement = Cypher.match(this.person)\n\t\t\t.where(this.person.relationshipTo(Cypher.anyNode(), \"A\")\n\t\t\t\t.asCondition()\n\t\t\t\t.or(this.person.relationshipTo(Cypher.anyNode(), \"B\")))\n\t\t\t.and(this.person.relationshipTo(Cypher.anyNode(), \"C\")\n\t\t\t\t.asCondition()\n\t\t\t\t.or(this.person.relationshipTo(Cypher.anyNode(), \"D\")\n\t\t\t\t\t.asCondition()\n\t\t\t\t\t.and(this.person.relationshipTo(Cypher.anyNode(), \"E\")))\n\t\t\t\t.or(this.person.relationshipTo(Cypher.anyNode(), \"F\")))\n\t\t\t.returning(this.person)\n\t\t\t.build();\n\n\t\tString expected = (\"\" + \"MATCH (person:`Person`) WHERE (\" + \"  (\"\n\t\t\t\t+ \"      (person)-[:`A`]->() OR (person)-[:`B`]->()\" + \"  ) AND (\" + \"      (\"\n\t\t\t\t+ \"          (person)-[:`C`]->() OR (\" + \"              (person)-[:`D`]->() AND (person)-[:`E`]->()\"\n\t\t\t\t+ \"          )\" + \"      ) OR (person)-[:`F`]->())\" + \") RETURN person\")\n\t\t\t.replaceAll(\"\\\\s{2,}\", \"\");\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\t}\n\n\t@Test // GH-142\n\tvoid pointShouldAcceptExpressionToo() {\n\n\t\tParameter<?> location = Cypher.parameter(\"location\");\n\t\tProperty distance = Cypher.property(location, \"distance\");\n\n\t\tExpression point = Cypher.point(Cypher.property(location, \"point\"));\n\n\t\tStatement statement = Cypher.match(this.person)\n\t\t\t.where(Cypher.distance(this.person.property(\"location\"), point).isEqualTo(distance))\n\t\t\t.returning(this.person)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"MATCH (person:`Person`) WHERE point.distance(person.location, point($location.point)) = $location.distance RETURN person\");\n\t}\n\n\t@Test // GH-141\n\tvoid propertiesShouldBeExtractableFromExpressions() {\n\n\t\tParameter<?> location = Cypher.parameter(\"location\");\n\n\t\tExpression point = Cypher.call(\"point\").withArgs(location.property(\"point\")).asFunction();\n\t\tProperty distance = Cypher.property(location, \"distance\");\n\n\t\tStatement statement = Cypher.match(this.person)\n\t\t\t.where(Cypher.distance(this.person.property(\"location\"), point).isEqualTo(distance))\n\t\t\t.returning(this.person)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"MATCH (person:`Person`) WHERE point.distance(person.location, point($location.point)) = $location.distance RETURN person\");\n\t}\n\n\t@Test\n\tvoid removeAllPropertiesShouldWork() {\n\n\t\tNode n = Cypher.node(\"DeleteMe\").named(\"n\");\n\t\tString cypher = Cypher.match(n)\n\t\t\t.set(n, Cypher.mapOf())\n\t\t\t.set(n.property(\"newProperty\").to(Cypher.literalOf(\"aValue\")))\n\t\t\t.returning(n)\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (n:`DeleteMe`) SET n = {} SET n.newProperty = 'aValue' RETURN n\");\n\t}\n\n\t@Test // GH-168\n\tvoid containersMustBeMutatableByProperties() {\n\n\t\tNode nodeA = Cypher.node(\"Target\").named(\"t\");\n\t\tNode nodeB = Cypher.node(\"Source\").named(\"s\");\n\t\tString cypher = Cypher.match(nodeA, nodeB).mutate(nodeA, nodeB.property(\"whatever\")).build().getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (t:`Target`), (s:`Source`) SET t += s.whatever\");\n\t}\n\n\t@ParameterizedTest // GH-152\n\t@MethodSource(\"relpatternChainingArgs\")\n\tvoid relpatternChaining(boolean multihops, int length, boolean backward, String expected) {\n\n\t\tNode start = Cypher.anyNode(\"s\");\n\t\tNode end = Cypher.anyNode(\"e\");\n\n\t\tPatternElement result;\n\t\tif (multihops) {\n\t\t\tRelationshipChain leadsTo;\n\t\t\tleadsTo = start.relationshipTo(Cypher.node(\"Resume\"), \"PART_OF\")\n\t\t\t\t.length(0, 1)\n\t\t\t\t.relationshipTo(Cypher.node(\"Resume\"), \"IS_PARALLEL\")\n\t\t\t\t.length(0, 1);\n\n\t\t\tif (backward) {\n\t\t\t\tleadsTo = leadsTo.relationshipFrom(end, \"LEADS_TO\").named(\"l\");\n\t\t\t}\n\t\t\telse {\n\t\t\t\tleadsTo = leadsTo.relationshipTo(end, \"LEADS_TO\").named(\"l\");\n\t\t\t}\n\t\t\tif (length > 1) {\n\t\t\t\tleadsTo = leadsTo.length(length, length);\n\t\t\t}\n\t\t\tresult = leadsTo;\n\t\t}\n\t\telse {\n\t\t\tRelationship leadsTo;\n\n\t\t\tif (backward) {\n\t\t\t\tleadsTo = start.relationshipFrom(end, \"LEADS_TO\").named(\"l\");\n\t\t\t}\n\t\t\telse {\n\t\t\t\tleadsTo = start.relationshipTo(end, \"LEADS_TO\").named(\"l\");\n\t\t\t}\n\t\t\tif (length > 1) {\n\t\t\t\tleadsTo = leadsTo.length(length, length);\n\t\t\t}\n\t\t\tresult = leadsTo;\n\t\t}\n\t\tString cypher = Cypher.match(result).returning(\"s\", \"l\", \"e\").build().getCypher();\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@Test // GH-187\n\tvoid returningRawShouldWork() {\n\n\t\tString userProvidedCypher = \"MATCH (this)-[:LINK]-(o:Other) RETURN o\";\n\t\tNode node = Cypher.node(\"Node\").named(\"node\");\n\t\tSymbolicName result = Cypher.name(\"result\");\n\t\tStatement statement = Cypher.match(node)\n\t\t\t.call(Cypher.with(node)\n\t\t\t\t// https://neo4j.com/docs/cypher-manual/current/clauses/call-subquery/#subquery-correlated-importing\n\t\t\t\t// > Aliasing or expressions are not supported in importing WITH clauses -\n\t\t\t\t// e.g. WITH a AS b or WITH a+1 AS b.\n\t\t\t\t.with(node.as(\"this\"))\n\t\t\t\t.returningRaw(Cypher.raw(userProvidedCypher).as(result))\n\t\t\t\t.build())\n\t\t\t.returning(result.project(\"foo\", \"bar\"))\n\t\t\t.build();\n\n\t\tString cypher = Renderer.getRenderer(Configuration.prettyPrinting()).render(statement);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tMATCH (node:Node)\n\t\t\t\tCALL (node) {\n\t\t\t\t  WITH node AS this\n\t\t\t\t  MATCH (this)-[:LINK]-(o:Other) RETURN o AS result\n\t\t\t\t}\n\t\t\t\tRETURN result {\n\t\t\t\t  .foo,\n\t\t\t\t  .bar\n\t\t\t\t}\"\"\");\n\t}\n\n\t@Test\n\tvoid veryRawCallShouldWork() {\n\n\t\tSymbolicName msg = Cypher.name(\"message\");\n\t\tString statement = Cypher.unwind(Cypher.parameter(\"events\"))\n\t\t\t.as(msg)\n\t\t\t.with(msg.property(\"value\").as(\"event\"), msg.property(\"header\").as(\"header\"), msg.property(\"key\").as(\"key\"),\n\t\t\t\t\tmsg.property(\"value\").as(\"value\"))\n\t\t\t.callRawCypher(\"WITH key, value CREATE (e:Event {key: key, value: value})\")\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(statement).isEqualTo(\n\t\t\t\t\"UNWIND $events AS message WITH message.value AS event, message.header AS header, message.key AS key, message.value AS value CALL (*) {WITH key, value CREATE (e:Event {key: key, value: value})}\");\n\t}\n\n\t@Test // GH-190\n\tvoid mixedWithShouldMakeSense() {\n\n\t\tNode node = Cypher.node(\"Node\").named(\"node\");\n\t\tExpression someExpression = Cypher.literalFalse();\n\n\t\tProperty ll = node.property(\"ll\");\n\t\tProperty l = node.property(\"l\");\n\n\t\tAliasedExpression aCase = Cypher.caseExpression().when(ll.isNull()).then(l).elseDefault(ll).as(\"l\");\n\n\t\tString cypher = Cypher.match(node)\n\t\t\t.with(node, someExpression.as(\"f\"), aCase)\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (node:`Node`) WITH node, false AS f, CASE WHEN node.ll IS NULL THEN node.l ELSE node.ll END AS l RETURN *\");\n\t}\n\n\t@Test // GH-190\n\tvoid withAliasOnTopLevel() {\n\n\t\tString cypher = Cypher.with(Cypher.literalFalse().as(\"f\")).returning(Cypher.asterisk()).build().getCypher();\n\t\tassertThat(cypher).isEqualTo(\"WITH false AS f RETURN *\");\n\t}\n\n\t@Test // GH-190\n\tvoid mixedWithDistinctShouldMakeSense() {\n\n\t\tNode node = Cypher.node(\"Node\").named(\"node\");\n\t\tExpression someExpression = Cypher.literalFalse();\n\n\t\tProperty ll = node.property(\"ll\");\n\t\tProperty l = node.property(\"l\");\n\n\t\tAliasedExpression aCase = Cypher.caseExpression().when(ll.isNull()).then(l).elseDefault(ll).as(\"l\");\n\n\t\tString cypher = Cypher.match(node)\n\t\t\t.withDistinct(node, someExpression.as(\"f\"), aCase)\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (node:`Node`) WITH DISTINCT node, false AS f, CASE WHEN node.ll IS NULL THEN node.l ELSE node.ll END AS l RETURN *\");\n\t}\n\n\t@Test // GH-190\n\tvoid heterogenAliasWithDistinctShouldMakeSense() {\n\n\t\tNode node = Cypher.node(\"Node\").named(\"node\");\n\t\tExpression someExpression = Cypher.literalFalse();\n\n\t\tString cypher = Cypher.match(node)\n\t\t\t.withDistinct(someExpression.as(\"f\"), Cypher.date().as(\"aDate\"))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (node:`Node`) WITH DISTINCT false AS f, date() AS aDate RETURN *\");\n\t}\n\n\t@Test // GH-190\n\tvoid symbolicNameAndAlias() {\n\n\t\tNode node = Cypher.node(\"Node\").named(\"node\");\n\t\tExpression someExpression = Cypher.literalFalse();\n\n\t\tString cypher = Cypher.match(node)\n\t\t\t.with(Cypher.name(\"n\"), someExpression.as(\"f\"), Cypher.date().as(\"aDate\"))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (node:`Node`) WITH n, false AS f, date() AS aDate RETURN *\");\n\t}\n\n\t@Test // GH-192\n\tvoid patternExpressionsAreNotAllowedToIntroduceNewVariables() {\n\n\t\tNode bike = Cypher.node(\"Bike\").named(\"b\");\n\t\tNode owner = Cypher.node(\"Person\").named(\"o\");\n\t\tRelationship owns = owner.relationshipTo(bike, \"OWNS\").named(\"r\");\n\t\tProperty p = owns.property(\"x\");\n\n\t\tStatement statement = Cypher.match(bike)\n\t\t\t.where(owns.asCondition())\n\t\t\t.with(bike)\n\t\t\t.match(owns)\n\t\t\t.returning(bike.property(\"f\"), p)\n\t\t\t.build();\n\t\tassertThat(statement.getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (b:`Bike`) WHERE (:`Person`)-[:`OWNS`]->(b) WITH b MATCH (o:`Person`)-[r:`OWNS`]->(b) RETURN b.f, r.x\");\n\n\t\tstatement = Cypher.match(owns).where(owns.asCondition()).returning(owns).build();\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(\"MATCH (o:`Person`)-[r:`OWNS`]->(b:`Bike`) WHERE (o)-[r]->(b) RETURN r\");\n\t}\n\n\t@Test // GH-193\n\tvoid matchAfterYieldShouldWorkStandalone() {\n\n\t\tNode g = Cypher.node(\"Group\").named(\"g\");\n\t\tNode a = Cypher.node(\"Asset\").named(\"a\");\n\t\tNode d = Cypher.node(\"Device\").named(\"d\");\n\t\tSymbolicName node = Cypher.name(\"node\");\n\t\tString cypher = Cypher.call(\"db.index.fulltext.queryNodes\")\n\t\t\t.withArgs(Cypher.literalOf(\"livesearch\"), Cypher.literalOf(\"*a*\"))\n\t\t\t.yield(node)\n\t\t\t.match(g.relationshipTo(a, \"GROUPS\")\n\t\t\t\t.relationshipFrom(Cypher.node(\"Deploy\"), \"ON\")\n\t\t\t\t.relationshipFrom(d, \"SCHEDULED\"))\n\t\t\t.where(a.property(\"asset_id\").isEqualTo(Cypher.property(node, \"asset_id\")))\n\t\t\t.withDistinct(Cypher.collect(d.project(d.property(\"sigfox_id\"), a)).as(\"assetdata\"))\n\t\t\t.returning(\"assetdata\")\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"CALL db.index.fulltext.queryNodes('livesearch', '*a*') \" + \"YIELD node \"\n\t\t\t\t+ \"MATCH (g:`Group`)-[:`GROUPS`]->(a:`Asset`)<-[:`ON`]-(:`Deploy`)<-[:`SCHEDULED`]-(d:`Device`) \"\n\t\t\t\t+ \"WHERE a.asset_id = node.asset_id \"\n\t\t\t\t+ \"WITH DISTINCT collect(d{.sigfox_id, a}) AS assetdata RETURN assetdata\");\n\t}\n\n\t@Test // GH-193\n\tvoid matchAfterYieldShouldWorkInQuery() {\n\n\t\tNode g = Cypher.node(\"Group\").named(\"g\");\n\t\tNode a = Cypher.node(\"Asset\").named(\"a\");\n\t\tNode d = Cypher.node(\"Device\").named(\"d\");\n\t\tSymbolicName node = Cypher.name(\"node\");\n\t\tSymbolicName nameOfIndex = Cypher.name(\"nameOfIndex\");\n\t\tString cypher = Cypher.with(Cypher.parameter(\"p\").as(nameOfIndex))\n\t\t\t.call(\"db.index.fulltext.queryNodes\")\n\t\t\t.withArgs(nameOfIndex, Cypher.literalOf(\"*a*\"))\n\t\t\t.yield(node)\n\t\t\t.match(g.relationshipTo(a, \"GROUPS\")\n\t\t\t\t.relationshipFrom(Cypher.node(\"Deploy\"), \"ON\")\n\t\t\t\t.relationshipFrom(d, \"SCHEDULED\"))\n\t\t\t.where(a.property(\"asset_id\").isEqualTo(Cypher.property(node, \"asset_id\")))\n\t\t\t.withDistinct(Cypher.collect(d.project(d.property(\"sigfox_id\"), a)).as(\"assetdata\"))\n\t\t\t.returning(\"assetdata\")\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher)\n\t\t\t.isEqualTo(\"WITH $p AS nameOfIndex CALL db.index.fulltext.queryNodes(nameOfIndex, '*a*') \" + \"YIELD node \"\n\t\t\t\t\t+ \"MATCH (g:`Group`)-[:`GROUPS`]->(a:`Asset`)<-[:`ON`]-(:`Deploy`)<-[:`SCHEDULED`]-(d:`Device`) \"\n\t\t\t\t\t+ \"WHERE a.asset_id = node.asset_id \"\n\t\t\t\t\t+ \"WITH DISTINCT collect(d{.sigfox_id, a}) AS assetdata RETURN assetdata\");\n\t}\n\n\t@Test // GH-189\n\tvoid propertyForExpressionWithCollectionOfNames() {\n\n\t\tNode node = Cypher.node(\"Node\").named(\"n\");\n\n\t\tString cypher = Cypher.match(node)\n\t\t\t.returning(Cypher.property(node.getRequiredSymbolicName(), Collections.singleton(\"name\")))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (n:`Node`) RETURN n.name\");\n\t}\n\n\t@Test // GH-189\n\tvoid exposesWithBasedOnExpressionCollectionOnNext() {\n\n\t\tNode node = Cypher.node(\"Node\").named(\"n\");\n\n\t\tString cypher = Cypher.match(node)\n\t\t\t.with(Collections.singleton(node.getRequiredSymbolicName())) // DefaultStatementBuilder\n\t\t\t.with(Collections.singleton(node.getRequiredSymbolicName())) // DefaultStatementWithWithBuilder\n\t\t\t.call(\"my.procedure\")\n\t\t\t.yield(\"x\")\n\t\t\t.with(Collections.singleton(node.getRequiredSymbolicName())) // InQueryCallBuilder\n\t\t\t.returning(node)\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\"MATCH (n:`Node`) WITH n WITH n CALL my.procedure() YIELD x WITH n RETURN n\");\n\t}\n\n\t@Test // GH-189\n\tvoid exposesWithDistinctBasedOnExpressionCollectionOnNext() {\n\n\t\tNode node = Cypher.node(\"Node\").named(\"n\");\n\n\t\tString cypher = Cypher.match(node)\n\t\t\t.withDistinct(Collections.singleton(node.getRequiredSymbolicName())) // DefaultStatementBuilder\n\t\t\t.withDistinct(Collections.singleton(node.getRequiredSymbolicName())) // DefaultStatementWithWithBuilder\n\t\t\t.call(\"my.procedure\")\n\t\t\t.yield(\"x\")\n\t\t\t.withDistinct(Collections.singleton(node.getRequiredSymbolicName())) // InQueryCallBuilder\n\t\t\t.returning(node)\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (n:`Node`) WITH DISTINCT n WITH DISTINCT n CALL my.procedure() YIELD x WITH DISTINCT n RETURN n\");\n\t}\n\n\t@Test // GH-197\n\tvoid symbolicNamesInNotConditionsMustNotBeResolvedWhenConditionIsARelationshipPatternV1() {\n\n\t\tNode node = Cypher.node(\"Division\").named(\"node\");\n\t\tStatement q = Cypher.match(node)\n\t\t\t.withDistinct(node)\n\t\t\t.where(Cypher.not(Cypher.anyNode(node.getRequiredSymbolicName())\n\t\t\t\t.relationshipTo(Cypher.node(\"Department\"), \"IN\")\n\t\t\t\t.relationshipTo(Cypher.node(\"Department\"), \"INSIDE\")\n\t\t\t\t.properties(\"rel_property\", Cypher.literalTrue())\n\t\t\t\t.relationshipTo(Cypher.node(\"Employee\"), \"EMPLOYS\")))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build();\n\n\t\tassertThat(Renderer.getRenderer(Configuration.newConfig().build()).render(q)).isEqualTo(\n\t\t\t\t\"MATCH (node:`Division`) WITH DISTINCT node WHERE NOT (node)-[:`IN`]->(:`Department`)-[:`INSIDE` {rel_property: true}]->(:`Department`)-[:`EMPLOYS`]->(:`Employee`) RETURN *\");\n\n\t\tassertThat(Renderer.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).build()).render(q))\n\t\t\t.isEqualTo(\n\t\t\t\t\t\"MATCH (node:Division) WITH DISTINCT node WHERE NOT (node)-[:IN]->(:Department)-[:INSIDE {rel_property: true}]->(:Department)-[:EMPLOYS]->(:Employee) RETURN *\");\n\n\t\tassertThat(Renderer.getRenderer(Configuration.prettyPrinting()).render(q)).isEqualTo(\"\"\"\n\t\t\t\tMATCH (node:Division)\n\t\t\t\tWITH DISTINCT node\n\t\t\t\tWHERE NOT (node)-[:IN]->(:Department)-[:INSIDE {\n\t\t\t\t  rel_property: true\n\t\t\t\t}]->(:Department)-[:EMPLOYS]->(:Employee)\n\t\t\t\tRETURN *\"\"\");\n\t}\n\n\t@Test // GH-197\n\tvoid symbolicNamesInNotConditionsMustNotBeResolvedWhenConditionIsARelationshipPatternV2() {\n\n\t\tNode node = Cypher.node(\"Division\").named(\"node\");\n\t\tStatement q = Cypher.match(node)\n\t\t\t.withDistinct(node)\n\t\t\t.where(Cypher.not(node.relationshipTo(Cypher.node(\"Department\"), \"IN\")\n\t\t\t\t.relationshipTo(Cypher.node(\"Department\"), \"INSIDE\")\n\t\t\t\t.properties(\"rel_property\", Cypher.literalTrue())\n\t\t\t\t.relationshipTo(Cypher.node(\"Employee\"), \"EMPLOYS\")))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build();\n\n\t\tassertThat(Renderer.getRenderer(Configuration.newConfig().build()).render(q)).isEqualTo(\n\t\t\t\t\"MATCH (node:`Division`) WITH DISTINCT node WHERE NOT (node)-[:`IN`]->(:`Department`)-[:`INSIDE` {rel_property: true}]->(:`Department`)-[:`EMPLOYS`]->(:`Employee`) RETURN *\");\n\n\t\tassertThat(Renderer.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).build()).render(q))\n\t\t\t.isEqualTo(\n\t\t\t\t\t\"MATCH (node:Division) WITH DISTINCT node WHERE NOT (node)-[:IN]->(:Department)-[:INSIDE {rel_property: true}]->(:Department)-[:EMPLOYS]->(:Employee) RETURN *\");\n\n\t\tassertThat(Renderer.getRenderer(Configuration.prettyPrinting()).render(q)).isEqualTo(\"\"\"\n\t\t\t\tMATCH (node:Division)\n\t\t\t\tWITH DISTINCT node\n\t\t\t\tWHERE NOT (node)-[:IN]->(:Department)-[:INSIDE {\n\t\t\t\t  rel_property: true\n\t\t\t\t}]->(:Department)-[:EMPLOYS]->(:Employee)\n\t\t\t\tRETURN *\"\"\");\n\t}\n\n\t@Test // GH-197\n\tvoid symbolicNamesMustBeClearedAfterUnion() {\n\n\t\tNode actor = Cypher.node(\"Actor\").named(\"n\");\n\t\tNode movie = Cypher.node(\"Movie\").named(\"n\");\n\t\tStatement stmt = Cypher.unionAll(Cypher.match(actor).returning(actor.property(\"name\").as(\"name\")).build(),\n\t\t\t\tCypher.match(movie).returning(movie.property(\"title\").as(\"name\")).build());\n\t\tassertThat(stmt.getCypher())\n\t\t\t.isEqualTo(\"MATCH (n:`Actor`) RETURN n.name AS name UNION ALL MATCH (n:`Movie`) RETURN n.title AS name\");\n\t}\n\n\t@Test // GH-203\n\tvoid patternComprehensionMustBeScoped() {\n\t\tNode testNode = Cypher.node(\"Department\").named(\"d\");\n\t\tNode user = Cypher.node(\"User\").named(\"u\");\n\t\tStatement query = Cypher.match(testNode)\n\t\t\t.returning(testNode.project(Cypher.asterisk(), \"firstname\",\n\t\t\t\t\tCypher.listBasedOn(testNode.relationshipTo(user)).returning(user.property(\"firstname\")), \"lastname\",\n\t\t\t\t\tCypher.listBasedOn(testNode.relationshipTo(user)).returning(user.property(\"lastname\"))))\n\t\t\t.build();\n\n\t\tassertThat(query.getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (d:`Department`) RETURN d{.*, firstname: [(d)-->(u:`User`) | u.firstname], lastname: [(d)-->(u:`User`) | u.lastname]}\");\n\t}\n\n\t@Test // GH-319\n\tvoid communitySite20220304() {\n\n\t\tSymbolicName nodes = Cypher.name(\"nodes\");\n\t\tSymbolicName relations = Cypher.name(\"relations\");\n\t\tSymbolicName second_nodes = Cypher.name(\"second_nodes\");\n\t\tSymbolicName second_relations = Cypher.name(\"second_relations\");\n\n\t\tNamedPath first_path = Cypher.path(\"p\")\n\t\t\t.definedBy(Cypher.node(\"lookingType\").relationshipFrom(Cypher.anyNode(), \"specifiedRelation\"));\n\t\tNamedPath second_path = Cypher.path(\"second_p\")\n\t\t\t.definedBy(Cypher.anyNode(\"n\")\n\t\t\t\t.relationshipTo(Cypher.anyNode().named(second_nodes), \"otherRelation\")\n\t\t\t\t.named(second_relations));\n\n\t\tStatement inner = Cypher.unwind(nodes)\n\t\t\t.as(\"n\")\n\t\t\t.with(\"n\")\n\t\t\t.match(second_path)\n\t\t\t.returning(second_nodes, second_relations)\n\t\t\t.build();\n\n\t\tStatement completeStatement = Cypher.match(first_path)\n\t\t\t.with(Cypher.nodes(first_path).as(nodes), Cypher.relationships(first_path).as(relations))\n\t\t\t.call(inner, nodes)\n\t\t\t.returning(nodes, relations, Cypher.collect(second_nodes), Cypher.collect(second_relations))\n\t\t\t.build();\n\n\t\tRenderer renderer = Renderer.getRenderer(Configuration.prettyPrinting());\n\t\tString cypher = renderer.render(completeStatement);\n\t\tString expected = \"\"\"\n\t\t\t\tMATCH p = (:lookingType)<-[:specifiedRelation]-()\n\t\t\t\tWITH nodes(p) AS nodes, relationships(p) AS relations\n\t\t\t\tCALL (nodes) {\n\t\t\t\t  UNWIND nodes AS n\n\t\t\t\t  WITH n\n\t\t\t\t  MATCH second_p = (n)-[second_relations:otherRelation]->(second_nodes)\n\t\t\t\t  RETURN second_nodes, second_relations\n\t\t\t\t}\n\t\t\t\tRETURN nodes, relations, collect(second_nodes), collect(second_relations)\"\"\";\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@SuppressWarnings(\"removal\")\n\t@ParameterizedTest // GH-319\n\t@EnumSource(Dialect.class)\n\tvoid subqueryWithRename(Dialect dialect) {\n\n\t\tSymbolicName nodes = Cypher.name(\"nodes\");\n\t\tSymbolicName relations = Cypher.name(\"relations\");\n\n\t\tNamedPath first_path = Cypher.path(\"p\")\n\t\t\t.definedBy(Cypher.node(\"Target\").relationshipFrom(Cypher.anyNode(), \"REL\"));\n\n\t\tStatement completeStatement = Cypher.match(first_path)\n\t\t\t.with(Cypher.nodes(first_path).as(nodes), Cypher.relationships(first_path).as(relations))\n\t\t\t.call(Cypher.returning(Cypher.name(\"x\")).build(), nodes.as(\"x\"))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build();\n\n\t\tRenderer renderer = Renderer\n\t\t\t.getRenderer(Configuration.newConfig().withDialect(dialect).withPrettyPrint(true).build());\n\t\tString cypher = renderer.render(completeStatement);\n\t\tString expected = \"\"\"\n\t\t\t\tMATCH p = (:Target)<-[:REL]-()\n\t\t\t\tWITH nodes(p) AS nodes, relationships(p) AS relations\n\t\t\t\tCALL {\n\t\t\t\t  WITH nodes\n\t\t\t\t  WITH nodes AS x\n\t\t\t\t  RETURN x\n\t\t\t\t}\n\t\t\t\tRETURN *\"\"\";\n\n\t\tif (EnumSet.complementOf(EnumSet.of(Dialect.NEO4J_4, Dialect.NEO4J_5)).contains(dialect)) {\n\t\t\texpected = expected.replace(\"CALL {\", \"CALL (nodes) {\").replace(\"  WITH nodes\\n\", \"\");\n\t\t}\n\t\tif (EnumSet.of(Dialect.NEO4J_5_26, Dialect.NEO4J_5_CYPHER_5).contains(dialect)) {\n\t\t\texpected = \"CYPHER 5 \" + expected;\n\t\t}\n\t\telse if (EnumSet.of(Dialect.NEO4J_5_CYPHER_25).contains(dialect)) {\n\t\t\texpected = \"CYPHER 25 \" + expected;\n\t\t}\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@Test // GH-319\n\tvoid subqueryWithoutImport() {\n\n\t\tSymbolicName nodes = Cypher.name(\"nodes\");\n\t\tSymbolicName relations = Cypher.name(\"relations\");\n\n\t\tNamedPath first_path = Cypher.path(\"p\")\n\t\t\t.definedBy(Cypher.node(\"Target\").relationshipFrom(Cypher.anyNode(), \"REL\"));\n\n\t\tStatement completeStatement = Cypher.match(first_path)\n\t\t\t.with(Cypher.nodes(first_path).as(nodes), Cypher.relationships(first_path).as(relations))\n\t\t\t.call(Cypher.returning(Cypher.literalOf(1)).build())\n\t\t\t.returning(Cypher.literalTrue())\n\t\t\t.build();\n\n\t\tString cypher;\n\n\t\tcypher = Renderer.getRenderer(Configuration.prettyPrinting()).render(completeStatement);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tMATCH p = (:Target)<-[:REL]-()\n\t\t\t\tWITH nodes(p) AS nodes, relationships(p) AS relations\n\t\t\t\tCALL (*) {\n\t\t\t\t  RETURN 1\n\t\t\t\t}\n\t\t\t\tRETURN true\"\"\");\n\n\t\tcypher = Renderer.getRenderer(Configuration.prettyPrinting()).render(completeStatement);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tMATCH p = (:Target)<-[:REL]-()\n\t\t\t\tWITH nodes(p) AS nodes, relationships(p) AS relations\n\t\t\t\tCALL (*) {\n\t\t\t\t  RETURN 1\n\t\t\t\t}\n\t\t\t\tRETURN true\"\"\");\n\n\t\tcypher = Renderer\n\t\t\t.getRenderer(Configuration.newConfig().withPrettyPrint(true).withDialect(Dialect.NEO4J_4).build())\n\t\t\t.render(completeStatement);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tMATCH p = (:Target)<-[:REL]-()\n\t\t\t\tWITH nodes(p) AS nodes, relationships(p) AS relations\n\t\t\t\tCALL {\n\t\t\t\t  RETURN 1\n\t\t\t\t}\n\t\t\t\tRETURN true\"\"\");\n\n\t}\n\n\t@Test // GH-349\n\tvoid allowProcedureCallWithoutResult() {\n\t\tNode n = Cypher.anyNode(\"n\");\n\t\tResultStatement statement = Cypher.match(n)\n\t\t\t.call(\"apoc.util.validate\")\n\t\t\t.withArgs(Cypher.exists(n.property(\"foo\")).not(), Cypher.literalOf(\"Error\"), Cypher.listOf())\n\t\t\t.withoutResults()\n\t\t\t.returning(n)\n\t\t\t.build();\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(\"MATCH (n) CALL apoc.util.validate(n.foo IS NULL, 'Error', []) RETURN n\");\n\t}\n\n\t@Test // GH-349\n\tvoid allowProcedureCallWithoutResultAndArguments() {\n\t\tNode n = Cypher.anyNode(\"n\");\n\t\tResultStatement statement = Cypher.match(n).call(\"apoc.util.validate\").withoutResults().returning(n).build();\n\t\tassertThat(statement.getCypher()).isEqualTo(\"MATCH (n) CALL apoc.util.validate() RETURN n\");\n\t}\n\n\t@Test // GH-349\n\tvoid wildValidate() {\n\n\t\tStatement statement = createSomewhatComplexStatement();\n\t\tRenderer renderer = Renderer.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).build());\n\t\tassertThat(renderer.render(statement)).isEqualTo(\n\t\t\t\t\"CALL () {CREATE (this0:Movie) SET this0.title = $this0_title WITH this0 CALL (this0) {CALL apoc.util.validate(NOT (any(r IN ['admin'] WHERE any(rr IN $auth.roles WHERE r = rr))), '@neo4j/graphql/FORBIDDEN', [0]) MERGE (this0_genres_connectOrCreate0:Genre {name: $this0_genres_connectOrCreate0_node_name}) ON CREATE SET this0_genres_connectOrCreate0.name = $this0_genres_connectOrCreate0_on_create_name MERGE (this0)-[this0_relationship_this0_genres_connectOrCreate0:IN_GENRE]->(this0_genres_connectOrCreate0) RETURN count(*)} RETURN this0} RETURN [this0{.title}] AS data\");\n\t}\n\n\t@Test // GH-1193\n\tvoid addLabels() {\n\n\t\tNode user = Cypher.node(\"User\").named(\"n\");\n\t\tStatement statement = Cypher.match(user).set(Cypher.setLabel(user, \"Cool\", \"Person\")).returning(user).build();\n\t\tassertThat(statement.getCypher()).isEqualTo(\"MATCH (n:`User`) SET n:`Cool`:`Person` RETURN n\");\n\t}\n\n\t@Test // GH-1186\n\tvoid testMultiPatternElementExist() {\n\t\tfinal Node user = Cypher.node(\"user\").named(\"T1\");\n\t\tfinal Node dept = Cypher.node(\"dept\").named(\"T2\");\n\t\tfinal Node parentDept = Cypher.node(\"dept\").named(\"T3\");\n\t\tfinal Statement statement = Cypher.match(user)\n\t\t\t.where(Cypher\n\t\t\t\t.exists(List.of(user.relationshipTo(dept, \"dept_id\"), dept.relationshipTo(parentDept, \"parent_id\"))))\n\t\t\t.returning(user)\n\t\t\t.build();\n\t\tassertThat(statement.getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (T1:`user`) WHERE EXISTS { (T1)-[:`dept_id`]->(T2:`dept`), (T2)-[:`parent_id`]->(T3:`dept`) } RETURN T1\");\n\t}\n\n\t@Test // GH-362\n\tvoid nodeNeedsToBeRenderedTwiceWithPatternsInCondition() {\n\n\t\tNode n = Cypher.node(\"Node\").named(\"n\");\n\t\tNode p = Cypher.anyNode(\"p\");\n\t\tSymbolicName x = Cypher.name(\"x\");\n\t\tCondition cond1 = Cypher.none(p.getRequiredSymbolicName())\n\t\t\t.in(x)\n\t\t\t.where(p.relationshipTo(Cypher.anyNode(), \"Y\")\n\t\t\t\t.asCondition()\n\t\t\t\t.or(p.relationshipTo(Cypher.anyNode(), \"Z\").asCondition()));\n\t\tCondition cond2 = Cypher.any(p.getRequiredSymbolicName())\n\t\t\t.in(x)\n\t\t\t.where(p.property(\"bar\").eq(Cypher.literalTrue()));\n\t\tStatement s = Cypher.match(n)\n\t\t\t.with(Cypher.collect(n).as(x))\n\t\t\t.where(cond1.and(cond2))\n\t\t\t.returning(Cypher.count(n))\n\t\t\t.build();\n\t\tassertThat(s.getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (n:`Node`) WITH collect(n) AS x WHERE (none(p IN x WHERE ((p)-[:`Y`]->() OR (p)-[:`Z`]->())) AND any(p IN x WHERE p.bar = true)) RETURN count(n)\");\n\t}\n\n\t@Test // GH-350\n\tvoid compoundConditionShouldBeImmutableAsStatedInTheDocs() {\n\t\tNode n = Cypher.anyNode(\"n\");\n\t\tCondition a = org.neo4j.cypherdsl.core.Cypher.noCondition();\n\t\ta = a.and(n.property(\"b\").eq(Cypher.literalOf(1)));\n\t\tCondition temp = a;\n\t\ta = a.and(n.property(\"c\").eq(Cypher.literalOf(2)));\n\t\tResultStatement statement = Cypher.match(n).where(temp).returning(n).build();\n\t\tassertThat(statement.getCypher()).isEqualTo(\"MATCH (n) WHERE n.b = 1 RETURN n\");\n\t}\n\n\t@Test // GH-389\n\tvoid shouldRenderCorrectDateTimeCall() {\n\n\t\tExpression datetime = Cypher.datetime(toMap(ZonedDateTime.parse(\"2022-06-19T15:47:38.590917308Z[UTC]\")));\n\t\tassertThat(Cypher.returning(datetime).build().getCypher()).isEqualTo(\n\t\t\t\t\"RETURN datetime({year: 2022, month: 6, day: 19, hour: 15, minute: 47, second: 38, nanosecond: 590917308, timezone: 'UTC'})\");\n\t}\n\n\t@Test // GH-388\n\tvoid shouldRenderSetOpOnNodeWithMap() {\n\t\tNode node = Cypher.node(\"CordraObject\")\n\t\t\t.named(\"existingNode\")\n\t\t\t.withProperties(\"_id\", Cypher.literalOf(\"test/55de0539eb1e14f26a04\"));\n\n\t\tStatement statement = Cypher.merge(node)\n\t\t\t.set(node,\n\t\t\t\t\tCypher.mapOf(\"_id\", Cypher.literalOf(\"test/55de0539eb1e14f26a04\"), \"_type\",\n\t\t\t\t\t\t\tCypher.literalOf(\"Movie\"), \"title\", Cypher.literalOf(\"Top Gun\"), \"released\",\n\t\t\t\t\t\t\tCypher.literalOf(1986)))\n\t\t\t.returning(node)\n\t\t\t.build();\n\n\t\tassertThat(Renderer.getRenderer(Configuration.prettyPrinting()).render(statement)).isEqualTo(\"\"\"\n\t\t\t\tMERGE (existingNode:CordraObject {\n\t\t\t\t  _id: 'test/55de0539eb1e14f26a04'\n\t\t\t\t})\n\t\t\t\tSET existingNode = {\n\t\t\t\t  _id: 'test/55de0539eb1e14f26a04',\n\t\t\t\t  _type: 'Movie',\n\t\t\t\t  title: 'Top Gun',\n\t\t\t\t  released: 1986\n\t\t\t\t}\n\t\t\t\tRETURN existingNode\"\"\");\n\t}\n\n\t@Test // GH-388\n\tvoid shouldProvideSetOperations() {\n\t\tNode node = Cypher.node(\"CordraObject\")\n\t\t\t.named(\"existingNode\")\n\t\t\t.withProperties(\"_id\", Cypher.literalOf(\"test/55de0539eb1e14f26a04\"));\n\n\t\tOperation thisChangesEverything = node\n\t\t\t.set(Cypher.mapOf(\"_id\", Cypher.literalOf(\"test/55de0539eb1e14f26a04\"), \"_type\", Cypher.literalOf(\"Movie\"),\n\t\t\t\t\t\"title\", Cypher.literalOf(\"Top Gun\"), \"released\", Cypher.literalOf(1986)));\n\n\t\tStatement statement = Cypher.merge(node).set(thisChangesEverything).returning(node).build();\n\n\t\tassertThat(Renderer.getRenderer(Configuration.prettyPrinting()).render(statement)).isEqualTo(\"\"\"\n\t\t\t\tMERGE (existingNode:CordraObject {\n\t\t\t\t  _id: 'test/55de0539eb1e14f26a04'\n\t\t\t\t})\n\t\t\t\tSET existingNode = {\n\t\t\t\t  _id: 'test/55de0539eb1e14f26a04',\n\t\t\t\t  _type: 'Movie',\n\t\t\t\t  title: 'Top Gun',\n\t\t\t\t  released: 1986\n\t\t\t\t}\n\t\t\t\tRETURN existingNode\"\"\");\n\t}\n\n\t@Test // GH-388\n\tvoid shouldProvideSetOperationsForParameter() {\n\t\tNode node = Cypher.node(\"CordraObject\")\n\t\t\t.named(\"existingNode\")\n\t\t\t.withProperties(\"_id\", Cypher.literalOf(\"test/55de0539eb1e14f26a04\"));\n\n\t\tOperation thisChangesEverything = node.set(Cypher.parameter(\"aNewMap\"));\n\n\t\tStatement statement = Cypher.merge(node).set(thisChangesEverything).returning(node).build();\n\n\t\tassertThat(Renderer.getRenderer(Configuration.prettyPrinting()).render(statement)).isEqualTo(\"\"\"\n\t\t\t\tMERGE (existingNode:CordraObject {\n\t\t\t\t  _id: 'test/55de0539eb1e14f26a04'\n\t\t\t\t})\n\t\t\t\tSET existingNode = $aNewMap\n\t\t\t\tRETURN existingNode\"\"\");\n\t}\n\n\t@Test // GH-419\n\tvoid aliasedElementsShouldBeCarriedForwardWithWithToo() {\n\n\t\tNode objectInstanceNode = Cypher.node(\"ObjectInstance\").named(\"oi\");\n\t\tNode attributeTypeNode = Cypher.node(\"AttributeType\").named(\"att\");\n\t\tNode attributeNode = Cypher.node(\"Attribute\").named(\"at\");\n\t\tSymbolicName attributeTypeAndValue = Cypher.name(\"attributeTypeAndValue\");\n\t\tSymbolicName collection = Cypher.name(\"collection\");\n\n\t\tSymbolicName oi = objectInstanceNode.getRequiredSymbolicName();\n\t\tStatement statement = Cypher.match(objectInstanceNode)\n\t\t\t.with(Cypher.mapOf(oi.getValue(), oi).as(collection))\n\t\t\t.unwind(Cypher.parameter(\"attributes\"))\n\t\t\t.as(attributeTypeAndValue)\n\t\t\t.with(attributeTypeAndValue, collection)\n\t\t\t.match(attributeTypeNode.withProperties(\"name\", attributeTypeAndValue.property(\"name\"))\n\t\t\t\t.relationshipFrom(attributeNode, \"OF_TYPE\"))\n\t\t\t.with(attributeNode, collection.property(\"oi\").as(oi))\n\t\t\t.match(objectInstanceNode.relationshipTo(attributeNode, \"IS_IDENTIFIED_BY\"))\n\t\t\t.returning(attributeNode)\n\t\t\t.build();\n\n\t\tString cypher = Renderer\n\t\t\t.getRenderer(Configuration.newConfig().withPrettyPrint(true).alwaysEscapeNames(true).build())\n\t\t\t.render(statement);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tMATCH (oi:`ObjectInstance`)\n\t\t\t\tWITH {\n\t\t\t\t  oi: oi\n\t\t\t\t} AS collection\n\t\t\t\tUNWIND $attributes AS attributeTypeAndValue\n\t\t\t\tWITH attributeTypeAndValue, collection\n\t\t\t\tMATCH (att:`AttributeType` {\n\t\t\t\t  name: attributeTypeAndValue.name\n\t\t\t\t})<-[:`OF_TYPE`]-(at:`Attribute`)\n\t\t\t\tWITH at, collection.oi AS oi\n\t\t\t\tMATCH (oi)-[:`IS_IDENTIFIED_BY`]->(at)\n\t\t\t\tRETURN at\"\"\");\n\t}\n\n\t@Test\n\tvoid bbBoxManual() {\n\n\t\tNode location = Cypher.node(\"Location\").named(\"loc\");\n\t\tExpression sw = Cypher\n\t\t\t.point(Cypher.mapOf(\"longitude\", Cypher.literalOf(2.592773), \"latitude\", Cypher.literalOf(46.346928)));\n\t\tExpression ne = Cypher\n\t\t\t.point(Cypher.mapOf(\"longitude\", Cypher.literalOf(18.654785), \"latitude\", Cypher.literalOf(55.714735)));\n\t\tExpression withinBBox = Cypher.call(\"point.withinBBox\")\n\t\t\t.withArgs(location.property(\"coordinates\"), sw, ne)\n\t\t\t.asFunction();\n\n\t\tCondition conditions = Cypher.noCondition();\n\t\tconditions = conditions.and(withinBBox.asCondition());\n\n\t\tString stmt = Cypher.match(location).where(conditions).returning(location).build().getCypher();\n\t\tassertThat(stmt).isEqualTo(\n\t\t\t\t\"MATCH (loc:`Location`) WHERE point.withinBBox(loc.coordinates, point({longitude: 2.592773, latitude: 46.346928}), point({longitude: 18.654785, latitude: 55.714735})) RETURN loc\");\n\t}\n\n\t@Test\n\tvoid bbBox() {\n\n\t\tNode location = Cypher.node(\"Location\").named(\"loc\");\n\t\tExpression sw = Cypher.coordinate(2.592773, 46.346928);\n\t\tExpression ne = Cypher.coordinate(18.654785, 55.714735);\n\t\tExpression withinBBox = Cypher.withinBBox(location.property(\"coordinates\"), sw, ne);\n\n\t\tCondition conditions = Cypher.noCondition();\n\t\tconditions = conditions.and(withinBBox.asCondition());\n\n\t\tString stmt = Cypher.match(location).where(conditions).returning(location).build().getCypher();\n\t\tassertThat(stmt).isEqualTo(\n\t\t\t\t\"MATCH (loc:`Location`) WHERE point.withinBBox(loc.coordinates, point({longitude: 2.592773, latitude: 46.346928}), point({longitude: 18.654785, latitude: 55.714735})) RETURN loc\");\n\t}\n\n\t@Test // GH-490\n\tvoid shouldAllowAsteriskInYield() {\n\t\tStatement yield = Cypher.call(\"db.info\").yield(Cypher.asterisk()).build();\n\t\tassertThat(Renderer.getDefaultRenderer().render(yield)).isEqualTo(\"CALL db.info() YIELD *\");\n\t}\n\n\t@Test // GH-544\n\tvoid shouldAllowAsteriskInYieldAndArgs() {\n\t\tStatement yield = Cypher.call(\"dbms.listConfig\")\n\t\t\t.withArgs(Cypher.literalOf(\"port\"))\n\t\t\t.yield(Cypher.asterisk())\n\t\t\t.build();\n\t\tassertThat(Renderer.getDefaultRenderer().render(yield)).isEqualTo(\"CALL dbms.listConfig('port') YIELD *\");\n\t}\n\n\t@Test // GH-505\n\tvoid testLabelRemoval() {\n\t\tNode node = Cypher.node(\"Wine\").named(\"n\");\n\n\t\tOperation removeOp = Cypher.removeLabel(node, \"Drink\");\n\t\tList<Expression> propertyExpressions = Collections.singletonList(removeOp);\n\t\t@SuppressWarnings(\"deprecation\")\n\t\tStatementBuilder.OngoingReadingWithWhere ongoingReadingWithWhere = Cypher.match(node)\n\t\t\t.where(Functions.id(node).isEqualTo(Cypher.literalOf(1)));\n\n\t\tString expectedMessage = \"REMOVE operations are not supported in a SET clause\";\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> ongoingReadingWithWhere.set(propertyExpressions))\n\t\t\t.withMessage(expectedMessage);\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> ongoingReadingWithWhere.set(removeOp))\n\t\t\t.withMessage(expectedMessage);\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.match(node).set(removeOp))\n\t\t\t.withMessage(expectedMessage);\n\n\t\t@SuppressWarnings(\"deprecation\")\n\t\tString correctQuery = ongoingReadingWithWhere.remove(node, \"Drink\")\n\t\t\t.returning(Functions.id(node).as(\"id\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(correctQuery).isEqualTo(\"MATCH (n:`Wine`) WHERE id(n) = 1 REMOVE n:`Drink` RETURN id(n) AS id\");\n\t}\n\n\t@Test // GH-524\n\tvoid unwindWithoutWith() {\n\n\t\tSymbolicName id = Cypher.name(\"id\");\n\t\tNode n = Cypher.node(\"Person\").named(\"n\");\n\t\tRenderer renderer = Renderer.getRenderer(Configuration.newConfig().withDialect(Dialect.NEO4J_5).build());\n\t\tStatement statement = Cypher.unwind(Cypher.parameter(\"ids\"))\n\t\t\t.as(id)\n\t\t\t.match(n)\n\t\t\t.where(n.elementId().isEqualTo(id))\n\t\t\t.returning(n)\n\t\t\t.build();\n\t\tassertThat(renderer.render(statement))\n\t\t\t.isEqualTo(\"UNWIND $ids AS id MATCH (n:`Person`) WHERE elementId(n) = id RETURN n\");\n\t}\n\n\t@Test // GH-547\n\tvoid mixedBagOfWith() {\n\n\t\tvar cypher = Cypher.match(this.person)\n\t\t\t.with(this.person,\n\t\t\t\t\tCypher.count(this.person.relationshipTo(Cypher.anyNode(), \"ACTED_IN\")).as(\"actedInDegree\"))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (person:`Person`) WITH person, COUNT { (person)-[:`ACTED_IN`]->() } AS actedInDegree RETURN *\");\n\t}\n\n\t@Test // GH-553\n\tvoid allowCovariantForMakingDynamicCypherCreationEasier() {\n\n\t\tvar patterns = List.of(Cypher.node(\"A\").named(\"a\"),\n\t\t\t\tCypher.node(\"B\").relationshipTo(Cypher.node(\"C\"), \"IS_RELATED\").named(\"r\"));\n\t\tvar cypher = Cypher.match(patterns.stream().toList()).returning(Cypher.asterisk()).build().getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (a:`A`), (:`B`)-[r:`IS_RELATED`]->(:`C`) RETURN *\");\n\t}\n\n\t@Test // GH-585\n\tvoid rerenderShouldYieldSameResultOnSameRenderer() throws NoSuchFieldException, IllegalAccessException {\n\n\t\tvar anonymous = Cypher.node(\"Person\");\n\t\tvar statement = Cypher.match(anonymous).delete(anonymous).build();\n\t\tvar s1 = statement.getCypher();\n\t\tvar s2 = statement.getCypher();\n\t\tvar defaultRenderer = Renderer.getDefaultRenderer();\n\t\tvar s3 = defaultRenderer.render(statement);\n\t\tassertThat(s1).isEqualTo(s2);\n\t\tassertThat(s2).isEqualTo(s3);\n\n\t\t// Nuke the cache\n\t\tvar renderedStatementCache = defaultRenderer.getClass().getDeclaredField(\"renderedStatementCache\");\n\t\trenderedStatementCache.setAccessible(true);\n\t\t((Map<?, ?>) renderedStatementCache.get(defaultRenderer)).clear();\n\t\tvar s4 = defaultRenderer.render(statement);\n\t\tassertThat(s3).isEqualTo(s4);\n\t}\n\n\t@Test // GH-589\n\tvoid unionMustNotDestroyScope() {\n\n\t\tvar actor = Cypher.node(\"Actor\").named(\"a\");\n\t\tvar movie = Cypher.node(\"Movie\").named(\"m\");\n\t\tvar serie = Cypher.node(\"Serie\").named(\"s\");\n\t\tvar x = Cypher.name(\"x\");\n\t\tStatement statement = Cypher.match(actor)\n\t\t\t.call(Cypher.union(\n\t\t\t\t\tCypher.with(actor)\n\t\t\t\t\t\t.match(actor.relationshipTo(movie).named(\"ACTED_IN\"))\n\t\t\t\t\t\t.returning(movie.as(x.getValue()))\n\t\t\t\t\t\t.build(),\n\t\t\t\t\tCypher.with(actor)\n\t\t\t\t\t\t.match(actor.relationshipTo(serie).named(\"ACTED_IN\"))\n\t\t\t\t\t\t.returning(serie.as(x.getValue()))\n\t\t\t\t\t\t.build()))\n\t\t\t.returning(x)\n\t\t\t.build();\n\n\t\tvar expected = \"\"\"\n\t\t\t\tMATCH (a:Actor)\n\t\t\t\tCALL (*) {\n\t\t\t\t  WITH a\n\t\t\t\t  MATCH (a)-[ACTED_IN]->(m:Movie)\n\t\t\t\t  RETURN m AS x UNION\n\t\t\t\t  WITH a\n\t\t\t\t  MATCH (a)-[ACTED_IN]->(s:Serie)\n\t\t\t\t  RETURN s AS x\n\t\t\t\t}\n\t\t\t\tRETURN x\"\"\";\n\t\tvar cypher = Renderer.getRenderer(Configuration.prettyPrinting()).render(statement);\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@Test // GH-595\n\tvoid callWithMustImportIntoScope() {\n\t\tSymbolicName var = Cypher.name(\"var\");\n\t\tNode movie = Cypher.node(\"Movie\").named(\"m\");\n\t\tNode actor = Cypher.node(\"Actor\").named(\"a\");\n\t\tSymbolicName actors = Cypher.name(\"actors\");\n\t\tStatement statement = Cypher.unwind(Cypher.parameter(\"x\"))\n\t\t\t.as(var)\n\t\t\t.call(Cypher.with(var).create(movie).returning(movie).build())\n\t\t\t.call(Cypher.with(movie)\n\t\t\t\t.match(movie.relationshipFrom(actor, \"ACTED_IN\"))\n\t\t\t\t.returning(Cypher.collect(actor).as(actors))\n\t\t\t\t.build())\n\t\t\t.returning(movie.project(movie.property(\"title\"), \"actors\", actors))\n\t\t\t.build();\n\t\tvar cypher = Renderer\n\t\t\t.getRenderer(Configuration.newConfig().withDialect(Dialect.NEO4J_4).withPrettyPrint(true).build())\n\t\t\t.render(statement);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tUNWIND $x AS var\n\t\t\t\tCALL {\n\t\t\t\t  WITH var\n\t\t\t\t  CREATE (m:Movie)\n\t\t\t\t  RETURN m\n\t\t\t\t}\n\t\t\t\tCALL {\n\t\t\t\t  WITH m\n\t\t\t\t  MATCH (m)<-[:ACTED_IN]-(a:Actor)\n\t\t\t\t  RETURN collect(a) AS actors\n\t\t\t\t}\n\t\t\t\tRETURN m {\n\t\t\t\t  .title,\n\t\t\t\t  actors: actors\n\t\t\t\t}\"\"\");\n\t\tcypher = Renderer.getRenderer(Configuration.newConfig().withPrettyPrint(true).build()).render(statement);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tUNWIND $x AS var\n\t\t\t\tCALL (var) {\n\t\t\t\t  CREATE (m:Movie)\n\t\t\t\t  RETURN m\n\t\t\t\t}\n\t\t\t\tCALL (m) {\n\t\t\t\t  MATCH (m)<-[:ACTED_IN]-(a:Actor)\n\t\t\t\t  RETURN collect(a) AS actors\n\t\t\t\t}\n\t\t\t\tRETURN m {\n\t\t\t\t  .title,\n\t\t\t\t  actors: actors\n\t\t\t\t}\"\"\");\n\n\t}\n\n\t@Test // GH-595\n\tvoid callWithMustImportIntoScopeProper() {\n\t\tSymbolicName var = Cypher.name(\"var\");\n\t\tNode movie = Cypher.node(\"Movie\").named(\"m\");\n\t\tNode actor = Cypher.node(\"Actor\").named(\"a\");\n\t\tSymbolicName actors = Cypher.name(\"actors\");\n\t\tStatement statement = Cypher.unwind(Cypher.parameter(\"x\"))\n\t\t\t.as(var)\n\t\t\t.call(Cypher.create(movie).returning(movie).build(), var)\n\t\t\t.call(Cypher.match(movie.relationshipFrom(actor, \"ACTED_IN\"))\n\t\t\t\t.returning(Cypher.collect(actor).as(actors))\n\t\t\t\t.build(), movie)\n\t\t\t.returning(movie.project(movie.property(\"title\"), \"actors\", actors))\n\t\t\t.build();\n\t\tvar cypher = Renderer\n\t\t\t.getRenderer(Configuration.newConfig().withDialect(Dialect.NEO4J_4).withPrettyPrint(true).build())\n\t\t\t.render(statement);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tUNWIND $x AS var\n\t\t\t\tCALL {\n\t\t\t\t  WITH var\n\t\t\t\t  CREATE (m:Movie)\n\t\t\t\t  RETURN m\n\t\t\t\t}\n\t\t\t\tCALL {\n\t\t\t\t  WITH m\n\t\t\t\t  MATCH (m)<-[:ACTED_IN]-(a:Actor)\n\t\t\t\t  RETURN collect(a) AS actors\n\t\t\t\t}\n\t\t\t\tRETURN m {\n\t\t\t\t  .title,\n\t\t\t\t  actors: actors\n\t\t\t\t}\"\"\");\n\n\t\tcypher = Renderer.getRenderer(Configuration.newConfig().withPrettyPrint(true).build()).render(statement);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tUNWIND $x AS var\n\t\t\t\tCALL (var) {\n\t\t\t\t  CREATE (m:Movie)\n\t\t\t\t  RETURN m\n\t\t\t\t}\n\t\t\t\tCALL (m) {\n\t\t\t\t  MATCH (m)<-[:ACTED_IN]-(a:Actor)\n\t\t\t\t  RETURN collect(a) AS actors\n\t\t\t\t}\n\t\t\t\tRETURN m {\n\t\t\t\t  .title,\n\t\t\t\t  actors: actors\n\t\t\t\t}\"\"\");\n\n\t}\n\n\t@ParameterizedTest(name = \"{1}\") // GH-605\n\t@MethodSource\n\tvoid conditionExpressionShouldWorkInReturn(Statement statement, String expected) {\n\t\tString cypher = statement.getCypher();\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@Test\n\tvoid manipulatingListExpressionsShouldBePossible() {\n\t\tvar n = Cypher.node(\"Person\").named(\"n\");\n\t\tvar x = Cypher.name(\"x\");\n\t\tvar rolesToAdd = Cypher.parameter(\"rolesToAdd\");\n\t\tvar rolesToRemove = Cypher.parameter(\"rolesToRemove\");\n\t\tvar cypher = Cypher.match(n)\n\t\t\t.returning(Cypher.listWith(x)\n\t\t\t\t.in(n.property(\"roles\"))\n\t\t\t\t.where(x.in(rolesToAdd).and(Cypher.not(x.in(rolesToRemove))))\n\t\t\t\t.returning()\n\t\t\t\t.add(rolesToAdd))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (n:`Person`) RETURN ([x IN n.roles WHERE (x IN $rolesToAdd AND NOT (x IN $rolesToRemove))] + $rolesToAdd)\");\n\t}\n\n\t@Test // GH-630\n\tvoid typesOfShouldWork() {\n\n\t\tvar p = Cypher.path(\"p\").definedBy(Cypher.node(\"Movie\").relationshipFrom(Cypher.anyNode()).named(\"r\"));\n\t\tvar x = Cypher.name(\"x\");\n\t\tvar relationTypeCast = Cypher.listWith(x).in(Cypher.relationships(p)).returning(Cypher.type(x));\n\n\t\tassertThat(Cypher.match(p).returning(relationTypeCast).build().getCypher())\n\t\t\t.isEqualTo(\"MATCH p = (:`Movie`)<-[r]-() RETURN [x IN relationships(p) | type(x)]\");\n\n\t\t// Current workaround\n\t\tvar relationTypeCast2 = Cypher.listWith(x)\n\t\t\t.in(Cypher.relationships(p))\n\t\t\t.returning(Cypher.call(\"type\").withArgs(x).asFunction());\n\t\tassertThat(Cypher.match(p).returning(relationTypeCast2).build().getCypher())\n\t\t\t.isEqualTo(\"MATCH p = (:`Movie`)<-[r]-() RETURN [x IN relationships(p) | type(x)]\");\n\t}\n\n\t@Test // GH-630\n\tvoid labelsOfShouldWork() {\n\n\t\tvar p = Cypher.path(\"p\").definedBy(Cypher.node(\"Movie\").relationshipFrom(Cypher.anyNode()).named(\"r\"));\n\n\t\tvar nodes = Cypher.name(\"nodes\");\n\t\tvar node = Cypher.name(\"node\");\n\t\tvar labels = Cypher.name(\"labels\");\n\t\tvar label = Cypher.name(\"label\");\n\n\t\t// The worst query ever to retrieve those labels. Don't do this at home.\n\t\tassertThat(Cypher.match(p)\n\t\t\t.with(Cypher.nodes(p).as(nodes))\n\t\t\t.unwind(nodes)\n\t\t\t.as(node)\n\t\t\t.with(Cypher.labels(node).as(labels))\n\t\t\t.unwind(labels)\n\t\t\t.as(label)\n\t\t\t.returningDistinct(label)\n\t\t\t.build()\n\t\t\t.getCypher()).isEqualTo(\n\t\t\t\t\t\"MATCH p = (:`Movie`)<-[r]-() WITH nodes(p) AS nodes UNWIND nodes AS node WITH labels(node) AS labels UNWIND labels AS label RETURN DISTINCT label\");\n\t}\n\n\t@Test // GH-634\n\tvoid withAllShouldWork() {\n\n\t\tvar this0 = Cypher.node(\"User\").named(\"this\");\n\t\tvar x = Cypher.name(\"x\");\n\t\tvar stmt = Cypher.match(this0)\n\t\t\t.call(Cypher.with(Cypher.asterisk())\n\t\t\t\t.with(this0.as(\"x\"))\n\t\t\t\t.returning(Cypher.count(Cypher.asterisk()).as(x))\n\t\t\t\t.build())\n\t\t\t.returning(x, Cypher.count(Cypher.asterisk()))\n\t\t\t.build();\n\n\t\tassertThat(stmt.getCypher())\n\t\t\t.isEqualTo(\"MATCH (this:`User`) CALL (*) {WITH this AS x RETURN count(*) AS x} RETURN x, count(*)\");\n\t\tassertThat(Renderer.getRenderer(Configuration.newConfig().withDialect(Dialect.NEO4J_4).build()).render(stmt))\n\t\t\t.isEqualTo(\"MATCH (this:`User`) CALL {WITH * WITH this AS x RETURN count(*) AS x} RETURN x, count(*)\");\n\t}\n\n\t@Test\n\tvoid withAllProperShouldWork() {\n\n\t\tvar this0 = Cypher.node(\"User\").named(\"this\");\n\t\tvar x = Cypher.name(\"x\");\n\t\tvar stmt = Cypher.match(this0)\n\t\t\t.call(Cypher.with(this0.as(\"x\")).returning(Cypher.count(Cypher.asterisk()).as(x)).build(),\n\t\t\t\t\tCypher.asterisk())\n\t\t\t.returning(x, Cypher.count(Cypher.asterisk()))\n\t\t\t.build();\n\n\t\tassertThat(stmt.getCypher())\n\t\t\t.isEqualTo(\"MATCH (this:`User`) CALL (*) {WITH this AS x RETURN count(*) AS x} RETURN x, count(*)\");\n\t\tassertThat(Renderer.getRenderer(Configuration.newConfig().withDialect(Dialect.NEO4J_4).build()).render(stmt))\n\t\t\t.isEqualTo(\"MATCH (this:`User`) CALL {WITH * WITH this AS x RETURN count(*) AS x} RETURN x, count(*)\");\n\t}\n\n\t@Test // GH-634\n\tvoid withAllAndThenSome() {\n\n\t\tvar stmt = Cypher.match(Cypher.anyNode(\"n\"))\n\t\t\t.with(Cypher.asterisk(), Cypher.count(Cypher.asterisk()).as(\"count\"))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build();\n\n\t\tvar expected = \"MATCH (n) WITH *, count(*) AS count RETURN *\";\n\t\tassertThat(stmt.getCypher()).isEqualTo(expected);\n\t}\n\n\t@Test // GH-642\n\tvoid mapLiteralShouldRenderProper() {\n\n\t\tvar l = Cypher.literalOf(new TreeMap<>(Map.of(\"a\", 1, \"b\", \"c\", \"whatever\", Cypher.literalOf(1))));\n\t\tassertThat(l).hasToString(\"MapLiteral{cypher={a: 1, b: 'c', whatever: 1}}\");\n\t}\n\n\t@Test // GH-694\n\t@SuppressWarnings(\"deprecation\")\n\tvoid fullTextCallShouldWork() {\n\n\t\tvar city = Cypher.anyNode(\"city\");\n\t\tvar node = Cypher.name(\"node\");\n\t\tvar score = Cypher.name(\"score\");\n\t\tvar statement = Cypher\n\t\t\t.match(Cypher.path(\"path\").definedBy(Cypher.node(\"Person\").named(\"p\").relationshipTo(city, \"TRAVELED_TO\")))\n\t\t\t.where(Cypher.exists(Cypher.call(\"db.index.fulltext.queryNodes\")\n\t\t\t\t.withArgs(Cypher.literalOf(\"City\"), Cypher.literalOf(\"ham*\"))\n\t\t\t\t.yield(node, score)\n\t\t\t\t.with(Cypher.asterisk())\n\t\t\t\t.where(Functions.id(Cypher.anyNode(node)).eq(Functions.id(city)))\n\t\t\t\t.returning(node, score)\n\t\t\t\t.build()))\n\t\t\t.returning(Cypher.name(\"path\"))\n\t\t\t.build();\n\t\tassertThat(statement.getCypher()).isEqualTo(\"\"\"\n\t\t\t\tMATCH path = (p:`Person`)-[:`TRAVELED_TO`]->(city)\n\t\t\t\tWHERE EXISTS {\n\t\t\t\tCALL db.index.fulltext.queryNodes('City', 'ham*')\n\t\t\t\tYIELD node, score\n\t\t\t\tWITH *\n\t\t\t\tWHERE id(node) = id(city)\n\t\t\t\tRETURN node, score\n\t\t\t\t}\n\t\t\t\tRETURN path\"\"\".replace(\"\\n\", \" \"));\n\t}\n\n\t@Test // GH-712\n\tvoid relationshipChainsMustActivelyEnterRelationshipsDuringVisit() {\n\n\t\tvar tom = Cypher.node(\"Person\").named(\"person0\").withProperties(\"name\", Cypher.literalOf(\"Tom Hanks\"));\n\t\tvar movie = Cypher.node(\"Movie\").named(\"movie0\");\n\t\tvar coActors = Cypher.node(\"Person\").named(\"person1\");\n\t\tvar path0 = Cypher.path(\"path0\");\n\t\tvar path1 = Cypher.path(\"path1\");\n\n\t\tvar statement = Cypher\n\t\t\t.match(path0.definedBy(\n\t\t\t\t\ttom.relationshipTo(movie, \"ACTED_IN\").named(\"acted_in0\").relationshipFrom(coActors, \"ACTED_IN\")))\n\t\t\t.match(path1.definedBy(\n\t\t\t\t\ttom.relationshipTo(movie, \"ACTED_IN\").named(\"acted_in0\").relationshipFrom(coActors, \"ACTED_IN\")))\n\t\t\t.returning(\"path0\", \"path1\")\n\t\t\t.build();\n\n\t\tvar cypher = Renderer.getRenderer(Configuration.prettyPrinting()).render(statement);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tMATCH path0 = (person0:Person {\n\t\t\t\t  name: 'Tom Hanks'\n\t\t\t\t})-[acted_in0:ACTED_IN]->(movie0:Movie)<-[:ACTED_IN]-(person1:Person)\n\t\t\t\tMATCH path1 = (person0)-[acted_in0]->(movie0)<-[:ACTED_IN]-(person1)\n\t\t\t\tRETURN path0, path1\"\"\");\n\t}\n\n\t@Test // GH-749\n\tvoid nonBuilderRelationshipMethodShouldWork() {\n\n\t\tvar n1 = Cypher.node(\"N1\");\n\t\tvar n2 = Cypher.node(\"N2\");\n\n\t\tassertThat(Cypher.match(n1.relationshipWith(n2, Relationship.Direction.LTR, \"X\").named(\"x\"))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher()).isEqualTo(\"MATCH (:`N1`)-[x:`X`]->(:`N2`) RETURN *\");\n\t\tassertThat(Cypher.match(n1.relationshipWith(n2, Relationship.Direction.RTL, \"X\").named(\"x\"))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher()).isEqualTo(\"MATCH (:`N1`)<-[x:`X`]-(:`N2`) RETURN *\");\n\t\tassertThat(Cypher.match(n1.relationshipWith(n2, Relationship.Direction.UNI, \"X\").named(\"x\"))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher()).isEqualTo(\"MATCH (:`N1`)-[x:`X`]-(:`N2`) RETURN *\");\n\t}\n\n\t@Test // GH-826\n\tvoid identifiablesCreatedInSubqueriesMustBeRecognizedAsSeenToo() {\n\n\t\tvar n1 = Cypher.node(\"Foo\").named(\"n1\");\n\t\tvar n2 = Cypher.node(\"Bar\").named(\"n2\");\n\t\tvar resultStatement = Cypher.create(n1)\n\t\t\t.with(n1)\n\t\t\t.call(Cypher.with(n1)\n\t\t\t\t.merge(n2.withProperties(\"foo\", Cypher.literalOf(\"x\")))\n\t\t\t\t.create(n1.relationshipTo(n2, \"NESTED\"))\n\t\t\t\t.returning(Cypher.count(n2).as(\"foo_2\"))\n\t\t\t\t.build())\n\t\t\t.returning(Cypher.literalTrue())\n\t\t\t.build();\n\n\t\tassertThat(resultStatement.getCypher()).isEqualTo(\n\t\t\t\t\"CREATE (n1:`Foo`) WITH n1 CALL (n1) {MERGE (n2:`Bar` {foo: 'x'}) CREATE (n1)-[:`NESTED`]->(n2) RETURN count(n2) AS foo_2} RETURN true\");\n\t}\n\n\t@Test // GH-832\n\tvoid sequentialExistingSubqueriesShouldNotHaveScopingIssues() {\n\n\t\tvar n1 = Cypher.node(\"Foo\").named(\"n1\");\n\t\tvar n2 = Cypher.node(\"Bar\").named(\"n2\");\n\t\tvar resultStatement = Cypher.match(n1)\n\t\t\t.where(Cypher.match(n1.relationshipTo(n2))\n\t\t\t\t.where(n2.property(\"bar\").isFalse())\n\t\t\t\t.asCondition()\n\t\t\t\t.or(Cypher.match(n1.relationshipTo(n2)).where(n2.property(\"foo\").isTrue()).asCondition()))\n\t\t\t.returning(Cypher.literalTrue())\n\t\t\t.build();\n\n\t\tassertThat(resultStatement.getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (n1:`Foo`) \" + \"WHERE (EXISTS {\" + \" MATCH (n1)-->(n2:`Bar`)\" + \" WHERE n2.bar = false \" + \"} \"\n\t\t\t\t\t\t+ \"OR EXISTS {\" + \" MATCH (n1)-->(n2:`Bar`)\" + \" WHERE n2.foo = true \" + \"}) \" + \"RETURN true\");\n\t}\n\n\t@Test // GH-838\n\tvoid aliasMustBeIncludedInSubqueries1() {\n\t\tvar n1 = Cypher.node(\"Foo\").named(\"n1\");\n\t\tvar point = Cypher.name(\"point\");\n\t\tvar resultStatement = Cypher.match(n1)\n\t\t\t.returning(n1.project(\"points\",\n\t\t\t\t\tCypher.collect(Cypher.unwind(n1.property(\"points\"))\n\t\t\t\t\t\t.as(point)\n\t\t\t\t\t\t.returning(Cypher.listOf(point.property(\"x\"), point.property(\"y\")))\n\t\t\t\t\t\t.build())))\n\t\t\t.build();\n\n\t\tassertThat(resultStatement.getCypher()).isEqualTo(\"MATCH (n1:`Foo`) \" + \"RETURN n1{\" + \"points: COLLECT {\"\n\t\t\t\t+ \" UNWIND n1.points AS point\" + \" RETURN [point.x, point.y]\" + \" }\" + \"}\");\n\t}\n\n\t@Test // GH-838\n\tvoid aliasMustBeIncludedInSubqueries2() {\n\t\tvar n1 = Cypher.node(\"Foo\").named(\"n1\");\n\t\tvar point = Cypher.name(\"point\");\n\t\tvar points = Cypher.name(\"points\");\n\t\tvar resultStatement = Cypher.match(n1)\n\t\t\t.returning(n1.project(\"points\",\n\t\t\t\t\torg.neo4j.cypherdsl.core.Cypher.collect(Cypher.with(n1.property(\"points\").as(points))\n\t\t\t\t\t\t.unwind(points)\n\t\t\t\t\t\t.as(point)\n\t\t\t\t\t\t.returning(Cypher.listOf(point.property(\"x\"), point.property(\"y\")))\n\t\t\t\t\t\t.build())))\n\t\t\t.build();\n\n\t\tassertThat(resultStatement.getCypher()).isEqualTo(\"MATCH (n1:`Foo`) \" + \"RETURN n1{\" + \"points: COLLECT {\"\n\t\t\t\t+ \" WITH n1.points AS points\" + \" UNWIND points AS point\" + \" RETURN [point.x, point.y]\" + \" }\" + \"}\");\n\t}\n\n\t@Test // GH-838\n\tvoid aliasMustBeIncludedInSubqueries3() {\n\t\tvar n1 = Cypher.node(\"Foo\").named(\"n1\");\n\t\tvar n2 = Cypher.node(\"Bar\").named(\"n2\");\n\t\tvar point = Cypher.name(\"point\");\n\t\tvar resultStatement = Cypher.match(n1)\n\t\t\t.returning(n1.project(\"points\", Cypher.collect(Cypher.unwind(n1.property(\"points\"))\n\t\t\t\t.as(point)\n\t\t\t\t.match(n2)\n\t\t\t\t.where(n2.property(\"loc\").eq(point))\n\t\t\t\t.returning(n2.project(n2.property(\"y\").as(\"x\"), Cypher.collect(\n\t\t\t\t\t\tCypher.match(Cypher.node(\"FooBar\").named(\"fb\")).returning(Cypher.name(\"fb\").as(\"foo\")).build())\n\t\t\t\t\t.as(\"y\")))\n\t\t\t\t.build())))\n\t\t\t.build();\n\n\t\tassertThat(resultStatement.getCypher()).isEqualTo(\"MATCH (n1:`Foo`) \" + \"RETURN n1{\" + \"points: COLLECT {\"\n\t\t\t\t+ \" UNWIND n1.points AS point\" + \" MATCH (n2:`Bar`)\" + \" WHERE n2.loc = point\"\n\t\t\t\t+ \" RETURN n2{x: n2.y, y: COLLECT { MATCH (fb:`FooBar`) RETURN fb AS foo }}\" + \" }\" + \"}\");\n\t}\n\n\t@Test // GH-533\n\tvoid additionalUnitSubqueries() {\n\n\t\tvar createThis1 = Cypher.name(\"create_this1\");\n\t\tvar createVar0 = Cypher.name(\"create_var0\");\n\t\tvar createVar2 = Cypher.name(\"create_var2\");\n\t\tvar createThis5 = Cypher.name(\"create_this5\");\n\t\tvar createVar3 = Cypher.name(\"create_var3\");\n\t\tvar stmt = Cypher.unwind(Cypher.parameter(\"create_param0\"))\n\t\t\t.as(createVar0)\n\t\t\t.call(Cypher.with(createVar0)\n\t\t\t\t.create(Cypher.node(\"Movie\").named(createThis1))\n\t\t\t\t.set(createThis1.property(\"id\").to(createVar0.property(\"id\")))\n\t\t\t\t.with(createThis1, createVar0)\n\t\t\t\t.call(Cypher.with(createThis1, createVar0)\n\t\t\t\t\t.unwind(createVar0.property(\"actors\").property(\"create\"))\n\t\t\t\t\t.as(createVar2)\n\t\t\t\t\t.with(createVar2.property(\"node\").as(createVar3), createVar2.property(\"edge\").as(\"create_var4\"),\n\t\t\t\t\t\t\tcreateThis1)\n\t\t\t\t\t.create(Cypher.node(\"Actor\").named(createThis5))\n\t\t\t\t\t.set(createThis5.property(\"name\").to(createVar3.property(\"name\")))\n\t\t\t\t\t.merge(Cypher.anyNode(createThis1)\n\t\t\t\t\t\t.relationshipFrom(Cypher.anyNode(createThis5), \"ACTED_IN\")\n\t\t\t\t\t\t.named(\"create_this6\"))\n\t\t\t\t\t.build())\n\t\t\t\t.returning(createThis1)\n\t\t\t\t.build())\n\t\t\t.returning(Cypher.collect(createThis1.project(\"id\")).as(\"data\"))\n\t\t\t.build();\n\n\t\tString cypher = Renderer\n\t\t\t.getRenderer(Configuration.newConfig().withPrettyPrint(true).withDialect(Dialect.NEO4J_4).build())\n\t\t\t.render(stmt);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tUNWIND $create_param0 AS create_var0\n\t\t\t\tCALL {\n\t\t\t\t  WITH create_var0\n\t\t\t\t  CREATE (create_this1:Movie)\n\t\t\t\t  SET create_this1.id = create_var0.id\n\t\t\t\t  WITH create_this1, create_var0\n\t\t\t\t  CALL {\n\t\t\t\t    WITH create_this1, create_var0\n\t\t\t\t    UNWIND create_var0.actors.create AS create_var2\n\t\t\t\t    WITH create_var2.node AS create_var3, create_var2.edge AS create_var4, create_this1\n\t\t\t\t    CREATE (create_this5:Actor)\n\t\t\t\t    SET create_this5.name = create_var3.name\n\t\t\t\t    MERGE (create_this1)<-[create_this6:ACTED_IN]-(create_this5)\n\t\t\t\t  }\n\t\t\t\t  RETURN create_this1\n\t\t\t\t}\n\t\t\t\tRETURN collect(create_this1 {\n\t\t\t\t  .id\n\t\t\t\t}) AS data\"\"\");\n\n\t\tcypher = Renderer.getRenderer(Configuration.prettyPrinting()).render(stmt);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tUNWIND $create_param0 AS create_var0\n\t\t\t\tCALL (create_var0) {\n\t\t\t\t  CREATE (create_this1:Movie)\n\t\t\t\t  SET create_this1.id = create_var0.id\n\t\t\t\t  WITH create_this1, create_var0\n\t\t\t\t  CALL (create_this1, create_var0) {\n\t\t\t\t    UNWIND create_var0.actors.create AS create_var2\n\t\t\t\t    WITH create_var2.node AS create_var3, create_var2.edge AS create_var4, create_this1\n\t\t\t\t    CREATE (create_this5:Actor)\n\t\t\t\t    SET create_this5.name = create_var3.name\n\t\t\t\t    MERGE (create_this1)<-[create_this6:ACTED_IN]-(create_this5)\n\t\t\t\t  }\n\t\t\t\t  RETURN create_this1\n\t\t\t\t}\n\t\t\t\tRETURN collect(create_this1 {\n\t\t\t\t  .id\n\t\t\t\t}) AS data\"\"\");\n\t}\n\n\t@Test // GH-533\n\tvoid additionalUnitSubqueriesExplicitImports() {\n\n\t\tvar createThis1 = Cypher.name(\"create_this1\");\n\t\tvar createVar0 = Cypher.name(\"create_var0\");\n\t\tvar createVar2 = Cypher.name(\"create_var2\");\n\t\tvar createThis5 = Cypher.name(\"create_this5\");\n\t\tvar createVar3 = Cypher.name(\"create_var3\");\n\t\tvar stmt = Cypher.unwind(Cypher.parameter(\"create_param0\"))\n\t\t\t.as(createVar0)\n\t\t\t.call(Cypher.with(createVar0)\n\t\t\t\t.create(Cypher.node(\"Movie\").named(createThis1))\n\t\t\t\t.set(createThis1.property(\"id\").to(createVar0.property(\"id\")))\n\t\t\t\t.with(createThis1, createVar0)\n\t\t\t\t.call(Cypher.with(createThis1, createVar0)\n\t\t\t\t\t.unwind(createVar0.property(\"actors\").property(\"create\"))\n\t\t\t\t\t.as(createVar2)\n\t\t\t\t\t.with(createVar2.property(\"node\").as(createVar3), createVar2.property(\"edge\").as(\"create_var4\"),\n\t\t\t\t\t\t\tcreateThis1)\n\t\t\t\t\t.create(Cypher.node(\"Actor\").named(createThis5))\n\t\t\t\t\t.set(createThis5.property(\"name\").to(createVar3.property(\"name\")))\n\t\t\t\t\t.merge(Cypher.anyNode(createThis1)\n\t\t\t\t\t\t.relationshipFrom(Cypher.anyNode(createThis5), \"ACTED_IN\")\n\t\t\t\t\t\t.named(\"create_this6\"))\n\t\t\t\t\t.build(), createThis1, createVar0)\n\t\t\t\t.returning(createThis1)\n\t\t\t\t.build(), createVar0)\n\t\t\t.returning(Cypher.collect(createThis1.project(\"id\")).as(\"data\"))\n\t\t\t.build();\n\n\t\tString cypher = Renderer\n\t\t\t.getRenderer(Configuration.newConfig().withPrettyPrint(true).withDialect(Dialect.NEO4J_4).build())\n\t\t\t.render(stmt);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tUNWIND $create_param0 AS create_var0\n\t\t\t\tCALL {\n\t\t\t\t  WITH create_var0\n\t\t\t\t  WITH create_var0\n\t\t\t\t  CREATE (create_this1:Movie)\n\t\t\t\t  SET create_this1.id = create_var0.id\n\t\t\t\t  WITH create_this1, create_var0\n\t\t\t\t  CALL {\n\t\t\t\t    WITH create_this1, create_var0\n\t\t\t\t    WITH create_this1, create_var0\n\t\t\t\t    UNWIND create_var0.actors.create AS create_var2\n\t\t\t\t    WITH create_var2.node AS create_var3, create_var2.edge AS create_var4, create_this1\n\t\t\t\t    CREATE (create_this5:Actor)\n\t\t\t\t    SET create_this5.name = create_var3.name\n\t\t\t\t    MERGE (create_this1)<-[create_this6:ACTED_IN]-(create_this5)\n\t\t\t\t  }\n\t\t\t\t  RETURN create_this1\n\t\t\t\t}\n\t\t\t\tRETURN collect(create_this1 {\n\t\t\t\t  .id\n\t\t\t\t}) AS data\"\"\");\n\n\t\tcypher = Renderer.getRenderer(Configuration.prettyPrinting()).render(stmt);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tUNWIND $create_param0 AS create_var0\n\t\t\t\tCALL (create_var0) {\n\t\t\t\t  WITH create_var0\n\t\t\t\t  CREATE (create_this1:Movie)\n\t\t\t\t  SET create_this1.id = create_var0.id\n\t\t\t\t  WITH create_this1, create_var0\n\t\t\t\t  CALL (create_this1, create_var0) {\n\t\t\t\t    WITH create_this1, create_var0\n\t\t\t\t    UNWIND create_var0.actors.create AS create_var2\n\t\t\t\t    WITH create_var2.node AS create_var3, create_var2.edge AS create_var4, create_this1\n\t\t\t\t    CREATE (create_this5:Actor)\n\t\t\t\t    SET create_this5.name = create_var3.name\n\t\t\t\t    MERGE (create_this1)<-[create_this6:ACTED_IN]-(create_this5)\n\t\t\t\t  }\n\t\t\t\t  RETURN create_this1\n\t\t\t\t}\n\t\t\t\tRETURN collect(create_this1 {\n\t\t\t\t  .id\n\t\t\t\t}) AS data\"\"\");\n\t}\n\n\t@Test // GH-903\n\tvoid variablesOfListPredicatesMustNotBeScoped() {\n\n\t\tvar expected = \"\"\"\n\t\t\t\tMATCH (this:`Movie`)\n\t\t\t\tWHERE single(this0 IN [(this)-[this1:`IN_GENRE`]->(this0:`Genre`) WHERE this0.name = $param0 | 1] WHERE true)\n\t\t\t\tRETURN this{.actorCount} AS this\"\"\";\n\n\t\tvar movie = Cypher.node(\"Movie\").named(\"this\");\n\t\tvar genre = Cypher.node(\"Genre\").named(\"this0\");\n\t\tvar rel = movie.relationshipTo(genre, \"IN_GENRE\").named(\"this1\");\n\t\tvar statement = Cypher.match(movie)\n\t\t\t.where(Cypher.single(\"this0\")\n\t\t\t\t.in(Cypher.listBasedOn(rel)\n\t\t\t\t\t.where(genre.property(\"name\").eq(Cypher.parameter(\"param0\")))\n\t\t\t\t\t.returning(Cypher.literalOf(1)))\n\t\t\t\t.where(Cypher.isTrue()))\n\t\t\t.returning(movie.project(\"actorCount\").as(\"this\"))\n\t\t\t.build();\n\t\tassertThat(statement.getCypher()).isEqualTo(expected.replace(\"\\n\", \" \"));\n\t}\n\n\t@ParameterizedTest // GH-999\n\t@EnumSource(value = Dialect.class, names = { \"NEO4J_4\", \"NEO4J_5_DEFAULT_CYPHER\" })\n\tvoid subQueryFromParserScope(Dialect dialect) {\n\t\tvar cfg = Configuration.newConfig().withPrettyPrint(true).withGeneratedNames(true).withDialect(dialect).build();\n\t\tvar renderer = Renderer.getRenderer(cfg);\n\n\t\tvar named = Cypher.node(\"Movie\").named(\"m\");\n\t\tvar stmt = Cypher.call(Cypher.create(named).returning(\"m\").build())\n\t\t\t.call(Cypher\n\t\t\t\t.returning(named.project(Cypher.property(named.getRequiredSymbolicName(), \"title\")).as(\"movies\"))\n\t\t\t\t.build(), named)\n\t\t\t.returning(\"movies\")\n\t\t\t.build();\n\t\tvar normalized = renderer.render(stmt);\n\n\t\tvar expected = (dialect == Dialect.NEO4J_4) ? \"\"\"\n\t\t\t\tCALL {\n\t\t\t\t  CREATE (v0:Movie)\n\t\t\t\t  RETURN v0\n\t\t\t\t}\n\t\t\t\tCALL {\n\t\t\t\t  WITH v0\n\t\t\t\t  RETURN v0 {\n\t\t\t\t    .title\n\t\t\t\t  } AS v1\n\t\t\t\t}\n\t\t\t\tRETURN v1\"\"\" : \"\"\"\n\t\t\t\tCALL () {\n\t\t\t\t  CREATE (v0:Movie)\n\t\t\t\t  RETURN v0\n\t\t\t\t}\n\t\t\t\tCALL (v0) {\n\t\t\t\t  RETURN v0 {\n\t\t\t\t    .title\n\t\t\t\t  } AS v1\n\t\t\t\t}\n\t\t\t\tRETURN v1\"\"\";\n\t\tassertThat(normalized).isEqualTo(expected);\n\t}\n\n\t@Test // GH-1014\n\tvoid patternExpressionMustNotIntroduceNames() {\n\n\t\tvar userIdParam = Cypher.parameter(\"userId\");\n\n\t\tvar book = Cypher.node(\"Book\").named(\"b\");\n\t\tvar userActivity = Cypher.node(\"UserSuggestionActivity\").named(\"ua\").withProperties(\"userId\", userIdParam);\n\n\t\t// ua has not been used before\n\t\tvar rel = book.relationshipBetween(userActivity);\n\t\tvar cypher = Cypher.match(book)\n\t\t\t.where(Cypher.not(Cypher.exists(rel)))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (b:`Book`) WHERE NOT (exists((b)--(:`UserSuggestionActivity` {userId: $userId}))) RETURN *\");\n\n\t\t// b has not been used before\n\t\tcypher = Cypher.match(userActivity)\n\t\t\t.where(Cypher.not(Cypher.exists(rel)))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (ua:`UserSuggestionActivity` {userId: $userId}) WHERE NOT (exists((:`Book`)--(ua))) RETURN *\");\n\n\t\t// Both have been used before, example does not make much sense, but still\n\t\tcypher = Cypher.match(book.relationshipFrom(userActivity, \"WROTE\"))\n\t\t\t.where(Cypher.not(Cypher.exists(rel)))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (b:`Book`)<-[:`WROTE`]-(ua:`UserSuggestionActivity` {userId: $userId}) WHERE NOT (exists((b)--(ua))) RETURN *\");\n\n\t\t// All expressions\n\t\tcypher = Cypher.match(book).returning(Cypher.size(rel)).build().getCypher();\n\n\t\tassertThat(cypher)\n\t\t\t.isEqualTo(\"MATCH (b:`Book`) RETURN size((b)--(:`UserSuggestionActivity` {userId: $userId}))\");\n\t}\n\n\t@Test\n\tvoid generatedNamesWithDeeplyNestedSubquerie() {\n\t\tvar m = Cypher.node(\"Movie\").named(\"this\");\n\t\tvar a = Cypher.node(\"Actor\").named(\"this1\");\n\t\tvar edge = Cypher.name(\"edge\");\n\t\tvar this1 = Cypher.name(\"this1\");\n\t\tvar edges = Cypher.name(\"edges\");\n\t\tvar stmt = Cypher.match(m)\n\t\t\t.call(Cypher.match(m.relationshipFrom(a, \"ACTED_IN\").named(\"this0\"))\n\t\t\t\t.with(Cypher.collect(Cypher.mapOf(\"node\", this1)).as(edges))\n\t\t\t\t.with(edges, Cypher.size(edges).as(\"totalCount\"))\n\t\t\t\t.call(Cypher.unwind(edges)\n\t\t\t\t\t.as(edge)\n\t\t\t\t\t.with(edge.property(\"node\").as(this1))\n\t\t\t\t\t.call(Cypher\n\t\t\t\t\t\t.match(Cypher.anyNode(this1)\n\t\t\t\t\t\t\t.relationshipTo(Cypher.node(\"Movie\").named(\"this3\"), \"ACTED_IN\")\n\t\t\t\t\t\t\t.named(\"this2\"))\n\t\t\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t\t\t.build(), this1)\n\t\t\t\t\t.build(), edges)\n\t\t\t\t.build(), m)\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build();\n\n\t\tassertThat(Renderer\n\t\t\t.getRenderer(Configuration.newConfig()\n\t\t\t\t.withPrettyPrint(true)\n\t\t\t\t.withGeneratedNames(true)\n\t\t\t\t.withDialect(Dialect.NEO4J_4)\n\t\t\t\t.build())\n\t\t\t.render(stmt)).isEqualTo(\"\"\"\n\t\t\t\t\tMATCH (v0:Movie)\n\t\t\t\t\tCALL {\n\t\t\t\t\t  WITH v0\n\t\t\t\t\t  MATCH (v0)<-[v1:ACTED_IN]-(v2:Actor)\n\t\t\t\t\t  WITH collect( {\n\t\t\t\t\t    node: v2\n\t\t\t\t\t  }) AS v3\n\t\t\t\t\t  WITH v3, size(v3) AS v4\n\t\t\t\t\t  CALL {\n\t\t\t\t\t    WITH v3\n\t\t\t\t\t    UNWIND v3 AS v5\n\t\t\t\t\t    WITH v5.node AS v6\n\t\t\t\t\t    CALL {\n\t\t\t\t\t      WITH v6\n\t\t\t\t\t      MATCH (v6)-[v0:ACTED_IN]->(v1:Movie)\n\t\t\t\t\t      RETURN *\n\t\t\t\t\t    }\n\t\t\t\t\t  }\n\t\t\t\t\t}\n\t\t\t\t\tRETURN *\"\"\");\n\n\t\tassertThat(\n\t\t\t\tRenderer.getRenderer(Configuration.newConfig().withPrettyPrint(true).withGeneratedNames(true).build())\n\t\t\t\t\t.render(stmt))\n\t\t\t.isEqualTo(\"\"\"\n\t\t\t\t\tMATCH (v0:Movie)\n\t\t\t\t\tCALL (v0) {\n\t\t\t\t\t  MATCH (v0)<-[v1:ACTED_IN]-(v2:Actor)\n\t\t\t\t\t  WITH collect( {\n\t\t\t\t\t    node: v2\n\t\t\t\t\t  }) AS v3\n\t\t\t\t\t  WITH v3, size(v3) AS v4\n\t\t\t\t\t  CALL (v3) {\n\t\t\t\t\t    UNWIND v3 AS v5\n\t\t\t\t\t    WITH v5.node AS v6\n\t\t\t\t\t    CALL (v6) {\n\t\t\t\t\t      MATCH (v6)-[v0:ACTED_IN]->(v1:Movie)\n\t\t\t\t\t      RETURN *\n\t\t\t\t\t    }\n\t\t\t\t\t  }\n\t\t\t\t\t}\n\t\t\t\t\tRETURN *\"\"\");\n\t}\n\n\t@ParameterizedTest // GH-1084\n\t@MethodSource\n\tvoid reusingAliases(EnumSet<Configuration.GeneratedNames> config, String expected) {\n\t\tvar renderer = Renderer.getRenderer(Configuration.newConfig().withGeneratedNames(config).build());\n\n\t\tvar movie = Cypher.node(\"Movie\").named(\"movie\");\n\t\tvar cypher = renderer.render(Cypher.match(movie).returning(movie.project(\"a\", \"b\").as(\"movie\")).build());\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@Test // GH-1113\n\tvoid listComprehensionsBasedOnRelationshipsMustWork() {\n\t\tNode anotherNode = Cypher.node(\"AnotherNode\").named(\"n\");\n\t\tNode movie = Cypher.node(\"Movie\").named(\"m\");\n\n\t\tvar refersTo = movie.relationshipFrom(anotherNode, \"HAS_RELATION\");\n\t\tvar stmt = Cypher.match(movie)\n\t\t\t.where(movie.property(\"name\").isEqualTo(Cypher.literalOf(\"star\")))\n\t\t\t.returningDistinct(Cypher.listBasedOn(refersTo).returning(Cypher.name(\"n\")))\n\t\t\t.build();\n\t\tassertThat(stmt.getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (m:`Movie`) WHERE m.name = 'star' RETURN DISTINCT [(m)<-[:`HAS_RELATION`]-(n:`AnotherNode`) | n]\");\n\t}\n\n\t@Test\n\tvoid callRawCypherFollowedByWhereMustWork() {\n\t\tvar cypher = Cypher.callRawCypher(\"MATCH (n:Movie) RETURN n\")\n\t\t\t.with(Cypher.asterisk())\n\t\t\t.where(Cypher.property(\"n\", \"title\").eq(Cypher.literalOf(\"The Matrix\")))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"CALL () {MATCH (n:Movie) RETURN n} WITH * WHERE n.title = 'The Matrix' RETURN *\");\n\t}\n\n\t@Test\n\tvoid callCypherFollowedByWhereMustWork() {\n\n\t\tvar cypher = Cypher.call(Cypher.match(Cypher.node(\"Movie\").named(\"n\")).returning(Cypher.name(\"n\")).build())\n\t\t\t.with(Cypher.asterisk())\n\t\t\t.where(Cypher.property(\"n\", \"title\").eq(Cypher.literalOf(\"The Matrix\")))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher)\n\t\t\t.isEqualTo(\"CALL () {MATCH (n:`Movie`) RETURN n} WITH * WHERE n.title = 'The Matrix' RETURN *\");\n\t}\n\n\t@Test\n\tvoid callRawCypherFollowedByWhereWithoutWithMustThrowGoodException() {\n\t\tvar buildableSubquery = Cypher.callRawCypher(\"MATCH (n:Movie) RETURN n\");\n\t\tvar trueCondition = Cypher.isTrue();\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> buildableSubquery.where(trueCondition))\n\t\t\t.withMessage(\"A CALL{} clause requires to WITH before you can add further conditions\");\n\t}\n\n\t@Test // GH-1235\n\tvoid caseParsingAndRenderingShouldWork() {\n\t\tvar node = Cypher.node(\"Node\").named(\"n\");\n\t\tvar query = Cypher.match(node)\n\t\t\t.returning(Cypher.caseExpression(node.property(\"prop\"))\n\t\t\t\t.when(Cypher.literalOf(\"A\"))\n\t\t\t\t.then(Cypher.literalOf(1))\n\t\t\t\t.elseDefault(Cypher.literalOf(2)))\n\t\t\t.build();\n\n\t\tassertThat(query.getCypher()).isEqualTo(\"MATCH (n:`Node`) RETURN CASE n.prop WHEN 'A' THEN 1 ELSE 2 END\");\n\t}\n\n\t@Test // GH-1313\n\tvoid asConditionShouldWorkWithMultipleMatchesToo() {\n\t\tvar me = Cypher.node(\"User\").named(\"me\").withProperties(Cypher.mapOf(\"id\", Cypher.parameter(\"userId\")));\n\t\tvar c = Cypher.node(\"Company\").named(\"c\");\n\t\tvar myCompany = Cypher.node(\"Company\").named(\"myCompany\");\n\t\tvar isAdmin = Cypher\n\t\t\t.match(me.relationshipTo(\n\t\t\t\t\tCypher.node(\"Role\").withProperties(Cypher.mapOf(\"name\", Cypher.literalOf(\"Admin\"))), \"HAS_ROLE\"))\n\t\t\t.asCondition()\n\t\t\t.as(\"isAdmin\");\n\t\tvar stmt = Cypher.match(me)\n\t\t\t.with(me, isAdmin)\n\t\t\t.match(c)\n\t\t\t.where(isAdmin.asCondition()\n\t\t\t\t.or(Cypher.match(me.relationshipTo(myCompany, \"WORKdS_FOR\"))\n\t\t\t\t\t.match(myCompany.relationshipTo(c, \"PARENT_OF\"))\n\t\t\t\t\t.asCondition()\n\n\t\t\t\t))\n\t\t\t.returning(c)\n\t\t\t.build();\n\n\t\tvar expected = \"\"\"\n\t\t\t\tMATCH (me:User {\n\t\t\t\t  id: $userId\n\t\t\t\t})\n\t\t\t\tWITH me, EXISTS {\n\t\t\t\t  MATCH (me)-[:HAS_ROLE]->(:Role {\n\t\t\t\t    name: 'Admin'\n\t\t\t\t  })\n\t\t\t\t} AS isAdmin\n\t\t\t\tMATCH (c:Company)\n\t\t\t\tWHERE (isAdmin\n\t\t\t\t  OR EXISTS {\n\t\t\t\t    MATCH (me)-[:WORKdS_FOR]->(myCompany:Company)\n\t\t\t\t    MATCH (myCompany)-[:PARENT_OF]->(c)\n\t\t\t\t  })\n\t\t\t\tRETURN c\"\"\";\n\t\tassertThat(Renderer.getRenderer(Configuration.prettyPrinting()).render(stmt)).isEqualTo(expected);\n\t}\n\n\t@ParameterizedTest // GH-1404\n\t@EnumSource(Dialect.class)\n\tvoid labelsExpressionMustBeLeftFromAllLabelHandlers(Dialect dialect) {\n\t\tvar stmt = Cypher\n\t\t\t.match(Cypher.node(Labels.exactly(\"Purchase_orders\").or(Labels.exactly(\"Another\")))\n\t\t\t\t.named(\"po\")\n\t\t\t\t.relationshipFrom(Cypher.node(\"Material\").named(\"m\"), \"IS_PURCHASED\"))\n\t\t\t.returning(Cypher.name(\"m\"))\n\t\t\t.build();\n\t\tvar renderer = Renderer.getRenderer(Configuration.newConfig().withDialect(dialect).build());\n\t\tassertThat(renderer.render(stmt))\n\t\t\t.endsWith(\"MATCH (po:`Purchase_orders`|`Another`)<-[:`IS_PURCHASED`]-(m:`Material`) RETURN m\");\n\t}\n\n\t@Nested\n\tclass Chaining {\n\n\t\t@Test\n\t\tvoid afterYieldingCalls() {\n\t\t\tStatementBuilder.OngoingStandaloneCallWithReturnFields statementPart1 = Cypher\n\t\t\t\t.call(\"db.index.vector.queryNodes\")\n\t\t\t\t.withArgs(Cypher.parameter(\"indexName\"), Cypher.parameter(\"numberOfNearestNeighbours\"),\n\t\t\t\t\t\tCypher.parameter(\"embeddingValue\"))\n\t\t\t\t.yield(\"node\", \"score\");\n\n\t\t\t// statement 2\n\t\t\tvar node = Cypher.anyNode().named(\"node\");\n\t\t\tvar relatedNode = Cypher.anyNode().named(\"relatedNode\");\n\t\t\tvar relationship = node.relationshipTo(relatedNode, \"CONNECTED_TO\");\n\t\t\tvar statementPart2 = Cypher.match(relationship).returning(relatedNode.property(\"value\").as(\"value\"));\n\n\t\t\tvar newStatement = statementPart1.andThen(statementPart2.build()).build();\n\n\t\t\tassertThat(newStatement.getCypher()).isEqualToIgnoringWhitespace(\"\"\"\n\t\t\t\t\tCALL db.index.vector.queryNodes($indexName, $numberOfNearestNeighbours, $embeddingValue)\n\t\t\t\t\tYIELD node, score\n\t\t\t\t\tMATCH (node)-[:`CONNECTED_TO`]->(relatedNode) RETURN relatedNode.value AS value\"\"\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/LabelsTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Map;\n\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\nclass LabelsTests {\n\n\tstatic final Labels SIMPLE_OR = Labels.exactly(\"Person\").or(Labels.exactly(\"Organization\"));\n\tstatic final Labels OR_AND_NOT = SIMPLE_OR.and(Labels.exactly(\"Sanctioned\").negate());\n\n\t@Test // GH-1077\n\tvoid labelExpressionsShouldWork1() {\n\n\t\tvar node = Cypher.node(SIMPLE_OR).named(\"n\");\n\t\tvar cypher = Cypher.match(node).returning(node).build().getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\"MATCH (n:`Person`|`Organization`) RETURN n\");\n\t}\n\n\t@Test // GH-1077\n\tvoid labelExpressionsShouldWork2() {\n\n\t\tvar node = Cypher.node(OR_AND_NOT).named(\"n\");\n\t\tvar cypher = Cypher.match(node).returning(node).build().getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\"MATCH (n:(`Person`|`Organization`)&!`Sanctioned`) RETURN n\");\n\t}\n\n\t@Test\n\tvoid shouldMatchLabelsDynamically() {\n\t\tvar labels = Cypher.listOf(Cypher.literalOf(\"Person\"), Cypher.literalOf(\"Director\")).as(\"labels\");\n\t\tvar directors = Cypher.node(Cypher.allLabels(labels)).named(\"directors\");\n\t\tvar stmt = Cypher.with(labels).match(directors).returning(directors).build();\n\t\tassertThat(stmt.getCypher())\n\t\t\t.isEqualTo(\"WITH ['Person', 'Director'] AS labels MATCH (directors:$(labels)) RETURN directors\");\n\t}\n\n\t@Test\n\tvoid shouldMatchNodesDynamicallyUsingAny() {\n\t\tvar labels = Cypher.listOf(Cypher.literalOf(\"Movie\"), Cypher.literalOf(\"Actor\"));\n\t\tvar n = Cypher.node(Cypher.anyLabel(labels)).named(\"n\");\n\t\tvar stmt = Cypher.match(n).returning(n.as(\"nodes\")).build();\n\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (n:$any(['Movie', 'Actor'])) RETURN n AS nodes\");\n\t}\n\n\t@Test\n\tvoid combinationWithLabelExpressionsShouldWork() {\n\n\t\tvar labels = Cypher.anyLabel(Cypher.listOf(Cypher.literalOf(\"Movie\"), Cypher.literalOf(\"Actor\")))\n\t\t\t.and(Cypher.exactlyLabel(\"Foo\"))\n\t\t\t.or(Cypher.exactlyLabel(\"Bar\").and(Cypher.allLabels(Cypher.parameter(\"IWantToDie\"))));\n\t\tvar n = Cypher.node(labels).named(\"n\");\n\t\tvar stmt = Cypher.match(n).returning(n.as(\"nodes\")).build();\n\t\tassertThat(stmt.getCypher())\n\t\t\t.isEqualTo(\"MATCH (n:$any(['Movie', 'Actor'])&`Foo`|`Bar`&$($IWantToDie)) RETURN n AS nodes\");\n\t}\n\n\t@Test\n\tvoid dynamicConjunctionsShouldWork() {\n\n\t\tvar labels = Cypher.allLabels(Cypher.parameter(\"a\")).or(Cypher.anyLabel(Cypher.parameter(\"b\")));\n\t\tvar n = Cypher.node(labels).named(\"n\");\n\t\tvar stmt = Cypher.match(n).returning(n.as(\"nodes\")).build();\n\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (n:$($a)|$any($b)) RETURN n AS nodes\");\n\t}\n\n\t@Test\n\tvoid dynamicSetWrongType1() {\n\t\tvar labels = Cypher.allLabels(Cypher.parameter(\"a\")).or(Cypher.anyLabel(Cypher.parameter(\"b\")));\n\t\tvar n = Cypher.node(\"Whatever\").named(\"n\");\n\t\tvar match = Cypher.match(n);\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> match.set(n, labels))\n\t\t\t.withMessage(\n\t\t\t\t\t\"Only a single dynamic label expression or a set of static labels might be used in an updating clause\");\n\t}\n\n\t@Test\n\tvoid dynamicRemoveWrongType1() {\n\t\tvar labels = Cypher.allLabels(Cypher.parameter(\"a\")).or(Cypher.anyLabel(Cypher.parameter(\"b\")));\n\t\tvar n = Cypher.node(\"Whatever\").named(\"n\");\n\t\tvar match = Cypher.match(n);\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> match.remove(n, labels))\n\t\t\t.withMessage(\n\t\t\t\t\t\"Only a single dynamic label expression or a set of static labels might be used in an updating clause\");\n\t}\n\n\t@Test\n\tvoid dynamicSetWrongSelector() {\n\t\tvar labels = Cypher.anyLabel(Cypher.parameter(\"a\"));\n\t\tvar n = Cypher.node(\"Whatever\").named(\"n\");\n\t\tvar match = Cypher.match(n);\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> match.set(n, labels))\n\t\t\t.withMessage(\n\t\t\t\t\t\"Only a single dynamic label expression or a set of static labels might be used in an updating clause\");\n\t}\n\n\t@Test\n\tvoid dynamicRemoveWrongSelector() {\n\t\tvar labels = Cypher.anyLabel(Cypher.parameter(\"a\"));\n\t\tvar n = Cypher.node(\"Whatever\").named(\"n\");\n\t\tvar match = Cypher.match(n);\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> match.remove(n, labels))\n\t\t\t.withMessage(\n\t\t\t\t\t\"Only a single dynamic label expression or a set of static labels might be used in an updating clause\");\n\t}\n\n\t@Test\n\tvoid dynamicSetAll() {\n\t\tvar labels = Cypher.allLabels(Cypher.parameter(\"a\"));\n\t\tvar n = Cypher.node(\"Whatever\").named(\"n\");\n\t\tvar stmt = Cypher.match(n).set(n, labels).build();\n\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (n:`Whatever`) SET n:$($a)\");\n\t}\n\n\t@Test\n\tvoid dynamicRemoveAll() {\n\t\tvar labels = Cypher.allLabels(Cypher.parameter(\"a\"));\n\t\tvar n = Cypher.node(\"Whatever\").named(\"n\");\n\t\tvar stmt = Cypher.match(n).remove(n, labels).build();\n\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (n:`Whatever`) REMOVE n:$($a)\");\n\t}\n\n\t@Test\n\tvoid dynamicSetAllColon() {\n\t\tvar labels = Cypher.allLabels(Cypher.parameter(\"a\")).conjunctionWith(Cypher.allLabels(Cypher.parameter(\"b\")));\n\t\tvar n = Cypher.node(\"Whatever\").named(\"n\");\n\t\tvar stmt = Cypher.match(n).set(n, labels).build();\n\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (n:`Whatever`) SET n:$($a):$($b)\");\n\t}\n\n\t@Test\n\tvoid dynamicRemoveAllColon() {\n\t\tvar labels = Cypher.allLabels(Cypher.parameter(\"a\")).conjunctionWith(Cypher.allLabels(Cypher.parameter(\"b\")));\n\t\tvar n = Cypher.node(\"Whatever\").named(\"n\");\n\t\tvar stmt = Cypher.match(n).remove(n, labels).build();\n\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (n:`Whatever`) REMOVE n:$($a):$($b)\");\n\t}\n\n\t@Test\n\tvoid dynamicSetAllColonMixed() {\n\t\tvar labels = Cypher.allLabels(Cypher.parameter(\"a\"))\n\t\t\t.conjunctionWith(Cypher.allLabels(Cypher.parameter(\"b\")))\n\t\t\t.conjunctionWith(Labels.exactly(\"OhBuggerOff\"));\n\t\tvar n = Cypher.node(\"Whatever\").named(\"n\");\n\t\tvar stmt = Cypher.match(n).set(n, labels).build();\n\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (n:`Whatever`) SET n:$($a):$($b):`OhBuggerOff`\");\n\t}\n\n\t@Test\n\tvoid dynamicRemoveAllColonMixed() {\n\t\tvar labels = Cypher.allLabels(Cypher.parameter(\"a\"))\n\t\t\t.conjunctionWith(Cypher.allLabels(Cypher.parameter(\"b\")))\n\t\t\t.conjunctionWith(Labels.exactly(\"OhBuggerOff\"));\n\t\tvar n = Cypher.node(\"Whatever\").named(\"n\");\n\t\tvar stmt = Cypher.match(n).remove(n, labels).build();\n\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (n:`Whatever`) REMOVE n:$($a):$($b):`OhBuggerOff`\");\n\t}\n\n\t@Test\n\tvoid labelsAsParametersMustBeInTheCatalog() {\n\t\tvar labels = Cypher.allLabels(Cypher.parameter(\"a\", \"X\"))\n\t\t\t.conjunctionWith(Cypher.allLabels(Cypher.parameter(\"b\", \"Y\")));\n\t\tvar n = Cypher.node(\"Whatever\").named(\"n\");\n\t\tvar stmt = Cypher.match(n).remove(n, labels).build();\n\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (n:`Whatever`) REMOVE n:$($a):$($b)\");\n\t\tassertThat(stmt.getCatalog().getParameterNames()).containsExactly(\"a\", \"b\");\n\t\tassertThat(stmt.getCatalog().getParameters()).containsAllEntriesOf(Map.of(\"a\", \"X\", \"b\", \"Y\"));\n\t}\n\n\t@Nested\n\tclass AsConditions {\n\n\t\t@Test // GH-1077\n\t\tvoid labelExpressionsShouldWork1() {\n\n\t\t\tvar node = Cypher.anyNode(\"n\");\n\t\t\tvar cypher = Cypher.match(node).where(node.hasLabels(SIMPLE_OR)).returning(node).build().getCypher();\n\n\t\t\tassertThat(cypher).isEqualTo(\"MATCH (n) WHERE n:`Person`|`Organization` RETURN n\");\n\t\t}\n\n\t\t@Test // GH-1077\n\t\tvoid labelExpressionsShouldWork2() {\n\n\t\t\tvar node = Cypher.anyNode(\"n\");\n\t\t\tvar cypher = Cypher.match(node).where(node.hasLabels(OR_AND_NOT)).returning(node).build().getCypher();\n\n\t\t\tassertThat(cypher).isEqualTo(\"MATCH (n) WHERE n:(`Person`|`Organization`)&!`Sanctioned` RETURN n\");\n\t\t}\n\n\t\t@Test // GH-1141\n\t\tvoid labelExpressionsInPredicates() {\n\n\t\t\tvar movieOrFilm = Labels.exactly(\"Movie\").or(Labels.exactly(\"Film\"));\n\n\t\t\tString statement;\n\t\t\tNode a = Cypher.node(\"Person\").withProperties(\"name\", Cypher.literalOf(\"Keanu Reeves\")).named(\"a\");\n\t\t\tNode b = Cypher.anyNode(\"b\");\n\n\t\t\tstatement = Cypher.match(a)\n\t\t\t\t.returning(Cypher.listBasedOn(a.relationshipBetween(b))\n\t\t\t\t\t.where(b.hasLabels(movieOrFilm).and(b.property(\"released\").isNotNull()))\n\t\t\t\t\t.returning(b.property(\"released\"))\n\t\t\t\t\t.as(\"years\"))\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(statement).isEqualTo(\n\t\t\t\t\t\"MATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) WHERE (b:`Movie`|`Film` AND b.released IS NOT NULL) | b.released] AS years\");\n\n\t\t\tstatement = Cypher.match(a)\n\t\t\t\t.returning(Cypher.listBasedOn(a.relationshipBetween(b))\n\t\t\t\t\t.where(b.hasLabels(movieOrFilm)\n\t\t\t\t\t\t.and(b.property(\"released\").isNotNull())\n\t\t\t\t\t\t.or(b.property(\"title\").isEqualTo(Cypher.literalOf(\"The Matrix\")))\n\t\t\t\t\t\t.or(b.property(\"title\").isEqualTo(Cypher.literalOf(\"The Matrix 2\"))))\n\t\t\t\t\t.returning(b.property(\"released\"))\n\t\t\t\t\t.as(\"years\"))\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(statement).isEqualTo(\n\t\t\t\t\t\"MATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) WHERE ((b:`Movie`|`Film` AND b.released IS NOT NULL) OR b.title = 'The Matrix' OR b.title = 'The Matrix 2') | b.released] AS years\");\n\n\t\t\tstatement = Cypher.match(a)\n\t\t\t\t.returning(Cypher.listBasedOn(a.relationshipBetween(b))\n\t\t\t\t\t.where(b.hasLabels(movieOrFilm))\n\t\t\t\t\t.and(b.property(\"released\").isNotNull())\n\t\t\t\t\t.or(b.property(\"title\").isEqualTo(Cypher.literalOf(\"The Matrix\")))\n\t\t\t\t\t.or(b.property(\"title\").isEqualTo(Cypher.literalOf(\"The Matrix 2\")))\n\t\t\t\t\t.returning(b.property(\"released\"))\n\t\t\t\t\t.as(\"years\"))\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\n\t\t\tassertThat(statement).isEqualTo(\n\t\t\t\t\t\"MATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) WHERE ((b:`Movie`|`Film` AND b.released IS NOT NULL) OR b.title = 'The Matrix' OR b.title = 'The Matrix 2') | b.released] AS years\");\n\n\t\t\tstatement = Cypher.match(a)\n\t\t\t\t.returning(Cypher.listBasedOn(a.relationshipBetween(b))\n\t\t\t\t\t.where(b.hasLabels(movieOrFilm))\n\t\t\t\t\t.returning(b.property(\"released\"))\n\t\t\t\t\t.as(\"years\"))\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(statement).isEqualTo(\n\t\t\t\t\t\"MATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) WHERE b:`Movie`|`Film` | b.released] AS years\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/LoadCSVIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.net.URI;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass LoadCSVIT {\n\n\t@Test\n\tvoid loadAndCreateShouldWork() {\n\n\t\tSymbolicName l = SymbolicName.of(\"line\");\n\t\tStatement statement = Cypher.loadCSV(URI.create(\"file:///artists.csv\"))\n\t\t\t.as(l)\n\t\t\t.create(Cypher.node(\"Artist\")\n\t\t\t\t.withProperties(\"name\", Cypher.valueAt(l, 1), \"year\", Cypher.toInteger(Cypher.valueAt(l, 2))))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher()).isEqualTo(\"LOAD CSV FROM 'file:///artists.csv' AS line \"\n\t\t\t\t+ \"CREATE (:`Artist` {name: line[1], year: toInteger(line[2])})\");\n\t}\n\n\t@Test\n\tvoid loadAndCreateWithHeadersShouldWork() {\n\n\t\tSymbolicName l = SymbolicName.of(\"line\");\n\t\tStatement statement = Cypher.loadCSV(URI.create(\"file:///artists.csv\"), true)\n\t\t\t.as(l)\n\t\t\t.create(Cypher.node(\"Artist\")\n\t\t\t\t.withProperties(\"name\", Cypher.valueAt(l, 1), \"year\", Cypher.toInteger(Cypher.valueAt(l, 2))))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher()).isEqualTo(\"LOAD CSV WITH HEADERS FROM 'file:///artists.csv' AS line \"\n\t\t\t\t+ \"CREATE (:`Artist` {name: line[1], year: toInteger(line[2])})\");\n\t}\n\n\t@Test\n\tvoid loadAndCreateWithFieldTerminatorShouldWork() {\n\n\t\tSymbolicName l = SymbolicName.of(\"line\");\n\t\tStatement statement = Cypher.loadCSV(URI.create(\"file:///artists.csv\"))\n\t\t\t.as(l)\n\t\t\t.withFieldTerminator(\";\")\n\t\t\t.create(Cypher.node(\"Artist\")\n\t\t\t\t.withProperties(\"name\", Cypher.valueAt(l, 1), \"year\", Cypher.toInteger(Cypher.valueAt(l, 2))))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher()).isEqualTo(\"LOAD CSV FROM 'file:///artists.csv' AS line FIELDTERMINATOR ';' \"\n\t\t\t\t+ \"CREATE (:`Artist` {name: line[1], year: toInteger(line[2])})\");\n\t}\n\n\t@Test\n\tvoid usingPeriodCommitShouldWork() {\n\n\t\tSymbolicName l = SymbolicName.of(\"line\");\n\t\tStatement statement = Cypher.usingPeriodicCommit()\n\t\t\t.loadCSV(URI.create(\"file:///artists.csv\"))\n\t\t\t.as(l)\n\t\t\t.create(Cypher.node(\"Artist\")\n\t\t\t\t.withProperties(\"name\", Cypher.valueAt(l, 1), \"year\", Cypher.toInteger(Cypher.valueAt(l, 2))))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher()).isEqualTo(\"USING PERIODIC COMMIT LOAD CSV FROM 'file:///artists.csv' AS line \"\n\t\t\t\t+ \"CREATE (:`Artist` {name: line[1], year: toInteger(line[2])})\");\n\t}\n\n\t@Test\n\tvoid usingPeriodCommitWithRateShouldWork() {\n\n\t\tSymbolicName l = SymbolicName.of(\"line\");\n\t\tStatement statement = Cypher.usingPeriodicCommit(500)\n\t\t\t.loadCSV(URI.create(\"file:///artists.csv\"))\n\t\t\t.as(l)\n\t\t\t.create(Cypher.node(\"Artist\")\n\t\t\t\t.withProperties(\"name\", Cypher.valueAt(l, 1), \"year\", Cypher.toInteger(Cypher.valueAt(l, 2))))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(\"USING PERIODIC COMMIT 500 LOAD CSV FROM 'file:///artists.csv' AS line \"\n\t\t\t\t\t+ \"CREATE (:`Artist` {name: line[1], year: toInteger(line[2])})\");\n\t}\n\n\t@Test\n\tvoid usingLinenumberShouldWork() {\n\n\t\tSymbolicName l = SymbolicName.of(\"line\");\n\t\tStatement statement = Cypher.loadCSV(URI.create(\"file:///artists.csv\"))\n\t\t\t.as(l)\n\t\t\t.returning(Cypher.linenumber().as(\"number\"), l)\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(\"LOAD CSV FROM 'file:///artists.csv' AS line RETURN linenumber() AS number, line\");\n\t}\n\n\t@Test\n\tvoid usingFileShouldWork() {\n\n\t\tSymbolicName l = SymbolicName.of(\"line\");\n\t\tStatement statement = Cypher.loadCSV(URI.create(\"file:///artists.csv\"))\n\t\t\t.as(l)\n\t\t\t.returning(Cypher.file().as(\"path\"))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(\"LOAD CSV FROM 'file:///artists.csv' AS line RETURN file() AS path\");\n\t}\n\n\t@Test\n\tvoid allOptionsCombinedShouldWork() {\n\n\t\tSymbolicName l = SymbolicName.of(\"line\");\n\t\tStatement statement = Cypher.usingPeriodicCommit(42)\n\t\t\t.loadCSV(URI.create(\"file:///artists.csv\"), true)\n\t\t\t.as(l)\n\t\t\t.withFieldTerminator(\";\")\n\t\t\t.create(Cypher.node(\"Artist\")\n\t\t\t\t.withProperties(\"name\", Cypher.valueAt(l, 1), \"year\", Cypher.toInteger(Cypher.valueAt(l, 2)), \"source\",\n\t\t\t\t\t\tCypher.file().concat(Cypher.literalOf(\"@\")).concat(Cypher.linenumber())))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher()).isEqualTo(\n\t\t\t\t\"USING PERIODIC COMMIT 42 LOAD CSV WITH HEADERS FROM 'file:///artists.csv' AS line FIELDTERMINATOR ';' \"\n\t\t\t\t\t\t+ \"CREATE (:`Artist` {name: line[1], year: toInteger(line[2]), source: ((file() + '@') + linenumber())})\");\n\t}\n\n\t@Test\n\tvoid devGuideExample1() {\n\n\t\tSymbolicName row = SymbolicName.of(\"row\");\n\t\tProperty id = row.property(\"Id\");\n\t\tStatement statement = Cypher.loadCSV(URI.create(\"file:///companies.csv\"), true)\n\t\t\t.as(row)\n\t\t\t.with(row)\n\t\t\t.where(id.isNotNull())\n\t\t\t.merge(Cypher.node(\"Company\").named(\"c\").withProperties(\"companyId\", id))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher()).isEqualTo(\"LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row \"\n\t\t\t\t+ \"WITH row WHERE row.Id IS NOT NULL \" + \"MERGE (c:`Company` {companyId: row.Id})\");\n\t}\n\n\t@Test\n\tvoid devGuideExample2() {\n\n\t\tSymbolicName row = SymbolicName.of(\"row\");\n\t\tProperty id = row.property(\"Id\");\n\t\tStatement statement = Cypher.loadCSV(URI.create(\"file:///companies.csv\"), true)\n\t\t\t.as(row)\n\t\t\t.merge(Cypher.node(\"Company\")\n\t\t\t\t.named(\"c\")\n\t\t\t\t.withProperties(\"companyId\", id, \"hqLocation\",\n\t\t\t\t\t\tCypher.coalesce(row.property(\"Location\"), Cypher.literalOf(\"Unknown\"))))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher()).isEqualTo(\"LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row \"\n\t\t\t\t+ \"MERGE (c:`Company` {companyId: row.Id, hqLocation: coalesce(row.Location, 'Unknown')})\");\n\t}\n\n\t@Test\n\tvoid devGuideExample3() {\n\n\t\tSymbolicName row = SymbolicName.of(\"row\");\n\t\tProperty id = row.property(\"Id\");\n\t\tProperty email = row.property(\"Email\");\n\n\t\tNode node = Cypher.node(\"Company\").named(\"c\").withProperties(\"companyId\", id);\n\n\t\tStatement statement = Cypher.loadCSV(URI.create(\"file:///companies.csv\"), true)\n\t\t\t.as(row)\n\t\t\t.merge(node)\n\t\t\t.set(node.property(\"emailAddress\")\n\t\t\t\t.to(Cypher.caseExpression(Cypher.trim(email))\n\t\t\t\t\t.when(Cypher.literalOf(\"\"))\n\t\t\t\t\t.then(NullLiteral.INSTANCE)\n\t\t\t\t\t.elseDefault(email)))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher()).isEqualTo(\"LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row \"\n\t\t\t\t+ \"MERGE (c:`Company` {companyId: row.Id}) \"\n\t\t\t\t+ \"SET c.emailAddress = CASE trim(row.Email) WHEN '' THEN NULL ELSE row.Email END\");\n\t}\n\n\t@Test\n\tvoid devGuideExample4() {\n\n\t\tSymbolicName row = SymbolicName.of(\"row\");\n\t\tProperty id = row.property(\"Id\");\n\t\tProperty email = row.property(\"Email\");\n\n\t\tSymbolicName skill = Cypher.name(\"skill\");\n\n\t\tNode e = Cypher.node(\"Employee\").named(\"e\").withProperties(\"employeeId\", id, \"email\", email);\n\t\tNode s = Cypher.node(\"Skill\").named(\"s\").withProperties(\"name\", skill);\n\n\t\tStatement statement = Cypher.loadCSV(URI.create(\"file:///employees.csv\"), true)\n\t\t\t.as(row)\n\t\t\t.merge(e)\n\t\t\t.with(e, row)\n\t\t\t.unwind(Cypher.split(row.property(\"Skills\"), Cypher.literalOf(\":\")))\n\t\t\t.as(skill)\n\t\t\t.merge(s)\n\t\t\t.merge(e.relationshipTo(s, \"HAS_EXPERIENCE\").named(\"r\"))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher()).isEqualTo(\"LOAD CSV WITH HEADERS FROM 'file:///employees.csv' AS row \"\n\t\t\t\t+ \"MERGE (e:`Employee` {employeeId: row.Id, email: row.Email}) \" + \"WITH e, row \"\n\t\t\t\t+ \"UNWIND split(row.Skills, ':') AS skill \" + \"MERGE (s:`Skill` {name: skill}) \"\n\t\t\t\t+ \"MERGE (e)-[r:`HAS_EXPERIENCE`]->(s)\");\n\t}\n\n\t@Test\n\tvoid inQuery() {\n\n\t\tSymbolicName row = SymbolicName.of(\"row\");\n\t\tNode userNode = Cypher.node(\"User\").named(\"u\").withProperties(\"name\", Cypher.literalOf(\"Michael\"));\n\n\t\tStatement statement = Cypher.match(userNode)\n\t\t\t.with(userNode)\n\t\t\t.orderBy(userNode.property(\"name\"))\n\t\t\t.ascending()\n\t\t\t.loadCSV(URI.create(\"file:///bikes.csv\"))\n\t\t\t.as(row)\n\t\t\t.merge(userNode.relationshipTo(Cypher.node(\"Bike\").withProperties(\"name\", Cypher.valueAt(row, 0)), \"OWNS\"))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (u:`User` {name: 'Michael'}) WITH u ORDER BY u.name ASC LOAD CSV FROM 'file:///bikes.csv' AS row MERGE (u)-[:`OWNS`]->(:`Bike` {name: row[0]})\");\n\t}\n\n\t@Test\n\tvoid finish() {\n\t\tSymbolicName row = SymbolicName.of(\"row\");\n\t\tNode userNode = Cypher.node(\"User\").named(\"u\").withProperties(\"name\", Cypher.literalOf(\"Michael\"));\n\n\t\tStatement statement = Cypher.match(userNode)\n\t\t\t.with(userNode)\n\t\t\t.orderBy(userNode.property(\"name\"))\n\t\t\t.ascending()\n\t\t\t.loadCSV(URI.create(\"file:///bikes.csv\"))\n\t\t\t.as(row)\n\t\t\t.finish()\n\t\t\t.build();\n\n\t\tassertThat(statement.getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (u:`User` {name: 'Michael'}) WITH u ORDER BY u.name ASC LOAD CSV FROM 'file:///bikes.csv' AS row FINISH\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/PackageAndAPIStructureTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport com.tngtech.archunit.base.DescribedPredicate;\nimport com.tngtech.archunit.core.domain.JavaClass;\nimport com.tngtech.archunit.core.domain.JavaClasses;\nimport com.tngtech.archunit.core.domain.JavaModifier;\nimport com.tngtech.archunit.core.importer.ClassFileImporter;\nimport com.tngtech.archunit.core.importer.ImportOption;\nimport com.tngtech.archunit.lang.ArchRule;\nimport com.tngtech.archunit.lang.conditions.ArchConditions;\nimport org.apiguardian.api.API;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.DisplayName;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.TestInstance;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.ValueSource;\nimport org.neo4j.cypherdsl.core.internal.SchemaNamesBridge;\nimport org.neo4j.cypherdsl.support.schema_name.SchemaNames;\n\nimport static com.tngtech.archunit.base.DescribedPredicate.not;\nimport static com.tngtech.archunit.core.domain.JavaAccess.Predicates.targetOwner;\nimport static com.tngtech.archunit.core.domain.JavaClass.Predicates.assignableFrom;\nimport static com.tngtech.archunit.core.domain.JavaClass.Predicates.assignableTo;\nimport static com.tngtech.archunit.core.domain.JavaClass.Predicates.resideInAPackage;\nimport static com.tngtech.archunit.core.domain.properties.HasModifiers.Predicates.modifier;\nimport static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;\nimport static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.fields;\nimport static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;\n\n/**\n * @author Michael J. Simons\n */\n@TestInstance(TestInstance.Lifecycle.PER_CLASS)\nclass PackageAndAPIStructureTests {\n\n\tprivate JavaClasses coreClasses;\n\n\t// tag::arch-rules.naming:TypeNameMustBeginWithGroupId[]\n\t@BeforeAll\n\tvoid importCorePackage() {\n\t\tthis.coreClasses = new ClassFileImporter().withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)\n\t\t\t.importPackages(\"org.neo4j.cypherdsl.core..\");\n\t}\n\t// end::arch-rules.naming:TypeNameMustBeginWithGroupId[]\n\n\t@DisplayName(\"API Guardian annotations must not be used on fields\")\n\t// tag::arch-rules.api:api-guardian-usage[]\n\t@Test\n\tvoid apiGuardian() {\n\t\tArchRule rule = fields().should().notBeAnnotatedWith(API.class);\n\t\trule.check(this.coreClasses);\n\t}\n\t// end::arch-rules.api:api-guardian-usage[]\n\n\t@DisplayName(\"Non abstract, public classes that are only part of internal API must be final and not reside in core\")\n\t// tag::arch-rules.api:internal[]\n\t@Test\n\tvoid internalPublicClassesMustBeFinal() {\n\t\tArchRule rule = classes().that()\n\t\t\t.areAnnotatedWith(API.class)\n\t\t\t.and()\n\t\t\t.arePublic()\n\t\t\t.and()\n\t\t\t.areTopLevelClasses()\n\t\t\t.and(not(modifier(JavaModifier.ABSTRACT)))\n\t\t\t.and(new DescribedPredicate<>(\"Is internal API\") {\n\t\t\t\t@Override\n\t\t\t\tpublic boolean test(JavaClass input) {\n\t\t\t\t\tAPI.Status status = input.getAnnotationOfType(API.class).status();\n\t\t\t\t\treturn \"INTERNAL\".equals(status.name());\n\t\t\t\t}\n\t\t\t})\n\t\t\t.should()\n\t\t\t.haveModifier(JavaModifier.FINAL)\n\t\t\t.andShould(ArchConditions.not(ArchConditions.resideInAPackage(\"..core\")));\n\t\trule.check(this.coreClasses);\n\t}\n\t// end::arch-rules.api:internal[]\n\n\t@DisplayName(\"The Cypher-DSL core package must not depend on the rendering infrastructure\")\n\t// tag::arch-rules.structure:core-must-not-depend-on-renderer[]\n\t@Test\n\tvoid coreMostNotDependOnRendering() {\n\t\tArchRule rule = noClasses().that()\n\t\t\t.resideInAPackage(\"..core\")\n\t\t\t.and(not(assignableFrom(AbstractStatement.class).or(assignableFrom(RendererBridge.class))))\n\t\t\t.should()\n\t\t\t.dependOnClassesThat(resideInAPackage(\"..renderer..\"));\n\t\trule.check(this.coreClasses);\n\t}\n\t// end::arch-rules.structure:core-must-not-depend-on-renderer[]\n\n\t@DisplayName(\"Supporting packages must not depend on anything from the outside\")\n\t// tag::arch-rules.structure:supporting-packages-are-dependency-free[]\n\t@ParameterizedTest\n\t@ValueSource(strings = { \"..core.ast\", \"..core.utils\" })\n\tvoid independentSupportPackages(String supportPackage) {\n\t\tArchRule rule = noClasses().that()\n\t\t\t.resideInAPackage(supportPackage)\n\t\t\t.should()\n\t\t\t.dependOnClassesThat(resideInAPackage(\"..core..\").and(not(resideInAPackage(supportPackage))));\n\t\trule.check(this.coreClasses);\n\t}\n\t// end::arch-rules.structure:supporting-packages-are-dependency-free[]\n\n\t@Test\n\tvoid allCallsToSchemaNamesMustUseTheBridge() {\n\n\t\tArchRule rule = noClasses().that()\n\t\t\t.areNotAssignableFrom(SchemaNamesBridge.class)\n\t\t\t.should()\n\t\t\t.callCodeUnitWhere(targetOwner(assignableTo(SchemaNames.class)));\n\t\trule.check(this.coreClasses);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/ParameterIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatExceptionOfType;\n\n/**\n * @author Andreas Berger\n * @author Michael J. Simons\n */\nclass ParameterIT {\n\n\tprivate static final Node userNode = Cypher.node(\"User\").named(\"u\");\n\n\tprivate static Stream<Arguments> conflictingParameters() {\n\t\treturn Stream.of(\"x\", null)\n\t\t\t.flatMap(v -> Stream.of(\n\t\t\t\t\tArguments.of(Cypher.match(userNode)\n\t\t\t\t\t\t.set(userNode.property(\"name\").to(Cypher.parameter(\"param\").withValue(v)),\n\t\t\t\t\t\t\t\tuserNode.property(\"firstName\").to(Cypher.parameter(\"param\")))\n\t\t\t\t\t\t.returning(userNode)\n\t\t\t\t\t\t.build()),\n\t\t\t\t\tArguments.of(Cypher.match(userNode)\n\t\t\t\t\t\t.set(userNode.property(\"firstName\").to(Cypher.parameter(\"param\")),\n\t\t\t\t\t\t\t\tuserNode.property(\"name\").to(Cypher.parameter(\"param\").withValue(v)))\n\t\t\t\t\t\t.returning(userNode)\n\t\t\t\t\t\t.build())));\n\t}\n\n\t@Test\n\tvoid shouldCollectParameters() {\n\t\tStatement statement = Cypher.match(userNode)\n\t\t\t.where(userNode.property(\"name\").isEqualTo(Cypher.parameter(\"name\", \"Neo\")))\n\t\t\t.returning(userNode)\n\t\t\t.limit(Cypher.parameter(\"param\").withValue(5))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCatalog().getParameters()).containsEntry(\"param\", 5).containsEntry(\"name\", \"Neo\");\n\n\t\tassertThat(statement.getCatalog().getParameterNames()).containsExactlyInAnyOrder(\"param\", \"name\");\n\t}\n\n\t@Test\n\tvoid shouldCollectParametersOnlyOnce() {\n\t\tStatement statement = Cypher.match(userNode)\n\t\t\t.where(userNode.property(\"cnt\").isEqualTo(Cypher.parameter(\"param\", 5)))\n\t\t\t.and(Cypher.anonParameter(\"y\").isTrue())\n\t\t\t.or(Cypher.anonParameter(\"y\").isFalse())\n\t\t\t.and(Cypher.anonParameter(\"z\").isTrue())\n\t\t\t.or(Cypher.anonParameter(\"z\").isFalse())\n\t\t\t.returning(userNode)\n\t\t\t.limit(Cypher.parameter(\"param\").withValue(5))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCatalog().getParameters()).containsOnly(Map.entry(\"param\", 5),\n\t\t\t\tMap.entry(\"pcdsl01\", \"y\"), Map.entry(\"pcdsl02\", \"z\"));\n\t}\n\n\t@Test\n\tvoid equalsShouldWork() {\n\t\tvar p1 = Cypher.anonParameter(\"y\");\n\t\tvar p2 = Cypher.anonParameter(\"y\");\n\t\tvar p3 = Cypher.anonParameter(\"z\");\n\t\tvar p4 = Cypher.parameter(\"pcdsl01\", \"z\");\n\t\tassertThat(p1).isEqualTo(p1);\n\t\tassertThat(p1).isEqualTo(p2);\n\t\tassertThat(p1).isNotEqualTo(p3);\n\t\tassertThat(p1).isNotEqualTo(p4);\n\t}\n\n\t@Test\n\tvoid shouldDealWithNullValues() {\n\t\tStatement statement = Cypher.match(userNode)\n\t\t\t.set(userNode.property(\"name\").to(Cypher.parameter(\"param\").withValue(null)))\n\t\t\t.returning(userNode)\n\t\t\t.build();\n\n\t\tassertThat(Renderer.getDefaultRenderer().render(statement))\n\t\t\t.isEqualTo(\"MATCH (u:`User`) SET u.name = $param RETURN u\");\n\t\tassertThat(statement.getCatalog().getParameters()).containsEntry(\"param\", null);\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource(\"conflictingParameters\")\n\tvoid shouldFailWithNoValueVsNull(Statement statement) {\n\n\t\tassertThatExceptionOfType(ConflictingParametersException.class).isThrownBy(statement::getCatalog);\n\t}\n\n\t@Test\n\tvoid shouldNotFailWithSameNameAndMultipleNulLValues() {\n\n\t\tStatement statement = Cypher.match(userNode)\n\t\t\t.set(userNode.property(\"name\").to(Cypher.parameter(\"param\").withValue(null)),\n\t\t\t\t\tuserNode.property(\"firstName\").to(Cypher.parameter(\"param\").withValue(null)))\n\t\t\t.returning(userNode)\n\t\t\t.build();\n\n\t\tassertThat(Renderer.getDefaultRenderer().render(statement))\n\t\t\t.isEqualTo(\"MATCH (u:`User`) SET u.name = $param, u.firstName = $param RETURN u\");\n\t\tassertThat(statement.getCatalog().getParameters()).containsEntry(\"param\", null);\n\t}\n\n\t@Test\n\tvoid shouldNotFailWithSameNameAndNoValue() {\n\n\t\tStatement statement = Cypher.match(userNode)\n\t\t\t.set(userNode.property(\"name\").to(Cypher.parameter(\"param\")),\n\t\t\t\t\tuserNode.property(\"firstName\").to(Cypher.parameter(\"param\")))\n\t\t\t.returning(userNode)\n\t\t\t.build();\n\n\t\tassertThat(Renderer.getDefaultRenderer().render(statement))\n\t\t\t.isEqualTo(\"MATCH (u:`User`) SET u.name = $param, u.firstName = $param RETURN u\");\n\t\tassertThat(statement.getCatalog().getParameters()).isEmpty();\n\t\tassertThat(statement.getCatalog().getParameterNames()).containsExactlyInAnyOrder(\"param\");\n\t}\n\n\t@Test\n\tvoid shouldFailOnDifferentBoundValues() {\n\t\tStatement statement = Cypher.match(userNode)\n\t\t\t.returning(userNode)\n\t\t\t.skip(Cypher.parameter(\"param\").withValue(1))\n\t\t\t.limit(Cypher.parameter(\"param\").withValue(5))\n\t\t\t.build();\n\n\t\tassertThatExceptionOfType(ConflictingParametersException.class).isThrownBy(statement::getCatalog)\n\t\t\t.satisfies(e -> {\n\t\t\t\tMap<String, Set<Object>> erroneousParameters = e.getErroneousParameters();\n\t\t\t\tassertThat(erroneousParameters).containsKey(\"param\");\n\t\t\t\tSet<Object> values = erroneousParameters.get(\"param\");\n\t\t\t\tassertThat(values).containsExactlyInAnyOrder(1, 5);\n\t\t\t});\n\t}\n\n\t@SuppressWarnings(\"deprecation\")\n\t@Test\n\tvoid shouldFailOnDifferentBoundValuesWhenSameValueIsUsedTwice() {\n\t\tStatement statement = Cypher.match(userNode)\n\t\t\t.where(userNode.internalId().isEqualTo(Cypher.parameter(\"param\").withValue(5)))\n\t\t\t.returning(userNode)\n\t\t\t.skip(Cypher.parameter(\"param\").withValue(1))\n\t\t\t.limit(Cypher.parameter(\"param\").withValue(1))\n\t\t\t.build();\n\n\t\tassertThatExceptionOfType(ConflictingParametersException.class).isThrownBy(statement::getCatalog)\n\t\t\t.satisfies(e -> {\n\t\t\t\tMap<String, Set<Object>> erroneousParameters = e.getErroneousParameters();\n\t\t\t\tassertThat(erroneousParameters).containsKey(\"param\");\n\t\t\t\tSet<Object> values = erroneousParameters.get(\"param\");\n\t\t\t\tassertThat(values).containsExactlyInAnyOrder(1, 5);\n\t\t\t});\n\t}\n\n\t@Test\n\tvoid shouldWorkWithUnions() {\n\n\t\tfinal Node bikeNode = Cypher.node(\"Bike\").named(\"b\");\n\n\t\tStatement statement1 = Cypher.match(bikeNode)\n\t\t\t.where(bikeNode.property(\"a\").isEqualTo(Cypher.parameter(\"p1\").withValue(\"A\")))\n\t\t\t.returning(bikeNode)\n\t\t\t.build();\n\t\tassertThat(statement1.getCatalog().getParameters()).containsEntry(\"p1\", \"A\");\n\n\t\tStatement statement2 = Cypher.match(bikeNode)\n\t\t\t.where(bikeNode.property(\"b\").isEqualTo(Cypher.parameter(\"p2\").withValue(\"B\")))\n\t\t\t.returning(bikeNode)\n\t\t\t.build();\n\t\tassertThat(statement2.getCatalog().getParameters()).containsEntry(\"p2\", \"B\");\n\n\t\tStatement statement3 = Cypher.match(bikeNode)\n\t\t\t.where(bikeNode.property(\"c\").isEqualTo(Cypher.parameter(\"p3\").withValue(\"C\")))\n\t\t\t.returning(bikeNode)\n\t\t\t.build();\n\t\tassertThat(statement3.getCatalog().getParameters()).containsEntry(\"p3\", \"C\");\n\n\t\tStatement statement = Cypher.union(statement1, statement2, statement3);\n\n\t\tassertThat(Renderer.getDefaultRenderer().render(statement)).isEqualTo(\n\t\t\t\t\"MATCH (b:`Bike`) WHERE b.a = $p1 RETURN b UNION MATCH (b:`Bike`) WHERE b.b = $p2 RETURN b UNION MATCH (b:`Bike`) WHERE b.c = $p3 RETURN b\");\n\n\t\tMap<String, Object> expectedParams = Map.of(\"p1\", \"A\", \"p2\", \"B\", \"p3\", \"C\");\n\t\tassertThat(statement.getCatalog().getParameters()).containsAllEntriesOf(expectedParams);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/ParameterLiteralTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nclass ParameterLiteralTests {\n\n\t@Test\n\tvoid anonParametersAreUnsupported() {\n\t\tvar anonParameter = Cypher.anonParameter(\"whatever\");\n\t\tAssertions.assertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> ParameterLiteral.of(anonParameter))\n\t\t\t.withMessage(\"Anonymous parameters cannot be used as parameter literals\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/PredicatesTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.lang.reflect.Method;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\nimport static org.mockito.Mockito.mock;\n\n/**\n * @author Michael J. Simons\n */\nclass PredicatesTests {\n\n\tprivate static final String FUNCTION_NAME_FIELD = \"functionName\";\n\n\tprivate static Stream<Arguments> predicatesToTest() {\n\t\treturn Stream.of(Arguments.of(\"exists\", Property.class), Arguments.of(\"exists\", RelationshipPattern.class));\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource(\"predicatesToTest\")\n\tvoid preconditionsShouldBeAsserted(String predicateName, Class<?> argumentType) {\n\n\t\t@SuppressWarnings(\"deprecation\")\n\t\tMethod method = TestUtils.findMethod(Predicates.class, predicateName, argumentType);\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> TestUtils.invokeMethod(method, null, (Expression) null))\n\t\t\t.withMessageEndingWith(\"is required.\");\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource(\"predicatesToTest\")\n\tvoid functionInvocationsShouldBeCreated(String functionName, Class<?> argumentType) {\n\n\t\t@SuppressWarnings(\"deprecation\")\n\t\tMethod method = TestUtils.findMethod(Predicates.class, functionName, argumentType);\n\t\tBooleanFunctionCondition invocation = (BooleanFunctionCondition) TestUtils.invokeMethod(method, null,\n\t\t\t\tmock(argumentType));\n\t\tassertThat(invocation).extracting(\"delegate\").hasFieldOrPropertyWithValue(FUNCTION_NAME_FIELD, functionName);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/ProcedureCallsIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.Arrays;\n\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n */\nclass ProcedureCallsIT {\n\n\tprivate static final Renderer cypherRenderer = Renderer.getDefaultRenderer();\n\n\t@Test\n\tvoid simple() {\n\n\t\tString expected = \"CALL db.labels()\";\n\n\t\tStatement call = Cypher.call(\"db\", \"labels\").build();\n\t\tassertThat(cypherRenderer.render(call)).isEqualTo(expected);\n\n\t\tcall = Cypher.call(\"db.labels\").build();\n\t\tassertThat(cypherRenderer.render(call)).isEqualTo(expected);\n\t}\n\n\t@Test\n\tvoid simpleBasedOnStringCollection() {\n\n\t\tString expected = \"CALL db.labels()\";\n\n\t\tString[] prodecureCallPart = { \"db\", \"labels\" };\n\t\tStatement call = Cypher.call(Arrays.asList(prodecureCallPart)).build();\n\t\tassertThat(cypherRenderer.render(call)).isEqualTo(expected);\n\n\t\tassertThat(call.getCatalog().getIdentifiableExpressions()).isEmpty();\n\t}\n\n\t@Test\n\tvoid shouldGenerateStatementsOfCorrectType() {\n\n\t\tStatement call = Cypher.call(\"db\", \"labels\").build();\n\t\tassertThat(call).isInstanceOf(ProcedureCall.class)\n\t\t\t.isInstanceOf(Statement.class)\n\t\t\t.isNotInstanceOf(ResultStatement.class);\n\n\t\tcall = Cypher.call(\"db\", \"labels\").yield(\"label\").build();\n\t\tassertThat(call).isInstanceOf(ProcedureCall.class)\n\t\t\t.isInstanceOf(Statement.class)\n\t\t\t.isInstanceOf(ResultStatement.class);\n\n\t\tcall = Cypher.call(\"db\", \"labels\").yield(\"label\").returning(\"label\").build();\n\t\tassertThat(call).isInstanceOf(Statement.SingleQuery.class)\n\t\t\t.isInstanceOf(Statement.class)\n\t\t\t.isInstanceOf(ResultStatement.class);\n\t}\n\n\t@Test\n\tvoid withArgs() {\n\n\t\tStatement call = Cypher.call(\"dbms.security.createUser\")\n\t\t\t.withArgs(Cypher.literalOf(\"johnsmith\"), Cypher.literalOf(\"h6u4%kr\"), BooleanLiteral.FALSE)\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(call))\n\t\t\t.isEqualTo(\"CALL dbms.security.createUser('johnsmith', 'h6u4%kr', false)\");\n\t}\n\n\t@Test\n\tvoid yieldItems() {\n\n\t\tString expected = \"CALL dbms.procedures() YIELD name, signature\";\n\n\t\tStatement call = Cypher.call(\"dbms.procedures\").yield(\"name\", \"signature\").build();\n\t\tassertThat(cypherRenderer.render(call)).isEqualTo(expected);\n\n\t\tcall = Cypher.call(\"dbms.procedures\").yield(Cypher.name(\"name\"), Cypher.name(\"signature\")).build();\n\t\tassertThat(cypherRenderer.render(call)).isEqualTo(expected);\n\n\t\tassertThat(call.getCatalog().getIdentifiableExpressions()).containsExactlyInAnyOrder(Cypher.name(\"name\"),\n\t\t\t\tCypher.name(\"signature\"));\n\t}\n\n\t@Test\n\tvoid yieldItemsRenamed() {\n\n\t\tStatement call = Cypher.call(\"db.propertyKeys\").yield(Cypher.name(\"propertyKey\").as(\"prop\")).build();\n\t\tassertThat(cypherRenderer.render(call)).isEqualTo(\"CALL db.propertyKeys() YIELD propertyKey AS prop\");\n\t}\n\n\t@Test\n\tvoid withArgsAndYield() {\n\n\t\tStatement call = Cypher.call(\"dbms.listConfig\").withArgs(Cypher.literalOf(\"browser\")).yield(\"name\").build();\n\t\tassertThat(cypherRenderer.render(call)).isEqualTo(\"CALL dbms.listConfig('browser') YIELD name\");\n\t}\n\n\t@Test\n\tvoid where() {\n\n\t\tSymbolicName name = Cypher.name(\"name\");\n\t\tStatement call = Cypher.call(\"dbms.listConfig\")\n\t\t\t.withArgs(Cypher.literalOf(\"browser\"))\n\t\t\t.yield(name)\n\t\t\t.where(name.matches(\"browser\\\\.allow.*\"))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(call))\n\t\t\t.isEqualTo(\"CALL dbms.listConfig('browser') YIELD name WHERE name =~ 'browser\\\\\\\\.allow.*' RETURN *\");\n\t}\n\n\t@Test\n\tvoid returning() {\n\n\t\tSymbolicName label = Cypher.name(\"label\");\n\t\tStatement call = Cypher.call(\"db.labels\").yield(label).returning(Cypher.count(label).as(\"numLabels\")).build();\n\t\tassertThat(cypherRenderer.render(call))\n\t\t\t.isEqualTo(\"CALL db.labels() YIELD label RETURN count(label) AS numLabels\");\n\t}\n\n\t@Test\n\tvoid withThanReturning() {\n\n\t\tSymbolicName label = Cypher.name(\"label\");\n\t\tStatement call = Cypher.call(\"db.labels\")\n\t\t\t.yield(label)\n\t\t\t.with(label)\n\t\t\t.returning(Cypher.count(label).as(\"numLabels\"))\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(call))\n\t\t\t.isEqualTo(\"CALL db.labels() YIELD label WITH label RETURN count(label) AS numLabels\");\n\n\t\tassertThat(call.getCatalog().getIdentifiableExpressions()).hasSize(1).first().satisfies(i -> {\n\t\t\tassertThat(i).isInstanceOf(AliasedExpression.class);\n\t\t\tassertThat(((AliasedExpression) i).getAlias()).isEqualTo(\"numLabels\");\n\t\t});\n\t}\n\n\t@Test\n\tvoid withThanReturningInQuery() {\n\n\t\tSymbolicName label = Cypher.name(\"label\");\n\t\tStatement call = Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t.with(\"n\")\n\t\t\t.call(\"db.labels\")\n\t\t\t.yield(label)\n\t\t\t.with(label)\n\t\t\t.returning(Cypher.count(label).as(\"numLabels\"))\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(call))\n\t\t\t.isEqualTo(\"MATCH (n) WITH n CALL db.labels() YIELD label WITH label RETURN count(label) AS numLabels\");\n\t}\n\n\t@Test // GH-101\n\tvoid shouldBeUsableAsExpression() {\n\n\t\tNode p = Cypher.node(\"Person\").named(\"p\");\n\t\tStatement stmt = Cypher\n\t\t\t.merge(p.withProperties(Cypher.mapOf(\"id\", Cypher.call(\"apoc.create.uuid\").asFunction())))\n\t\t\t.set(p.property(\"firstName\").to(Cypher.literalOf(\"Michael\")),\n\t\t\t\t\tp.property(\"surname\").to(Cypher.literalOf(\"Hunger\")))\n\t\t\t.returning(p)\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(stmt)).isEqualTo(\n\t\t\t\t\"MERGE (p:`Person` {id: apoc.create.uuid()}) SET p.firstName = 'Michael', p.surname = 'Hunger' RETURN p\");\n\t}\n\n\t@Test\n\tvoid dynamicDistinct() {\n\n\t\tassertThat(cypherRenderer\n\t\t\t.render(Cypher.returning(Cypher.call(\"aVg\").withArgs(Cypher.literalOf(1)).asFunction(true)).build()))\n\t\t\t.isEqualTo(\"RETURN aVg(DISTINCT 1)\");\n\t}\n\n\t@Test\n\tvoid dynamicDistinctUnsupported() {\n\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> Cypher.call(\"foobar\").withArgs(Cypher.literalOf(1)).asFunction(true))\n\t\t\t.withMessage(\"The distinct operator can only be applied within aggregate functions.\");\n\t}\n\n\t@Test // GH-101\n\tvoid shouldBeUsableWithParametersAsExpression() {\n\n\t\tNode p = Cypher.node(\"Person\").named(\"p\");\n\t\tStatement stmt = Cypher\n\t\t\t.merge(p.withProperties(Cypher.mapOf(\"id\", Cypher.call(\"apoc.create.uuid\").asFunction())))\n\t\t\t.set(p.property(\"surname\").to(Cypher.literalOf(\"Simons\")))\n\t\t\t.with(p)\n\t\t\t.call(\"apoc.create.setProperty\")\n\t\t\t.withArgs(p.getRequiredSymbolicName(),\n\t\t\t\t\tCypher.call(\"apoc.text.camelCase\").withArgs(Cypher.literalOf(\"first name\")).asFunction(),\n\t\t\t\t\tCypher.literalOf(\"Michael\"))\n\t\t\t.yield(\"node\")\n\t\t\t.returning(\"node\")\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(stmt)).isEqualTo(\n\t\t\t\t\"MERGE (p:`Person` {id: apoc.create.uuid()}) SET p.surname = 'Simons' WITH p CALL apoc.create.setProperty(p, apoc.text.camelCase('first name'), 'Michael') YIELD node RETURN node\");\n\t}\n\n\t@Nested\n\tclass MultipartQueries {\n\n\t\t@Test\n\t\tvoid unrelated() {\n\n\t\t\tSymbolicName name = Cypher.name(\"name\");\n\t\t\tStatement call = Cypher.call(\"dbms.listConfig\")\n\t\t\t\t.withArgs(Cypher.literalOf(\"browser\"))\n\t\t\t\t.yield(name)\n\t\t\t\t.where(name.matches(\"browser\\\\.allow.*\"))\n\t\t\t\t.match(Cypher.anyNode(\"n\"))\n\t\t\t\t.with(name)\n\t\t\t\t.returning(Cypher.asterisk())\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(call)).isEqualTo(\n\t\t\t\t\t\"CALL dbms.listConfig('browser') YIELD name WHERE name =~ 'browser\\\\\\\\.allow.*' MATCH (n) WITH name RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid related() {\n\n\t\t\tSymbolicName name = Cypher.name(\"name\");\n\t\t\tSymbolicName description = Cypher.name(\"description\");\n\t\t\tStatement call = Cypher.call(\"dbms.listConfig\")\n\t\t\t\t.withArgs(Cypher.literalOf(\"browser\"))\n\t\t\t\t.yield(name, description)\n\t\t\t\t.where(name.matches(\"browser\\\\.allow.*\"))\n\t\t\t\t.with(Cypher.asterisk())\n\t\t\t\t.create(Cypher.node(\"Config\").withProperties(\"name\", name, \"description\", description).named(\"n\"))\n\t\t\t\t.returning(Cypher.name(\"n\"))\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(call)).isEqualTo(\n\t\t\t\t\t\"CALL dbms.listConfig('browser') YIELD name, description WHERE name =~ 'browser\\\\\\\\.allow.*' WITH * CREATE (n:`Config` {name: name, description: description}) RETURN n\");\n\t\t}\n\n\t\t@Test\n\t\tvoid relatedInner() {\n\n\t\t\tSymbolicName name = Cypher.name(\"name\");\n\t\t\tAliasedExpression parameters = Cypher\n\t\t\t\t.listOf(Cypher.literalOf(\"browser\"), Cypher.literalOf(\"causal_clustering\"))\n\t\t\t\t.as(\"parameters\");\n\t\t\tStatement call = Cypher.with(parameters)\n\t\t\t\t.unwind(parameters)\n\t\t\t\t.as(\"p\")\n\t\t\t\t.call(\"dbms.listConfig\")\n\t\t\t\t.withArgs(Cypher.name(\"p\"))\n\t\t\t\t.yield(name)\n\t\t\t\t.where(name.matches(\".*allow.*\"))\n\t\t\t\t.returning(name)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(call)).isEqualTo(\n\t\t\t\t\t\"WITH ['browser', 'causal_clustering'] AS parameters UNWIND parameters AS p CALL dbms.listConfig(p) YIELD name WHERE name =~ '.*allow.*' RETURN name\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/RawLiteralTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * Generates a raw cypher literal. The factory method is able to replace {@code $E}\n * placeholders with expressions passed to it. To use a {@literal $E} escape it as\n * {$literal \\$E}.\n *\n * @author Michael J. Simons\n *\n */\nclass RawLiteralTests {\n\n\t@Test\n\tvoid shouldWorkWithoutPlaceHolder() {\n\n\t\tString cypher = Cypher.returning(Cypher.raw(\"1 * 2\").as(\"result\")).build().getCypher();\n\t\tassertThat(cypher).isEqualTo(\"RETURN 1 * 2 AS result\");\n\t}\n\n\t@Test\n\tvoid shouldUnescapeEscapedPlaceholders() {\n\n\t\tString cypher = Cypher.returning(Cypher.raw(\"\\\\$E * \\\\$E\").as(\"result\")).build().getCypher();\n\t\tassertThat(cypher).isEqualTo(\"RETURN $E * $E AS result\");\n\t}\n\n\t@Test\n\tvoid noArguments() {\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.raw(\"$E + 23 * $E\"))\n\t\t\t.withMessageStartingWith(\"Too few arguments for the raw literal format `\");\n\t}\n\n\t@Test\n\tvoid tooFewArguments() {\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.raw(\"$E + 23 * $E\", Cypher.literalOf(1)))\n\t\t\t.withMessageStartingWith(\"Too few arguments for the raw literal format `\");\n\t}\n\n\t@Test\n\tvoid tooManyArguments() {\n\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> Cypher.raw(\"$E + 23 * $E\", Cypher.literalOf(1), Cypher.literalOf(2), Cypher.literalOf(3)))\n\t\t\t.withMessageStartingWith(\"Too many arguments for the raw literal format `\");\n\t}\n\n\t@Test\n\tvoid mixedArguments() {\n\n\t\tString cypher = Cypher.returning(Cypher.raw(\"($E + $E) + \\\\$E\", Cypher.parameter(\"summand1\"), 2).as(\"result\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"RETURN ($summand1 + 2) + $E AS result\");\n\t}\n\n\t@Test\n\tvoid mixedArguments2() {\n\n\t\tString cypher = Cypher\n\t\t\t.returning(\n\t\t\t\t\tCypher.raw(\"($E + $E) + \\\\$E\", Cypher.parameter(\"summand1\"), 2, Cypher.parameter(\"E\")).as(\"result\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"RETURN ($summand1 + 2) + $E AS result\");\n\t}\n\n\t@Test\n\tvoid mixedArguments3() {\n\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> Cypher.raw(\"($E + $E) + \\\\$E\", Cypher.parameter(\"summand1\"), 2, Cypher.parameter(\"F\")))\n\t\t\t.withMessageStartingWith(\"Too many arguments for the raw literal format `\");\n\t}\n\n\t@Test\n\tvoid stringLiteral() {\n\n\t\tString cypher = Cypher.returning(Cypher.raw(\"size($E)\", \"test\").as(\"result\")).build().getCypher();\n\t\tassertThat(cypher).isEqualTo(\"RETURN size('test') AS result\");\n\t}\n\n\t@Test // GH-187\n\tvoid withParamAsExpression() {\n\n\t\tString userProvidedCypher = \"MATCH (this)-[:LINK]-(o:Other) WHERE o.name = $E RETURN o\";\n\t\tString cypher = Cypher.match(Cypher.anyNode().named(\"this\"))\n\t\t\t.with(\"this\")\n\t\t\t.returningRaw(Cypher.raw(userProvidedCypher, Cypher.parameter(\"name\").withValue(\"fooo\")).as(\"result\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher)\n\t\t\t.isEqualTo(\"MATCH (this) WITH this MATCH (this)-[:LINK]-(o:Other) WHERE o.name = $name RETURN o AS result\");\n\t}\n\n\t@Test\n\tvoid withParam() {\n\n\t\tString userProvidedCypher = \"MATCH (this)-[:LINK]-(o:Other) WHERE 1 = $E OR (o.name = $name AND $E IS NOT NULL) RETURN o\";\n\t\tfor (Object[] args : new Object[][] {\n\t\t\t\t{ Cypher.literalOf(1), Cypher.literalOf(\"whatever\"), Cypher.parameter(\"name\").withValue(\"fooo\") },\n\t\t\t\t{ Cypher.literalOf(1), Cypher.parameter(\"name\").withValue(\"fooo\"), Cypher.literalOf(\"whatever\") },\n\t\t\t\t{ Cypher.literalOf(1), Cypher.literalOf(\"whatever\") },\n\t\t\t\t{ Cypher.parameter(\"name\").withValue(\"fooo\"), Cypher.literalOf(1), Cypher.literalOf(\"whatever\") } }) {\n\t\t\tString cypher = Cypher.match(Cypher.anyNode().named(\"this\"))\n\t\t\t\t.with(\"this\")\n\t\t\t\t.returningRaw(Cypher.raw(userProvidedCypher, args).as(\"result\"))\n\t\t\t\t.build()\n\t\t\t\t.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\t\"MATCH (this) WITH this MATCH (this)-[:LINK]-(o:Other) WHERE 1 = 1 OR (o.name = $name AND 'whatever' IS NOT NULL) RETURN o AS result\");\n\t\t}\n\t}\n\n\t@Test\n\tvoid withParamSimple() {\n\n\t\tString userProvidedCypher = \"MATCH (this)-[:LINK]-(o:Other) WHERE o.name = $name RETURN o\";\n\t\tString cypher = Cypher.match(Cypher.anyNode().named(\"this\"))\n\t\t\t.with(\"this\")\n\t\t\t.returningRaw(Cypher.raw(userProvidedCypher, Cypher.parameter(\"name\").withValue(\"fooo\")).as(\"result\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher)\n\t\t\t.isEqualTo(\"MATCH (this) WITH this MATCH (this)-[:LINK]-(o:Other) WHERE o.name = $name RETURN o AS result\");\n\t}\n\n\t@Test\n\tvoid withParamSimpleNoArgs() {\n\n\t\tString userProvidedCypher = \"MATCH (this)-[:LINK]-(o:Other) WHERE o.name = $name RETURN o\";\n\t\tString cypher = Cypher.match(Cypher.anyNode().named(\"this\"))\n\t\t\t.with(\"this\")\n\t\t\t.returningRaw(Cypher.raw(userProvidedCypher).as(\"result\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher)\n\t\t\t.isEqualTo(\"MATCH (this) WITH this MATCH (this)-[:LINK]-(o:Other) WHERE o.name = $name RETURN o AS result\");\n\t}\n\n\t@Test\n\tvoid shouldUnescapeEscapedPlaceholdersAndUseThem() {\n\n\t\tString cypher = Cypher.returning(Cypher.raw(\"\\\\$E * \\\\$E\", Parameter.create(\"E\")).as(\"result\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"RETURN $E * $E AS result\");\n\n\t\tcypher = Cypher.returning(Cypher.raw(\"\\\\$E   * \\\\$E\", Parameter.create(\"E\")).as(\"result\")).build().getCypher();\n\t\tassertThat(cypher).isEqualTo(\"RETURN $E   * $E AS result\");\n\t}\n\n\t@Test\n\tvoid shouldUnescapeEscapedPlaceholdersAndUseThemAndBlanksDontMatter() {\n\n\t\tString cypher = Cypher.returning(Cypher.raw(\"\\\\$E   * \\\\$E\\n\", Parameter.create(\"E\")).as(\"result\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"RETURN $E   * $E\\n AS result\");\n\t}\n\n\t@Test\n\tvoid onlyExpressionArguments() {\n\n\t\tString cypher = Cypher.returning(Cypher.raw(\"$E + $E\", Cypher.literalOf(1), Cypher.literalOf(2)).as(\"result\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"RETURN 1 + 2 AS result\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/RelationshipChainTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.TestInstance;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\n@TestInstance(TestInstance.Lifecycle.PER_CLASS)\nclass RelationshipChainTests {\n\n\tprivate final Node s = Cypher.node(\"Start\").named(\"s\");\n\n\tprivate final Node e = Cypher.node(\"End\").named(\"e\");\n\n\tprivate final RelationshipChain chain1 = this.s.relationshipTo(Cypher.anyNode()).relationshipTo(this.e);\n\n\t@Test\n\tvoid namedShouldReturnNew() {\n\n\t\tRelationshipChain chain2 = this.chain1.named(\"x\");\n\t\tassertThat(chain2).isNotSameAs(this.chain1);\n\n\t\tString cypher1 = Cypher.match(this.chain1).returning(Cypher.asterisk()).build().getCypher();\n\t\tassertThat(cypher1).isEqualTo(\"MATCH (s:`Start`)-->()-->(e:`End`) RETURN *\");\n\t\tString cypher2 = Cypher.match(chain2).returning(Cypher.asterisk()).build().getCypher();\n\t\tassertThat(cypher2).isEqualTo(\"MATCH (s:`Start`)-->()-[x]->(e:`End`) RETURN *\");\n\t}\n\n\t@Test\n\tvoid unboundedShouldReturnNew() {\n\n\t\tRelationshipChain chain2 = this.chain1.unbounded();\n\t\tassertThat(chain2).isNotSameAs(this.chain1);\n\n\t\tString cypher1 = Cypher.match(this.chain1).returning(Cypher.asterisk()).build().getCypher();\n\t\tassertThat(cypher1).isEqualTo(\"MATCH (s:`Start`)-->()-->(e:`End`) RETURN *\");\n\t\tString cypher2 = Cypher.match(chain2).returning(Cypher.asterisk()).build().getCypher();\n\t\tassertThat(cypher2).isEqualTo(\"MATCH (s:`Start`)-->()-[*]->(e:`End`) RETURN *\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/RelationshipTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass RelationshipTests {\n\n\t@Test\n\tvoid relationshipWithoutTypesMustNotThrowNPEs() {\n\n\t\tRelationship relationship = Cypher.anyNode().relationshipTo(Cypher.anyNode());\n\t\tassertThat(relationship.getDetails().getTypes()).isEmpty();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/StatementCatalogBuildingVisitorTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.net.URI;\nimport java.util.Set;\n\nimport org.junit.jupiter.api.RepeatedTest;\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Dialect;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n */\nclass StatementCatalogBuildingVisitorTests {\n\n\t@Test\n\tvoid simpleShowCase() {\n\n\t\t// tag::catalog-example[]\n\t\tvar p = Cypher.node(\"Person\").named(\"p\");\n\t\tvar m = Cypher.node(\"Movie\").named(\"m\");\n\t\tvar a = m.withProperties(\"title\", Cypher.literalOf(\"The Matrix\")).relationshipFrom(p, \"ACTED_IN\").named(\"a\");\n\t\tvar statement = Cypher.match(a)\n\t\t\t.where(p.property(\"born\").gte(Cypher.parameter(\"born\", 1979)))\n\t\t\t.returning(p)\n\t\t\t.build();\n\n\t\tvar catalog = statement.getCatalog();\n\n\t\tassertThat(catalog.getNodeLabels()).extracting(StatementCatalog.Token::value)\n\t\t\t.containsExactlyInAnyOrder(\"Person\", \"Movie\");\n\t\tassertThat(catalog.getProperties()).containsExactlyInAnyOrder(\n\t\t\t\tStatementCatalog.property(Set.of(StatementCatalog.label(\"Movie\")), \"title\"),\n\t\t\t\tStatementCatalog.property(Set.of(StatementCatalog.label(\"Person\")), \"born\"));\n\t\t// end::catalog-example[]\n\n\t\tvar cypher = statement.getCypher();\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (m:`Movie` {title: 'The Matrix'})<-[a:`ACTED_IN`]-(p:`Person`) WHERE p.born >= $born RETURN p\");\n\t}\n\n\t@Test\n\tvoid labelExpressionsShouldWork() {\n\n\t\tvar p = Cypher.node(Cypher.exactlyLabel(\"Person\").or(Cypher.exactlyLabel(\"Actor\")));\n\t\tvar statement = Cypher.match(p)\n\t\t\t.where(p.property(\"born\").gte(Cypher.parameter(\"born\", 1979)))\n\t\t\t.returning(p)\n\t\t\t.build();\n\n\t\tvar catalog = statement.getCatalog();\n\n\t\tassertThat(catalog.getNodeLabels()).extracting(StatementCatalog.Token::value)\n\t\t\t.containsExactlyInAnyOrder(\"Actor\", \"Person\");\n\t\tassertThat(catalog.getProperties()).containsExactlyInAnyOrder(StatementCatalog\n\t\t\t.property(Set.of(StatementCatalog.label(\"Actor\"), StatementCatalog.label(\"Person\")), \"born\"));\n\t}\n\n\t@Test\n\tvoid labelFiltersShouldWork() {\n\t\tvar n = Cypher.node(\"Person\").withProperties(\"name\", Cypher.literalOf(\"John Doe\")).named(\"n\");\n\t\tvar m = Cypher.node(\"Person\").named(\"m\");\n\n\t\tvar statement = Cypher.match(n.relationshipTo(m, \"IS_FRIEND_WITH\"))\n\t\t\t.where(n.hasLabels(\"Active\"))\n\t\t\t.and(m.hasLabels(\"Kind\", \"Positive\").and(m.property(\"name\").eq(Cypher.literalOf(\"Jane\"))))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build();\n\t\tvar cypher = statement.getCypher();\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (n:`Person` {name: 'John Doe'})-[:`IS_FRIEND_WITH`]->(m:`Person`) WHERE (n:`Active` AND m:`Kind`:`Positive` AND m.name = 'Jane') RETURN *\");\n\n\t\tvar catalog = statement.getCatalog();\n\t\tvar expectedLabelFilters = Set.of(\n\t\t\t\tnew StatementCatalog.LabelFilter(\"n\", Set.of(StatementCatalog.label(\"Active\"))),\n\t\t\t\tnew StatementCatalog.LabelFilter(\"m\",\n\t\t\t\t\t\tSet.of(StatementCatalog.label(\"Kind\"), StatementCatalog.label(\"Positive\"))));\n\t\tassertThat(catalog.getAllFilters()).hasSize(4)\n\t\t\t.filteredOn(StatementCatalog.LabelFilter.class::isInstance)\n\t\t\t.map(StatementCatalog.LabelFilter.class::cast)\n\t\t\t.containsExactlyInAnyOrderElementsOf(expectedLabelFilters);\n\t\tassertThat(catalog.getAllLabelFilters()).containsExactlyInAnyOrderElementsOf(expectedLabelFilters);\n\t}\n\n\t@Test // GH-674\n\tvoid shouldThrowWhenAskingWithTypeForTypes() {\n\n\t\tvar n = Cypher.node(\"Person\").withProperties(\"name\", Cypher.literalOf(\"John Doe\")).named(\"n\");\n\t\tvar m = Cypher.node(\"Person\").named(\"m\");\n\n\t\tvar catalog = Cypher.match(n.relationshipTo(m, \"IS_FRIEND_WITH\"))\n\t\t\t.where(n.hasLabels(\"Active\"))\n\t\t\t.and(m.hasLabels(\"Kind\", \"Positive\").and(m.property(\"name\").eq(Cypher.literalOf(\"Jane\"))))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCatalog();\n\n\t\tvar aType = StatementCatalog.Token.type(\"whatever\");\n\t\tvar expectedMessage = \"Token[type=RELATIONSHIP_TYPE, value=whatever] must be a node label, not a relationship type\";\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> catalog.getIncomingRelations(aType))\n\t\t\t.withMessage(expectedMessage);\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> catalog.getOutgoingRelations(aType))\n\t\t\t.withMessage(expectedMessage);\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> catalog.getUndirectedRelations(aType))\n\t\t\t.withMessage(expectedMessage);\n\t}\n\n\t@Test // GH-674\n\tvoid shouldThrowWhenAskingWithLabelForLabels() {\n\n\t\tvar n = Cypher.node(\"Person\").withProperties(\"name\", Cypher.literalOf(\"John Doe\")).named(\"n\");\n\t\tvar m = Cypher.node(\"Person\").named(\"m\");\n\n\t\tvar catalog = Cypher.match(n.relationshipTo(m, \"IS_FRIEND_WITH\"))\n\t\t\t.where(n.hasLabels(\"Active\"))\n\t\t\t.and(m.hasLabels(\"Kind\", \"Positive\").and(m.property(\"name\").eq(Cypher.literalOf(\"Jane\"))))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCatalog();\n\n\t\tvar aLabel = StatementCatalog.Token.label(\"whatever\");\n\t\tvar expectedMessage = \"Token[type=NODE_LABEL, value=whatever] must be a relationship type, not a node label\";\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> catalog.getTargetNodes(aLabel))\n\t\t\t.withMessage(expectedMessage);\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> catalog.getSourceNodes(aLabel))\n\t\t\t.withMessage(expectedMessage);\n\t}\n\n\t@Test // GH-738\n\tvoid literalRetrievalShouldWork() {\n\n\t\tvar literals = Cypher.match(Cypher.anyNode(\"n\"))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCatalog()\n\t\t\t.getLiterals();\n\t\tassertThat(literals).isEmpty();\n\n\t\tliterals = Cypher.match(Cypher.anyNode(\"n\").withProperties(Cypher.mapOf(\"a\", Cypher.literalOf(\"A\"))))\n\t\t\t.where(Cypher.name(\"n\").property(\"prop\").eq(Cypher.literalOf(42)))\n\t\t\t.and(Cypher.name(\"n\").property(\"b\").isFalse())\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCatalog()\n\t\t\t.getLiterals();\n\n\t\tassertThat(literals).map(Literal::asString).containsExactlyInAnyOrder(\"'A'\", \"42\", \"false\");\n\n\t\tvar x = Cypher.name(\"x\");\n\t\tvar stmt = Cypher.usingPeriodicCommit()\n\t\t\t.loadCSV(URI.create(\"https://test.com/test.csv\"))\n\t\t\t.as(\"x\")\n\t\t\t.with(\"x\")\n\t\t\t.merge(Cypher.anyNode(\"n\").withProperties(\"x\", x))\n\t\t\t.onCreate()\n\t\t\t.set(x.property(\"y\").to(Cypher.literalNull()), x.property(\"a\").to(Cypher.literalOf(\"Hallo\")))\n\t\t\t.onCreate()\n\t\t\t.set(x.property(\"b\").to(Cypher.subList(Cypher.listOf(Cypher.literalTrue()), 1, 2)))\n\t\t\t.returning(Cypher.raw(\"x\"))\n\t\t\t.build();\n\t\tassertThat(stmt.getCypher()).isEqualTo(\n\t\t\t\t\"USING PERIODIC COMMIT LOAD CSV FROM 'https://test.com/test.csv' AS x WITH x MERGE (n {x: x}) ON CREATE SET x.y = NULL, x.a = 'Hallo' ON CREATE SET x.b = [true][1..2] RETURN x\");\n\t\tassertThat(stmt.getCatalog().getLiterals()).map(Literal::asString)\n\t\t\t.containsExactlyInAnyOrder(\"1\", \"2\", \"NULL\", \"true\", \"'Hallo'\");\n\t}\n\n\t@Test // GH-738\n\tvoid procedureNamesMustNotAppearAsLiterals() {\n\n\t\tvar stmt = Cypher.call(\"dbms.routing.getRoutingTable\")\n\t\t\t.withArgs(Cypher.parameter(\"routingContext\"), Cypher.parameter(\"databaseName\"))\n\t\t\t.yieldStar()\n\t\t\t.build();\n\t\tassertThat(stmt.getCatalog().getLiterals()).isEmpty();\n\t}\n\n\t@Test // GH-674\n\tvoid retrievalOfRelationshipsShouldWork() {\n\n\t\tvar n = Cypher.node(\"Person\").withProperties(\"name\", Cypher.literalOf(\"John Doe\")).named(\"n\");\n\t\tvar m = Cypher.node(\"Person\").named(\"m\");\n\n\t\tvar catalog = Cypher.match(n.relationshipTo(m, \"IS_FRIEND_WITH\"))\n\t\t\t.where(n.hasLabels(\"Active\"))\n\t\t\t.and(m.hasLabels(\"Kind\", \"Positive\").and(m.property(\"name\").eq(Cypher.literalOf(\"Jane\"))))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build()\n\t\t\t.getCatalog();\n\n\t\tvar isFriendWith = StatementCatalog.Token.type(\"IS_FRIEND_WITH\");\n\t\tassertThat(catalog.getTargetNodes(isFriendWith)).isNotEmpty();\n\t\tassertThat(catalog.getSourceNodes(isFriendWith)).isNotEmpty();\n\n\t\tvar person = StatementCatalog.Token.label(\"Person\");\n\t\tassertThat(catalog.getIncomingRelations(person)).containsExactlyInAnyOrder(isFriendWith);\n\t\tassertThat(catalog.getOutgoingRelations(person)).containsExactlyInAnyOrder(isFriendWith);\n\t}\n\n\t@RepeatedTest(20)\n\tvoid random_order_test() {\n\t\tvar rendererConfig = Configuration.newConfig().withDialect(Dialect.NEO4J_5).withPrettyPrint(true).build();\n\t\tvar renderer = Renderer.getRenderer(rendererConfig);\n\t\tvar person = Cypher.node(\"Person\").named(\"n\");\n\t\tvar movie = Cypher.node(\"Movie\").named(\"m\");\n\t\tvar rel = person.relationshipTo(movie).named(\"r\");\n\t\tvar innerStatement = Cypher.match(rel).returning(person, rel, movie).build();\n\n\t\tvar graph_name = Cypher.name(\"__graph__name__\");\n\t\tvar statement = Cypher.unwind(Cypher.graphNames())\n\t\t\t.as(graph_name)\n\t\t\t.call(Cypher.use(Cypher.graphByName(graph_name), innerStatement))\n\t\t\t.returning(innerStatement.getCatalog().getIdentifiableExpressions())\n\t\t\t.build();\n\n\t\tassertThat(renderer.render(statement)).isEqualTo(\"\"\"\n\t\t\t\tUNWIND graph.names() AS __graph__name__\n\t\t\t\tCALL {\n\t\t\t\t  USE graph.byName(__graph__name__)\n\t\t\t\t  MATCH (n:Person)-[r]->(m:Movie)\n\t\t\t\t  RETURN n, r, m\n\t\t\t\t}\n\t\t\t\tRETURN n, r, m\"\"\");\n\t}\n\n\t@Test // GH-785\n\tvoid nullParametersMustBeAllowed() {\n\n\t\tvar statement = Cypher.match(Cypher.anyNode(\"n\"))\n\t\t\t.where(Cypher.property(\"n\", \"whatever\").isEqualTo(Cypher.parameter(\"foo\", null)))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build();\n\t\tassertThat(statement.getCypher()).isEqualTo(\"MATCH (n) WHERE n.whatever = $foo RETURN *\");\n\t\tassertThat(statement.getCatalog().getParameters()).containsEntry(\"foo\", null);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/StringLiteralTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass StringLiteralTests {\n\n\t@Test\n\tvoid shouldEscapeContent() {\n\t\tStringLiteral literal = new StringLiteral(\"A\\\\B\\\\\\\\Ca'bc123\\\\\");\n\n\t\tassertThat(literal.asString()).isEqualTo(\"'A\\\\\\\\B\\\\\\\\\\\\\\\\Ca\\\\'bc123\\\\\\\\'\");\n\t}\n\n\t@Test\n\tvoid shouldEscapeNull() {\n\t\tStringLiteral literal = new StringLiteral(null);\n\n\t\tassertThat(literal.asString()).isEqualTo(\"''\");\n\t}\n\n\t@Test\n\tvoid shouldCorrectlyEscapeEmptyStrings() {\n\n\t\tfor (String[] strings : new String[][] { { \"\", \"\" }, { \" \\t \", \" \\t \" },\n\t\t\t\t{ \"Nothing to escape\", \"Nothing to escape\" }, { \"' \\\" '\", \"\\\\' \\\\\\\" \\\\'\" } }) {\n\t\t\tString string = strings[0];\n\t\t\tString expectedEscapedString = strings[1];\n\t\t\tassertThat(StringLiteral.escapeString(string)).hasValue(expectedEscapedString);\n\t\t}\n\t}\n\n\t@Test\n\tvoid shouldNotTryToEscapeNullStrings() {\n\t\tassertThat(StringLiteral.escapeString(null)).isEmpty();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/SubqueriesGQLIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.net.URI;\n\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.ValueSource;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n */\nclass SubqueriesGQLIT {\n\n\tprivate static final Renderer cypherRenderer = Renderer.getDefaultRenderer();\n\n\t@Test // GH-533\n\tvoid unitSubqueries() {\n\n\t\tvar p = Cypher.node(\"Person\").named(\"p\");\n\t\tvar outer = Cypher.match(p);\n\t\tvar inner = Cypher.with(p)\n\t\t\t.unwind(Cypher.range(1, 5))\n\t\t\t.as(\"i\")\n\t\t\t.create(Cypher.node(\"Person\").withProperties(\"name\", p.property(\"name\")))\n\t\t\t.build();\n\n\t\tvar statement = outer.call(inner).returning(Cypher.count(Cypher.asterisk())).build();\n\t\tassertThat(statement.getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (p:`Person`) CALL (p) {UNWIND range(1, 5) AS i CREATE (:`Person` {name: p.name})} RETURN count(*)\");\n\t}\n\n\t@Nested\n\tclass Scope {\n\n\t\t@Test\n\t\tvoid nodePatternInCallMustBeFullAndNotKnown() {\n\t\t\tStatement parsed = Cypher.match(Cypher.node(\"Person\").named(\"n\"))\n\t\t\t\t.call(Cypher\n\t\t\t\t\t.match(Cypher.node(\"Movie\").named(\"n\").withProperties(\"title\", Cypher.literalOf(\"The Matrix\")))\n\t\t\t\t\t.where(Cypher.anyNode(\"n\").property(\"released\").gte(Cypher.literalOf(1980)))\n\t\t\t\t\t.returning(Cypher.anyNode(\"n\").as(\"m\"))\n\t\t\t\t\t.build())\n\t\t\t\t.returning(Cypher.anyNode(\"n\").property(\"name\"))\n\t\t\t\t.build();\n\t\t\tString cypher = Renderer.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).build())\n\t\t\t\t.render(parsed);\n\t\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\t\"MATCH (n:Person) CALL (*) {MATCH (n:Movie {title: 'The Matrix'}) WHERE n.released >= 1980 RETURN n AS m} RETURN n.name\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass ResultReturningSubqueries {\n\n\t\t@Test\n\t\tvoid importingVariablesShouldWork() {\n\n\t\t\tStatement statement = Cypher.unwind(Cypher.literalOf(0), Cypher.literalOf(1), Cypher.literalOf(2))\n\t\t\t\t.as(\"x\")\n\t\t\t\t.call(Cypher.with(Cypher.name(\"x\"))\n\t\t\t\t\t.returning(Cypher.name(\"x\").multiply(Cypher.literalOf(10)).as(\"y\"))\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"x\", \"y\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"UNWIND [0, 1, 2] AS x CALL (x) {RETURN (x * 10) AS y} RETURN x, y\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"x\"), SymbolicName.of(\"y\"));\n\t\t}\n\n\t\t@Test\n\t\tvoid postUnionProcessingShouldWork() {\n\n\t\t\tProperty ageProperty = Cypher.property(\"p\", \"age\");\n\t\t\tProperty nameProperty = Cypher.property(\"p\", \"name\");\n\n\t\t\t// This must be 2 different person nodes and statement, otherwise the union\n\t\t\t// will reuse it.\n\t\t\tStatement s1 = Cypher.match(Cypher.node(\"Person\").named(\"p\"))\n\t\t\t\t.returning(\"p\")\n\t\t\t\t.orderBy(ageProperty.ascending())\n\t\t\t\t.limit(1)\n\t\t\t\t.build();\n\t\t\tStatement s2 = Cypher.match(Cypher.node(\"Person\").named(\"p\"))\n\t\t\t\t.returning(\"p\")\n\t\t\t\t.orderBy(ageProperty.descending())\n\t\t\t\t.limit(1)\n\t\t\t\t.build();\n\n\t\t\tStatement statement = Cypher.call(Cypher.union(s1, s2))\n\t\t\t\t.returning(nameProperty, ageProperty)\n\t\t\t\t.orderBy(nameProperty)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CALL () {MATCH (p:`Person`) RETURN p ORDER BY p.age ASC LIMIT 1 UNION MATCH (p:`Person`) RETURN p ORDER BY p.age DESC LIMIT 1} RETURN p.name, p.age ORDER BY p.name\");\n\t\t}\n\n\t\t@Test\n\t\tvoid aggregationAndSideEffectsShouldWork() {\n\n\t\t\tNode person = Cypher.node(\"Person\").named(\"p\");\n\t\t\tNode clone = Cypher.node(\"Clone\").named(\"c\");\n\t\t\tStatement statement = Cypher.match(person)\n\t\t\t\t.call(Cypher.unwind(Cypher.range(1, 5))\n\t\t\t\t\t.as(\"i\")\n\t\t\t\t\t.create(clone)\n\t\t\t\t\t.returning(Cypher.count(clone).as(\"numberOfClones\"))\n\t\t\t\t\t.build())\n\t\t\t\t.returning(person.property(\"name\"), Cypher.name(\"numberOfClones\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (p:`Person`) CALL (*) {UNWIND range(1, 5) AS i CREATE (c:`Clone`) RETURN count(c) AS numberOfClones} RETURN p.name, numberOfClones\");\n\t\t}\n\n\t\t@Test\n\t\tvoid aggregationOnImportedVariablesShouldWork() {\n\n\t\t\tNode person = Cypher.node(\"Person\").named(\"p\");\n\t\t\tNode other = Cypher.node(\"Person\").named(\"other\");\n\t\t\tStatement statement = Cypher.match(person)\n\t\t\t\t.call(Cypher.with(person)\n\t\t\t\t\t.match(other)\n\t\t\t\t\t.where(other.property(\"age\").lt(person.property(\"age\")))\n\t\t\t\t\t.returning(Cypher.count(other).as(\"youngerPersonsCount\"))\n\t\t\t\t\t.build())\n\t\t\t\t.returning(person.property(\"name\"), Cypher.name(\"youngerPersonsCount\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (p:`Person`) CALL (p) {MATCH (other:`Person`) WHERE other.age < p.age RETURN count(other) AS youngerPersonsCount} RETURN p.name, youngerPersonsCount\");\n\t\t}\n\n\t\t@Test\n\t\tvoid nestedAfterProcedureCall() {\n\n\t\t\t// With with\n\t\t\tStatement statement = Cypher.call(\"dbms.components\")\n\t\t\t\t.yield(\"name\")\n\t\t\t\t.with(\"name\")\n\t\t\t\t.call(Cypher.with(\"name\")\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(Cypher.name(\"name\")))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CALL dbms.components() YIELD name WITH name CALL (name) {MATCH (n) WHERE n.name = name RETURN n} RETURN n\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"n\"));\n\n\t\t\t// Without with\n\t\t\tstatement = Cypher.call(\"dbms.components\")\n\t\t\t\t.yield(\"name\")\n\t\t\t\t.call(Cypher.with(\"name\")\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(Cypher.name(\"name\")))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CALL dbms.components() YIELD name CALL (name) {MATCH (n) WHERE n.name = name RETURN n} RETURN n\");\n\n\t\t\t// After inQueryCall with with\n\t\t\tSymbolicName label = Cypher.name(\"label\");\n\t\t\tstatement = Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t.with(\"n\")\n\t\t\t\t.call(\"db.labels\")\n\t\t\t\t.yield(label)\n\t\t\t\t.with(label)\n\t\t\t\t.call(Cypher.with(label)\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(label))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n) WITH n CALL db.labels() YIELD label WITH label CALL (label) {MATCH (n) WHERE n.name = label RETURN n} RETURN n\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"n\"));\n\n\t\t\t// After inQueryCall without with\n\t\t\tstatement = Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t.with(\"n\")\n\t\t\t\t.call(\"db.labels\")\n\t\t\t\t.yield(label)\n\t\t\t\t.call(Cypher.with(label)\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n2\"))\n\t\t\t\t\t.where(Cypher.property(\"n2\", \"name\").isEqualTo(label))\n\t\t\t\t\t.returning(\"n2\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n2\")\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n) WITH n CALL db.labels() YIELD label CALL (label) {MATCH (n2) WHERE n2.name = label RETURN n2} RETURN n2\");\n\t\t}\n\n\t\t@Test\n\t\tvoid afterRegularWith() {\n\n\t\t\tStatement statement = Cypher.match(Cypher.node(\"Person\").named(\"p\"))\n\t\t\t\t.with(\"p\")\n\t\t\t\t.call(Cypher.with(\"p\")\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(Cypher.property(\"p\", \"name\")))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (p:`Person`) WITH p CALL (p) {MATCH (n) WHERE n.name = p.name RETURN n} RETURN n\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"n\"));\n\t\t}\n\n\t\t@Test\n\t\tvoid afterRegularWithManualImport() {\n\n\t\t\tStatement statement = Cypher.match(Cypher.node(\"Person\").named(\"p\"))\n\t\t\t\t.with(\"p\")\n\t\t\t\t.call(Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(Cypher.property(\"p\", \"name\")))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build(), \"p\")\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (p:`Person`) WITH p CALL (p) {MATCH (n) WHERE n.name = p.name RETURN n} RETURN n\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"n\"));\n\t\t}\n\n\t\t@Test\n\t\tvoid callsCallingCalls() {\n\n\t\t\tStatement someStatement = Cypher.match(Cypher.anyNode().named(\"n\")).returning(\"n\").build();\n\t\t\tStatement statement = someStatement;\n\n\t\t\tfor (int i = 0; i < 5; ++i) {\n\t\t\t\tstatement = Cypher.call(statement).returning(\"n\").build();\n\t\t\t}\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CALL () {CALL () {CALL () {CALL () {CALL () {MATCH (n) RETURN n} RETURN n} RETURN n} RETURN n} RETURN n} RETURN n\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass ExistentialSubqueries {\n\n\t\t@Test // GH-578\n\t\tvoid fullStatementsAsExistentialSubQuery() {\n\n\t\t\tNode p = Cypher.node(\"Person\").named(\"person\");\n\t\t\tStatement inner = Cypher.match(p.relationshipTo(Cypher.node(\"Dog\"), \"HAS_DOG\"))\n\t\t\t\t.returning(p.property(\"name\"))\n\t\t\t\t.build();\n\t\t\tStatement outer = Cypher.match(p)\n\t\t\t\t.where(Cypher.exists(inner))\n\t\t\t\t.returning(p.property(\"name\").as(\"name\"))\n\t\t\t\t.build();\n\n\t\t\tString cypher = outer.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`) WHERE EXISTS { MATCH (person)-[:`HAS_DOG`]->(:`Dog`) RETURN person.name } RETURN person.name AS name\");\n\t\t}\n\n\t\t@Test // GH-578\n\t\tvoid fullStatementsAsExistentialSubQueryWithImports() {\n\n\t\t\tNode p = Cypher.node(\"Person\").named(\"person\");\n\t\t\tNode d = Cypher.node(\"Dog\").named(\"d\");\n\t\t\tSymbolicName dogName = Cypher.name(\"dogName\");\n\t\t\tStatement inner = Cypher.match(p.relationshipTo(d, \"HAS_DOG\"))\n\t\t\t\t.where(d.property(\"name\").eq(dogName))\n\t\t\t\t.returning(p.property(\"name\"))\n\t\t\t\t.build();\n\t\t\tStatement outer = Cypher.match(p)\n\t\t\t\t.where(Cypher.exists(inner, Cypher.literalOf(\"Ozzy\").as(dogName)))\n\t\t\t\t.returning(p.property(\"name\").as(\"name\"))\n\t\t\t\t.build();\n\n\t\t\tString cypher = outer.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`) WHERE EXISTS { WITH 'Ozzy' AS dogName MATCH (person)-[:`HAS_DOG`]->(d:`Dog`) WHERE d.name = dogName RETURN person.name } RETURN person.name AS name\");\n\t\t}\n\n\t\t@Test\n\t\tvoid simple() {\n\n\t\t\tNode p = Cypher.node(\"Person\").named(\"p\");\n\t\t\tNode friend = Cypher.node(\"Person\").named(\"friend\");\n\n\t\t\tRelationship r = p.relationshipTo(friend, \"IS_FRIENDS_WITH\").named(\"r\");\n\t\t\tStatement statement = Cypher.match(r)\n\t\t\t\t.where(Cypher\n\t\t\t\t\t.match(p.relationshipTo(Cypher.node(\"Company\").withProperties(\"name\", Cypher.literalOf(\"Neo4j\")),\n\t\t\t\t\t\t\t\"WORKS_FOR\"))\n\t\t\t\t\t.asCondition())\n\t\t\t\t.returning(p, r, friend)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (p:`Person`)-[r:`IS_FRIENDS_WITH`]->(friend:`Person`) WHERE EXISTS { MATCH (p)-[:`WORKS_FOR`]->(:`Company` {name: 'Neo4j'}) } RETURN p, r, friend\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withBooleanOpsAndWhere() {\n\n\t\t\tNode p = Cypher.node(\"Person\").named(\"person\");\n\t\t\tNode company = Cypher.anyNode().named(\"company\");\n\t\t\tNode t = Cypher.node(\"Technology\").named(\"t\");\n\n\t\t\tStatement statement = Cypher.match(p.relationshipTo(company, \"WORKS_FOR\"))\n\t\t\t\t.where(company.property(\"name\").startsWith(Cypher.literalOf(\"Company\")))\n\t\t\t\t.and(Cypher.match(p.relationshipTo(t, \"LIKES\"))\n\t\t\t\t\t.where(Cypher.size(t.relationshipFrom(Cypher.anyNode(), \"LIKES\")).gte(Cypher.literalOf(3)))\n\t\t\t\t\t.asCondition())\n\t\t\t\t.returning(p.property(\"name\").as(\"person\"), company.property(\"name\").as(\"company\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`)-[:`WORKS_FOR`]->(company) WHERE (company.name STARTS WITH 'Company' AND EXISTS { MATCH (person)-[:`LIKES`]->(t:`Technology`) WHERE size((t)<-[:`LIKES`]-()) >= 3 }) RETURN person.name AS person, company.name AS company\");\n\n\t\t\tstatement = Cypher.match(p.relationshipTo(company, \"WORKS_FOR\"))\n\t\t\t\t.where(Cypher.match(p.relationshipTo(t, \"LIKES\"))\n\t\t\t\t\t.where(Cypher.size(t.relationshipFrom(Cypher.anyNode(), \"LIKES\")).gte(Cypher.literalOf(3)))\n\t\t\t\t\t.asCondition())\n\t\t\t\t.and(company.property(\"name\").startsWith(Cypher.literalOf(\"Company\")))\n\t\t\t\t.returning(p.property(\"name\").as(\"person\"), company.property(\"name\").as(\"company\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`)-[:`WORKS_FOR`]->(company) WHERE (EXISTS { MATCH (person)-[:`LIKES`]->(t:`Technology`) WHERE size((t)<-[:`LIKES`]-()) >= 3 } AND company.name STARTS WITH 'Company') RETURN person.name AS person, company.name AS company\");\n\n\t\t\tstatement = Cypher.match(p.relationshipTo(company, \"WORKS_FOR\"))\n\t\t\t\t.where(Cypher.match(p.relationshipTo(t, \"LIKES\"))\n\t\t\t\t\t.where(Cypher.size(t.relationshipFrom(Cypher.anyNode(), \"LIKES\")).gte(Cypher.literalOf(3)))\n\t\t\t\t\t.asCondition()\n\t\t\t\t\t.and(company.property(\"name\").startsWith(Cypher.literalOf(\"Company\"))))\n\t\t\t\t.returning(p.property(\"name\").as(\"person\"), company.property(\"name\").as(\"company\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`)-[:`WORKS_FOR`]->(company) WHERE (EXISTS { MATCH (person)-[:`LIKES`]->(t:`Technology`) WHERE size((t)<-[:`LIKES`]-()) >= 3 } AND company.name STARTS WITH 'Company') RETURN person.name AS person, company.name AS company\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass InTransactions {\n\n\t\t@Test\n\t\tvoid docs44_7() {\n\n\t\t\tSymbolicName line = Cypher.name(\"line\");\n\t\t\tStatement statement = Cypher.loadCSV(URI.create(\"file:///friends.csv\"))\n\t\t\t\t.as(\"line\")\n\t\t\t\t.callInTransactions(Cypher.with(\"line\")\n\t\t\t\t\t.create(Cypher.node(\"Person\")\n\t\t\t\t\t\t.withProperties(\"name\", Cypher.valueAt(line, 1), \"age\",\n\t\t\t\t\t\t\t\tCypher.toInteger(Cypher.valueAt(line, 2))))\n\t\t\t\t\t.build())\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"LOAD CSV FROM 'file:///friends.csv' AS line CALL (line) {CREATE (:`Person` {name: line[1], age: toInteger(line[2])})} IN TRANSACTIONS\");\n\t\t}\n\n\t\t@Test\n\t\tvoid docs44_7_1a() {\n\n\t\t\tSymbolicName line = Cypher.name(\"line\");\n\t\t\tStatement statement = Cypher.loadCSV(URI.create(\"file:///friends.csv\"))\n\t\t\t\t.as(\"line\")\n\t\t\t\t.callInTransactions(Cypher.with(\"line\")\n\t\t\t\t\t.create(Cypher.node(\"Person\")\n\t\t\t\t\t\t.withProperties(\"name\", Cypher.valueAt(line, 1), \"age\",\n\t\t\t\t\t\t\t\tCypher.toInteger(Cypher.valueAt(line, 2))))\n\t\t\t\t\t.build(), 2)\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"LOAD CSV FROM 'file:///friends.csv' AS line CALL (line) {CREATE (:`Person` {name: line[1], age: toInteger(line[2])})} IN TRANSACTIONS OF 2 ROWS\");\n\t\t}\n\n\t\t@Test\n\t\tvoid docs44_7_1b() {\n\n\t\t\tStatement statement = Cypher.match(Cypher.anyNode(\"n\"))\n\t\t\t\t.callInTransactions(Cypher.with(\"n\").detachDelete(\"n\").build(), 2)\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (n) CALL (n) {DETACH DELETE n} IN TRANSACTIONS OF 2 ROWS\");\n\t\t}\n\n\t\t@ParameterizedTest\n\t\t@ValueSource(ints = { -1, 23 })\n\t\tvoid afterRegularWith(int numRows) {\n\n\t\t\tResultStatement subquery = Cypher\n\t\t\t\t.create(Cypher.anyNode(\"p\").relationshipTo(Cypher.node(\"User\").named(\"u\"), \"IS\"))\n\t\t\t\t.returning(Cypher.name(\"u\"))\n\t\t\t\t.build();\n\n\t\t\tStatementBuilder.OrderableOngoingReadingAndWithWithoutWhere with = Cypher\n\t\t\t\t.match(Cypher.node(\"Person\").named(\"p\"))\n\t\t\t\t.with(\"p\");\n\t\t\tStatement statement = ((numRows < 0) ? with.callInTransactions(subquery, \"p\")\n\t\t\t\t\t: with.callInTransactions(subquery, numRows, \"p\"))\n\t\t\t\t.returning(\"u\")\n\t\t\t\t.build();\n\n\t\t\tString expected = \"MATCH (p:`Person`) WITH p CALL (p) {CREATE (p)-[:`IS`]->(u:`User`) RETURN u} IN TRANSACTIONS\";\n\t\t\tif (numRows > 0) {\n\t\t\t\texpected += \" OF \" + numRows + \" ROWS\";\n\t\t\t}\n\t\t\texpected += \" RETURN u\";\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"u\"));\n\t\t}\n\n\t\t@ParameterizedTest\n\t\t@ValueSource(ints = { -1, 23 })\n\t\tvoid afterRegularWithSymNameImport(int numRows) {\n\n\t\t\tSymbolicName p = Cypher.name(\"p\");\n\t\t\tResultStatement subquery = Cypher\n\t\t\t\t.create(Cypher.anyNode(p).relationshipTo(Cypher.node(\"User\").named(\"u\"), \"IS\"))\n\t\t\t\t.returning(Cypher.name(\"u\"))\n\t\t\t\t.build();\n\n\t\t\tStatementBuilder.OrderableOngoingReadingAndWithWithoutWhere with = Cypher\n\t\t\t\t.match(Cypher.node(\"Person\").named(p))\n\t\t\t\t.with(p);\n\t\t\tStatement statement = ((numRows < 0) ? with.callInTransactions(subquery, p)\n\t\t\t\t\t: with.callInTransactions(subquery, numRows, p))\n\t\t\t\t.returning(\"u\")\n\t\t\t\t.build();\n\n\t\t\tString expected = \"MATCH (p:`Person`) WITH p CALL (p) {CREATE (p)-[:`IS`]->(u:`User`) RETURN u} IN TRANSACTIONS\";\n\t\t\tif (numRows > 0) {\n\t\t\t\texpected += \" OF \" + numRows + \" ROWS\";\n\t\t\t}\n\t\t\texpected += \" RETURN u\";\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"u\"));\n\t\t}\n\n\t\t@Test\n\t\tvoid nestedAfterProcedureCall() {\n\n\t\t\t// With with\n\t\t\tStatement statement = Cypher.call(\"dbms.components\")\n\t\t\t\t.yield(\"name\")\n\t\t\t\t.with(\"name\")\n\t\t\t\t.callInTransactions(Cypher.with(\"name\")\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(Cypher.name(\"name\")))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CALL dbms.components() YIELD name WITH name CALL (name) {MATCH (n) WHERE n.name = name RETURN n} IN TRANSACTIONS RETURN n\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"n\"));\n\n\t\t\t// Without with\n\t\t\tstatement = Cypher.call(\"dbms.components\")\n\t\t\t\t.yield(\"name\")\n\t\t\t\t.callInTransactions(Cypher.with(\"name\")\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(Cypher.name(\"name\")))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CALL dbms.components() YIELD name CALL (name) {MATCH (n) WHERE n.name = name RETURN n} IN TRANSACTIONS RETURN n\");\n\n\t\t\t// After inQueryCall with with\n\t\t\tSymbolicName label = Cypher.name(\"label\");\n\t\t\tstatement = Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t.with(\"n\")\n\t\t\t\t.call(\"db.labels\")\n\t\t\t\t.yield(label)\n\t\t\t\t.with(label)\n\t\t\t\t.callInTransactions(Cypher.with(label)\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(label))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n) WITH n CALL db.labels() YIELD label WITH label CALL (label) {MATCH (n) WHERE n.name = label RETURN n} IN TRANSACTIONS RETURN n\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"n\"));\n\n\t\t\t// After inQueryCall without with\n\t\t\tstatement = Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t.with(\"n\")\n\t\t\t\t.call(\"db.labels\")\n\t\t\t\t.yield(label)\n\t\t\t\t.callInTransactions(Cypher.with(label)\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n2\"))\n\t\t\t\t\t.where(Cypher.property(\"n2\", \"name\").isEqualTo(label))\n\t\t\t\t\t.returning(\"n2\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n2\")\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n) WITH n CALL db.labels() YIELD label CALL (label) {MATCH (n2) WHERE n2.name = label RETURN n2} IN TRANSACTIONS RETURN n2\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass CollectSubqueries {\n\n\t\tprivate final Node person = Cypher.node(\"Person\").named(\"person\");\n\n\t\tprivate final Property personName = this.person.property(\"name\");\n\n\t\tprivate final Node dog = Cypher.node(\"Dog\").named(\"dog\");\n\n\t\tprivate final Property dogName = this.dog.property(\"name\");\n\n\t\tprivate final Relationship hasDog = this.person.relationshipTo(this.dog, \"HAS_DOG\");\n\n\t\tprivate final Node cat = Cypher.node(\"Cat\").named(\"cat\");\n\n\t\t@Test\n\t\tvoid shouldCheckForReturnStatement() {\n\n\t\t\tvar nonReturnStatement = Cypher.create(Cypher.node(\"Foo\")).build();\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.collect(nonReturnStatement))\n\t\t\t\t.withMessage(\n\t\t\t\t\t\t\"The final RETURN clause in a subquery used with COLLECT is mandatory and the RETURN clause must return exactly one column.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid simple() {\n\n\t\t\tvar inner = Cypher.match(this.person.relationshipTo(this.dog, \"HAS_DOG\")).returning(this.dogName).build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.where(Cypher.literalOf(\"Ozzy\").in(Cypher.collect(inner)))\n\t\t\t\t.returning(this.person.property(\"name\").as(\"name\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`) WHERE 'Ozzy' IN COLLECT { MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`) RETURN dog.name } RETURN person.name AS name\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withWhereClause() {\n\n\t\t\tvar r = this.hasDog.named(\"r\");\n\t\t\tvar inner = Cypher.match(r)\n\t\t\t\t.where(r.property(\"since\").gt(Cypher.literalOf(2017)))\n\t\t\t\t.returning(this.dogName)\n\t\t\t\t.build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.returning(this.person.property(\"name\").as(\"name\"), Cypher.collect(inner).as(\"youngDogs\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) \" + \"RETURN person.name AS name, COLLECT {\"\n\t\t\t\t\t+ \" MATCH (person)-[r:`HAS_DOG`]->(dog:`Dog`)\" + \" WHERE r.since > 2017\" + \" RETURN dog.name \"\n\t\t\t\t\t+ \"} AS youngDogs\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withAUnion() {\n\n\t\t\tvar hasCat = this.person.relationshipTo(this.cat, \"HAS_CAT\");\n\t\t\tvar inner = Cypher.union(Cypher.match(this.hasDog).returning(this.dogName.as(\"petName\")).build(),\n\t\t\t\t\tCypher.match(hasCat).returning(this.cat.property(\"name\").as(\"petName\")).build());\n\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.returning(this.person.property(\"name\").as(\"name\"), Cypher.collect(inner).as(\"petNames\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) \" + \"RETURN person.name AS name, \"\n\t\t\t\t\t+ \"COLLECT {\" + \" MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`)\" + \" RETURN dog.name AS petName\"\n\t\t\t\t\t+ \" UNION\" + \" MATCH (person)-[:`HAS_CAT`]->(cat:`Cat`)\" + \" RETURN cat.name AS petName \"\n\t\t\t\t\t+ \"} AS petNames\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withWith() {\n\n\t\t\tvar r = this.hasDog.named(\"r\");\n\t\t\tvar yearOfTheDog = Cypher.literalOf(2018).as(\"yearOfTheDog\");\n\t\t\tvar inner = Cypher.match(r).where(r.property(\"since\").eq(yearOfTheDog)).returning(this.dogName).build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.returning(this.person.property(\"name\").as(\"name\"),\n\t\t\t\t\t\tCypher.subqueryWith(yearOfTheDog).collect(inner).as(\"dogsOfTheYear\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) \" + \"RETURN person.name AS name, COLLECT {\"\n\t\t\t\t\t+ \" WITH 2018 AS yearOfTheDog\" + \" MATCH (person)-[r:`HAS_DOG`]->(dog:`Dog`)\"\n\t\t\t\t\t+ \" WHERE r.since = yearOfTheDog\" + \" RETURN dog.name \" + \"} AS dogsOfTheYear\");\n\t\t}\n\n\t\t@Test\n\t\tvoid inReturn() {\n\n\t\t\tvar toy = Cypher.node(\"Toy\").named(\"t\");\n\t\t\tvar inner = Cypher.match(this.hasDog)\n\t\t\t\t.match(this.dog.relationshipTo(toy, \"HAS_TOY\"))\n\t\t\t\t.returning(toy.property(\"name\"))\n\t\t\t\t.build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.returning(this.person.property(\"name\"), Cypher.collect(inner).as(\"toyNames\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) \" + \"RETURN person.name, \" + \"COLLECT {\"\n\t\t\t\t\t+ \" MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`)\" + \" MATCH (dog)-[:`HAS_TOY`]->(t:`Toy`)\"\n\t\t\t\t\t+ \" RETURN t.name \" + \"} AS toyNames\");\n\t\t}\n\n\t\t@Test\n\t\tvoid collectInSet() {\n\n\t\t\tvar inner = Cypher.match(this.hasDog).returning(this.dogName).build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.where(this.person.property(\"name\").eq(Cypher.literalOf(\"Peter\")))\n\t\t\t\t.set(this.person.property(\"dogNames\").to(Cypher.collect(inner)))\n\t\t\t\t.returning(this.person.property(\"dogNames\").as(\"dogNames\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) WHERE person.name = 'Peter' \"\n\t\t\t\t\t+ \"SET person.dogNames = COLLECT { MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`) RETURN dog.name } \"\n\t\t\t\t\t+ \"RETURN person.dogNames AS dogNames\");\n\t\t}\n\n\t\t@Test\n\t\tvoid inCase() {\n\n\t\t\tvar inner = Cypher.match(this.hasDog).returning(this.dogName).build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.returning(Cypher.caseExpression()\n\t\t\t\t\t.when(Cypher.collect(inner).eq(Cypher.listOf()))\n\t\t\t\t\t.then(Cypher.literalOf(\"No Dogs \").concat(this.personName))\n\t\t\t\t\t.elseDefault(this.personName)\n\t\t\t\t\t.as(\"result\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) \" + \"RETURN \" + \"CASE \"\n\t\t\t\t\t+ \"WHEN COLLECT { MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`) RETURN dog.name } = [] THEN ('No Dogs ' + person.name) \"\n\t\t\t\t\t+ \"ELSE person.name \" + \"END AS result\");\n\t\t}\n\n\t\t@Test\n\t\tvoid asGroupingKey() {\n\n\t\t\tvar inner = Cypher.match(this.hasDog).returning(this.dogName).build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.returning(Cypher.collect(inner).as(\"dogNames\"),\n\t\t\t\t\t\tCypher.avg(this.person.property(\"age\")).as(\"averageAge\"))\n\t\t\t\t.orderBy(Cypher.name(\"dogNames\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) \"\n\t\t\t\t\t+ \"RETURN COLLECT { MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`) RETURN dog.name } AS dogNames,\"\n\t\t\t\t\t+ \" avg(person.age) AS averageAge \" + \"ORDER BY dogNames\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/SubqueriesIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.net.URI;\n\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.CsvSource;\nimport org.junit.jupiter.params.provider.ValueSource;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Dialect;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n */\nclass SubqueriesIT {\n\n\tprivate static final Renderer cypherRenderer = Renderer\n\t\t.getRenderer(Configuration.newConfig().withDialect(Dialect.NEO4J_4).build());\n\n\t@Test // GH-533\n\tvoid unitSubqueries() {\n\n\t\tvar p = Cypher.node(\"Person\").named(\"p\");\n\t\tvar outer = Cypher.match(p);\n\t\tvar inner = Cypher.with(p)\n\t\t\t.unwind(Cypher.range(1, 5))\n\t\t\t.as(\"i\")\n\t\t\t.create(Cypher.node(\"Person\").withProperties(\"name\", p.property(\"name\")))\n\t\t\t.build();\n\n\t\tvar statement = outer.call(inner).returning(Cypher.count(Cypher.asterisk())).build();\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"MATCH (p:`Person`) CALL {WITH p UNWIND range(1, 5) AS i CREATE (:`Person` {name: p.name})} RETURN count(*)\");\n\t}\n\n\t@Nested\n\tclass Scope {\n\n\t\t@Test\n\t\tvoid nodePatternInCallMustBeFullAndNotKnown() {\n\t\t\tStatement parsed = Cypher.match(Cypher.node(\"Person\").named(\"n\"))\n\t\t\t\t.call(Cypher\n\t\t\t\t\t.match(Cypher.node(\"Movie\").named(\"n\").withProperties(\"title\", Cypher.literalOf(\"The Matrix\")))\n\t\t\t\t\t.where(Cypher.anyNode(\"n\").property(\"released\").gte(Cypher.literalOf(1980)))\n\t\t\t\t\t.returning(Cypher.anyNode(\"n\").as(\"m\"))\n\t\t\t\t\t.build())\n\t\t\t\t.returning(Cypher.anyNode(\"n\").property(\"name\"))\n\t\t\t\t.build();\n\t\t\tString cypher = Renderer.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).build())\n\t\t\t\t.render(parsed);\n\t\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\t\"MATCH (n:Person) CALL (*) {MATCH (n:Movie {title: 'The Matrix'}) WHERE n.released >= 1980 RETURN n AS m} RETURN n.name\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass DialectSupport {\n\n\t\t@ParameterizedTest\n\t\t@CsvSource(delimiterString = \"|\", textBlock = \"\"\"\n\t\t\t\tNEO4J_5|UNWIND [0, 1, 2] AS x CALL {RETURN 'hello' AS innerReturn} RETURN innerReturn\n\t\t\t\tNEO4J_5_23|UNWIND [0, 1, 2] AS x CALL (*) {RETURN 'hello' AS innerReturn} RETURN innerReturn\n\t\t\t\t\"\"\")\n\t\tvoid starterExample(Dialect dialect, String expected) {\n\t\t\tvar stmt = Cypher.unwind(Cypher.listOf(Cypher.literalOf(0), Cypher.literalOf(1), Cypher.literalOf(2)))\n\t\t\t\t.as(\"x\")\n\t\t\t\t.call(Cypher.returning(Cypher.literalOf(\"hello\").as(\"innerReturn\")).build())\n\t\t\t\t.returning(\"innerReturn\")\n\t\t\t\t.build();\n\n\t\t\tvar renderer = Renderer.getRenderer(Configuration.newConfig().withDialect(dialect).build());\n\t\t\tassertThat(renderer.render(stmt)).isEqualTo(expected);\n\t\t}\n\n\t\t@ParameterizedTest\n\t\t@CsvSource(delimiterString = \"|\",\n\t\t\t\ttextBlock = \"\"\"\n\t\t\t\t\t\tNEO4J_5|MATCH (p:Player), (t:Team) CALL {WITH p WITH p, rand() AS random SET p.rating = random RETURN p.name AS playerName, p.rating AS rating} RETURN playerName, rating, t AS team ORDER BY rating LIMIT 1\n\t\t\t\t\t\tNEO4J_5_23|MATCH (p:Player), (t:Team) CALL (p) {WITH p, rand() AS random SET p.rating = random RETURN p.name AS playerName, p.rating AS rating} RETURN playerName, rating, t AS team ORDER BY rating LIMIT 1\n\t\t\t\t\t\t\"\"\")\n\t\tvoid someImports(Dialect dialect, String expected) {\n\n\t\t\tvar p = Cypher.node(\"Player\").named(\"p\");\n\t\t\tvar t = Cypher.node(\"Team\").named(\"t\");\n\n\t\t\tvar rating = Cypher.name(\"rating\");\n\t\t\tvar playerName = Cypher.name(\"playerName\");\n\t\t\tvar stmt = Cypher.match(p, t)\n\t\t\t\t.call(Cypher.with(p, Cypher.rand().as(\"random\"))\n\t\t\t\t\t.set(p.property(\"rating\").to(Cypher.name(\"random\")))\n\t\t\t\t\t.returning(p.property(\"name\").as(playerName), p.property(\"rating\").as(rating))\n\t\t\t\t\t.build(), p)\n\t\t\t\t.returning(playerName, rating, t.as(\"team\"))\n\t\t\t\t.orderBy(rating)\n\t\t\t\t.limit(1)\n\t\t\t\t.build();\n\n\t\t\tvar renderer = Renderer\n\t\t\t\t.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).withDialect(dialect).build());\n\t\t\tassertThat(renderer.render(stmt)).isEqualTo(expected);\n\t\t}\n\n\t\t@ParameterizedTest\n\t\t@CsvSource(delimiterString = \"|\", textBlock = \"\"\"\n\t\t\t\tNEO4J_5|MATCH (p:Player), (t:Team) CALL {WITH * RETURN p AS player, t AS team} RETURN player, team\n\t\t\t\tNEO4J_5_23|MATCH (p:Player), (t:Team) CALL (*) {RETURN p AS player, t AS team} RETURN player, team\n\t\t\t\t\"\"\")\n\t\tvoid allImports(Dialect dialect, String expected) {\n\n\t\t\tvar p = Cypher.node(\"Player\").named(\"p\");\n\t\t\tvar t = Cypher.node(\"Team\").named(\"t\");\n\n\t\t\tvar player = Cypher.name(\"player\");\n\t\t\tvar stmt = Cypher.match(p, t)\n\t\t\t\t.call(Cypher.returning(p.as(\"player\"), t.as(\"team\")).build(), Cypher.asterisk())\n\t\t\t\t.returning(player, Cypher.name(\"team\"))\n\t\t\t\t.build();\n\n\t\t\tvar renderer = Renderer\n\t\t\t\t.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).withDialect(dialect).build());\n\t\t\tassertThat(renderer.render(stmt)).isEqualTo(expected);\n\t\t}\n\n\t\t@ParameterizedTest\n\t\t@CsvSource(delimiterString = \"|\",\n\t\t\t\ttextBlock = \"\"\"\n\t\t\t\t\t\tNEO4J_5|MATCH (t:Team) CALL {MATCH (p:Player) RETURN count(p) AS totalPlayers} RETURN count(t) AS totalTeams, totalPlayers\n\t\t\t\t\t\tNEO4J_5_23|MATCH (t:Team) CALL (*) {MATCH (p:Player) RETURN count(p) AS totalPlayers} RETURN count(t) AS totalTeams, totalPlayers\n\t\t\t\t\t\t\"\"\")\n\t\tvoid noImports(Dialect dialect, String expected) {\n\n\t\t\tvar p = Cypher.node(\"Player\").named(\"p\");\n\t\t\tvar t = Cypher.node(\"Team\").named(\"t\");\n\n\t\t\tvar stmt = Cypher.match(t)\n\t\t\t\t.call(Cypher.match(p).returning(Cypher.count(p).as(\"totalPlayers\")).build())\n\t\t\t\t.returning(Cypher.count(t).as(\"totalTeams\"), Cypher.name(\"totalPlayers\"))\n\t\t\t\t.build();\n\n\t\t\tvar renderer = Renderer\n\t\t\t\t.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).withDialect(dialect).build());\n\t\t\tassertThat(renderer.render(stmt)).isEqualTo(expected);\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass ResultReturningSubqueries {\n\n\t\t@Test\n\t\tvoid importingVariablesShouldWork() {\n\n\t\t\tStatement statement = Cypher.unwind(Cypher.literalOf(0), Cypher.literalOf(1), Cypher.literalOf(2))\n\t\t\t\t.as(\"x\")\n\t\t\t\t.call(Cypher.with(Cypher.name(\"x\"))\n\t\t\t\t\t.returning(Cypher.name(\"x\").multiply(Cypher.literalOf(10)).as(\"y\"))\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"x\", \"y\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"UNWIND [0, 1, 2] AS x CALL {WITH x RETURN (x * 10) AS y} RETURN x, y\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"x\"), SymbolicName.of(\"y\"));\n\t\t}\n\n\t\t@Test\n\t\tvoid postUnionProcessingShouldWork() {\n\n\t\t\tProperty ageProperty = Cypher.property(\"p\", \"age\");\n\t\t\tProperty nameProperty = Cypher.property(\"p\", \"name\");\n\n\t\t\t// This must be 2 different person nodes and statement, otherwise the union\n\t\t\t// will reuse it.\n\t\t\tStatement s1 = Cypher.match(Cypher.node(\"Person\").named(\"p\"))\n\t\t\t\t.returning(\"p\")\n\t\t\t\t.orderBy(ageProperty.ascending())\n\t\t\t\t.limit(1)\n\t\t\t\t.build();\n\t\t\tStatement s2 = Cypher.match(Cypher.node(\"Person\").named(\"p\"))\n\t\t\t\t.returning(\"p\")\n\t\t\t\t.orderBy(ageProperty.descending())\n\t\t\t\t.limit(1)\n\t\t\t\t.build();\n\n\t\t\tStatement statement = Cypher.call(Cypher.union(s1, s2))\n\t\t\t\t.returning(nameProperty, ageProperty)\n\t\t\t\t.orderBy(nameProperty)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CALL {MATCH (p:`Person`) RETURN p ORDER BY p.age ASC LIMIT 1 UNION MATCH (p:`Person`) RETURN p ORDER BY p.age DESC LIMIT 1} RETURN p.name, p.age ORDER BY p.name\");\n\t\t}\n\n\t\t@Test\n\t\tvoid aggregationAndSideEffectsShouldWork() {\n\n\t\t\tNode person = Cypher.node(\"Person\").named(\"p\");\n\t\t\tNode clone = Cypher.node(\"Clone\").named(\"c\");\n\t\t\tStatement statement = Cypher.match(person)\n\t\t\t\t.call(Cypher.unwind(Cypher.range(1, 5))\n\t\t\t\t\t.as(\"i\")\n\t\t\t\t\t.create(clone)\n\t\t\t\t\t.returning(Cypher.count(clone).as(\"numberOfClones\"))\n\t\t\t\t\t.build())\n\t\t\t\t.returning(person.property(\"name\"), Cypher.name(\"numberOfClones\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (p:`Person`) CALL {UNWIND range(1, 5) AS i CREATE (c:`Clone`) RETURN count(c) AS numberOfClones} RETURN p.name, numberOfClones\");\n\t\t}\n\n\t\t@Test\n\t\tvoid aggregationOnImportedVariablesShouldWork() {\n\n\t\t\tNode person = Cypher.node(\"Person\").named(\"p\");\n\t\t\tNode other = Cypher.node(\"Person\").named(\"other\");\n\t\t\tStatement statement = Cypher.match(person)\n\t\t\t\t.call(Cypher.with(person)\n\t\t\t\t\t.match(other)\n\t\t\t\t\t.where(other.property(\"age\").lt(person.property(\"age\")))\n\t\t\t\t\t.returning(Cypher.count(other).as(\"youngerPersonsCount\"))\n\t\t\t\t\t.build())\n\t\t\t\t.returning(person.property(\"name\"), Cypher.name(\"youngerPersonsCount\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (p:`Person`) CALL {WITH p MATCH (other:`Person`) WHERE other.age < p.age RETURN count(other) AS youngerPersonsCount} RETURN p.name, youngerPersonsCount\");\n\t\t}\n\n\t\t@Test\n\t\tvoid nestedAfterProcedureCall() {\n\n\t\t\t// With with\n\t\t\tStatement statement = Cypher.call(\"dbms.components\")\n\t\t\t\t.yield(\"name\")\n\t\t\t\t.with(\"name\")\n\t\t\t\t.call(Cypher.with(\"name\")\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(Cypher.name(\"name\")))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CALL dbms.components() YIELD name WITH name CALL {WITH name MATCH (n) WHERE n.name = name RETURN n} RETURN n\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"n\"));\n\n\t\t\t// Without with\n\t\t\tstatement = Cypher.call(\"dbms.components\")\n\t\t\t\t.yield(\"name\")\n\t\t\t\t.call(Cypher.with(\"name\")\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(Cypher.name(\"name\")))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CALL dbms.components() YIELD name CALL {WITH name MATCH (n) WHERE n.name = name RETURN n} RETURN n\");\n\n\t\t\t// After inQueryCall with with\n\t\t\tSymbolicName label = Cypher.name(\"label\");\n\t\t\tstatement = Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t.with(\"n\")\n\t\t\t\t.call(\"db.labels\")\n\t\t\t\t.yield(label)\n\t\t\t\t.with(label)\n\t\t\t\t.call(Cypher.with(label)\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(label))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n) WITH n CALL db.labels() YIELD label WITH label CALL {WITH label MATCH (n) WHERE n.name = label RETURN n} RETURN n\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"n\"));\n\n\t\t\t// After inQueryCall without with\n\t\t\tstatement = Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t.with(\"n\")\n\t\t\t\t.call(\"db.labels\")\n\t\t\t\t.yield(label)\n\t\t\t\t.call(Cypher.with(label)\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n2\"))\n\t\t\t\t\t.where(Cypher.property(\"n2\", \"name\").isEqualTo(label))\n\t\t\t\t\t.returning(\"n2\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n2\")\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n) WITH n CALL db.labels() YIELD label CALL {WITH label MATCH (n2) WHERE n2.name = label RETURN n2} RETURN n2\");\n\t\t}\n\n\t\t@Test\n\t\tvoid afterRegularWith() {\n\n\t\t\tStatement statement = Cypher.match(Cypher.node(\"Person\").named(\"p\"))\n\t\t\t\t.with(\"p\")\n\t\t\t\t.call(Cypher.with(\"p\")\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(Cypher.property(\"p\", \"name\")))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (p:`Person`) WITH p CALL {WITH p MATCH (n) WHERE n.name = p.name RETURN n} RETURN n\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"n\"));\n\t\t}\n\n\t\t@Test\n\t\tvoid afterRegularWithManualImport() {\n\n\t\t\tStatement statement = Cypher.match(Cypher.node(\"Person\").named(\"p\"))\n\t\t\t\t.with(\"p\")\n\t\t\t\t.call(Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(Cypher.property(\"p\", \"name\")))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build(), \"p\")\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (p:`Person`) WITH p CALL {WITH p MATCH (n) WHERE n.name = p.name RETURN n} RETURN n\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"n\"));\n\t\t}\n\n\t\t@Test\n\t\tvoid callsCallingCalls() {\n\n\t\t\tStatement someStatement = Cypher.match(Cypher.anyNode().named(\"n\")).returning(\"n\").build();\n\t\t\tStatement statement = someStatement;\n\n\t\t\tfor (int i = 0; i < 5; ++i) {\n\t\t\t\tstatement = Cypher.call(statement).returning(\"n\").build();\n\t\t\t}\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CALL {CALL {CALL {CALL {CALL {MATCH (n) RETURN n} RETURN n} RETURN n} RETURN n} RETURN n} RETURN n\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass ExistentialSubqueries {\n\n\t\t@Test // GH-578\n\t\tvoid fullStatementsAsExistentialSubQuery() {\n\n\t\t\tNode p = Cypher.node(\"Person\").named(\"person\");\n\t\t\tStatement inner = Cypher.match(p.relationshipTo(Cypher.node(\"Dog\"), \"HAS_DOG\"))\n\t\t\t\t.returning(p.property(\"name\"))\n\t\t\t\t.build();\n\t\t\tStatement outer = Cypher.match(p)\n\t\t\t\t.where(Cypher.exists(inner))\n\t\t\t\t.returning(p.property(\"name\").as(\"name\"))\n\t\t\t\t.build();\n\n\t\t\tString cypher = outer.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`) WHERE EXISTS { MATCH (person)-[:`HAS_DOG`]->(:`Dog`) RETURN person.name } RETURN person.name AS name\");\n\t\t}\n\n\t\t@Test // GH-578\n\t\tvoid fullStatementsAsExistentialSubQueryWithImports() {\n\n\t\t\tNode p = Cypher.node(\"Person\").named(\"person\");\n\t\t\tNode d = Cypher.node(\"Dog\").named(\"d\");\n\t\t\tSymbolicName dogName = Cypher.name(\"dogName\");\n\t\t\tStatement inner = Cypher.match(p.relationshipTo(d, \"HAS_DOG\"))\n\t\t\t\t.where(d.property(\"name\").eq(dogName))\n\t\t\t\t.returning(p.property(\"name\"))\n\t\t\t\t.build();\n\t\t\tStatement outer = Cypher.match(p)\n\t\t\t\t.where(Cypher.exists(inner, Cypher.literalOf(\"Ozzy\").as(dogName)))\n\t\t\t\t.returning(p.property(\"name\").as(\"name\"))\n\t\t\t\t.build();\n\n\t\t\tString cypher = outer.getCypher();\n\t\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`) WHERE EXISTS { WITH 'Ozzy' AS dogName MATCH (person)-[:`HAS_DOG`]->(d:`Dog`) WHERE d.name = dogName RETURN person.name } RETURN person.name AS name\");\n\t\t}\n\n\t\t@Test\n\t\tvoid simple() {\n\n\t\t\tNode p = Cypher.node(\"Person\").named(\"p\");\n\t\t\tNode friend = Cypher.node(\"Person\").named(\"friend\");\n\n\t\t\tRelationship r = p.relationshipTo(friend, \"IS_FRIENDS_WITH\").named(\"r\");\n\t\t\tStatement statement = Cypher.match(r)\n\t\t\t\t.where(Cypher\n\t\t\t\t\t.match(p.relationshipTo(Cypher.node(\"Company\").withProperties(\"name\", Cypher.literalOf(\"Neo4j\")),\n\t\t\t\t\t\t\t\"WORKS_FOR\"))\n\t\t\t\t\t.asCondition())\n\t\t\t\t.returning(p, r, friend)\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (p:`Person`)-[r:`IS_FRIENDS_WITH`]->(friend:`Person`) WHERE EXISTS { MATCH (p)-[:`WORKS_FOR`]->(:`Company` {name: 'Neo4j'}) } RETURN p, r, friend\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withBooleanOpsAndWhere() {\n\n\t\t\tNode p = Cypher.node(\"Person\").named(\"person\");\n\t\t\tNode company = Cypher.anyNode().named(\"company\");\n\t\t\tNode t = Cypher.node(\"Technology\").named(\"t\");\n\n\t\t\tStatement statement = Cypher.match(p.relationshipTo(company, \"WORKS_FOR\"))\n\t\t\t\t.where(company.property(\"name\").startsWith(Cypher.literalOf(\"Company\")))\n\t\t\t\t.and(Cypher.match(p.relationshipTo(t, \"LIKES\"))\n\t\t\t\t\t.where(Cypher.size(t.relationshipFrom(Cypher.anyNode(), \"LIKES\")).gte(Cypher.literalOf(3)))\n\t\t\t\t\t.asCondition())\n\t\t\t\t.returning(p.property(\"name\").as(\"person\"), company.property(\"name\").as(\"company\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`)-[:`WORKS_FOR`]->(company) WHERE (company.name STARTS WITH 'Company' AND EXISTS { MATCH (person)-[:`LIKES`]->(t:`Technology`) WHERE size((t)<-[:`LIKES`]-()) >= 3 }) RETURN person.name AS person, company.name AS company\");\n\n\t\t\tstatement = Cypher.match(p.relationshipTo(company, \"WORKS_FOR\"))\n\t\t\t\t.where(Cypher.match(p.relationshipTo(t, \"LIKES\"))\n\t\t\t\t\t.where(Cypher.size(t.relationshipFrom(Cypher.anyNode(), \"LIKES\")).gte(Cypher.literalOf(3)))\n\t\t\t\t\t.asCondition())\n\t\t\t\t.and(company.property(\"name\").startsWith(Cypher.literalOf(\"Company\")))\n\t\t\t\t.returning(p.property(\"name\").as(\"person\"), company.property(\"name\").as(\"company\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`)-[:`WORKS_FOR`]->(company) WHERE (EXISTS { MATCH (person)-[:`LIKES`]->(t:`Technology`) WHERE size((t)<-[:`LIKES`]-()) >= 3 } AND company.name STARTS WITH 'Company') RETURN person.name AS person, company.name AS company\");\n\n\t\t\tstatement = Cypher.match(p.relationshipTo(company, \"WORKS_FOR\"))\n\t\t\t\t.where(Cypher.match(p.relationshipTo(t, \"LIKES\"))\n\t\t\t\t\t.where(Cypher.size(t.relationshipFrom(Cypher.anyNode(), \"LIKES\")).gte(Cypher.literalOf(3)))\n\t\t\t\t\t.asCondition()\n\t\t\t\t\t.and(company.property(\"name\").startsWith(Cypher.literalOf(\"Company\"))))\n\t\t\t\t.returning(p.property(\"name\").as(\"person\"), company.property(\"name\").as(\"company\"))\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`)-[:`WORKS_FOR`]->(company) WHERE (EXISTS { MATCH (person)-[:`LIKES`]->(t:`Technology`) WHERE size((t)<-[:`LIKES`]-()) >= 3 } AND company.name STARTS WITH 'Company') RETURN person.name AS person, company.name AS company\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass InTransactions {\n\n\t\t@Test\n\t\tvoid docs44_7() {\n\n\t\t\tSymbolicName line = Cypher.name(\"line\");\n\t\t\tStatement statement = Cypher.loadCSV(URI.create(\"file:///friends.csv\"))\n\t\t\t\t.as(\"line\")\n\t\t\t\t.callInTransactions(Cypher.with(\"line\")\n\t\t\t\t\t.create(Cypher.node(\"Person\")\n\t\t\t\t\t\t.withProperties(\"name\", Cypher.valueAt(line, 1), \"age\",\n\t\t\t\t\t\t\t\tCypher.toInteger(Cypher.valueAt(line, 2))))\n\t\t\t\t\t.build())\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"LOAD CSV FROM 'file:///friends.csv' AS line CALL {WITH line CREATE (:`Person` {name: line[1], age: toInteger(line[2])})} IN TRANSACTIONS\");\n\t\t}\n\n\t\t@Test\n\t\tvoid docs44_7_1a() {\n\n\t\t\tSymbolicName line = Cypher.name(\"line\");\n\t\t\tStatement statement = Cypher.loadCSV(URI.create(\"file:///friends.csv\"))\n\t\t\t\t.as(\"line\")\n\t\t\t\t.callInTransactions(Cypher.with(\"line\")\n\t\t\t\t\t.create(Cypher.node(\"Person\")\n\t\t\t\t\t\t.withProperties(\"name\", Cypher.valueAt(line, 1), \"age\",\n\t\t\t\t\t\t\t\tCypher.toInteger(Cypher.valueAt(line, 2))))\n\t\t\t\t\t.build(), 2)\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"LOAD CSV FROM 'file:///friends.csv' AS line CALL {WITH line CREATE (:`Person` {name: line[1], age: toInteger(line[2])})} IN TRANSACTIONS OF 2 ROWS\");\n\t\t}\n\n\t\t@Test\n\t\tvoid docs44_7_1b() {\n\n\t\t\tStatement statement = Cypher.match(Cypher.anyNode(\"n\"))\n\t\t\t\t.callInTransactions(Cypher.with(\"n\").detachDelete(\"n\").build(), 2)\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t\t.isEqualTo(\"MATCH (n) CALL {WITH n DETACH DELETE n} IN TRANSACTIONS OF 2 ROWS\");\n\t\t}\n\n\t\t@ParameterizedTest\n\t\t@ValueSource(ints = { -1, 23 })\n\t\tvoid afterRegularWith(int numRows) {\n\n\t\t\tResultStatement subquery = Cypher\n\t\t\t\t.create(Cypher.anyNode(\"p\").relationshipTo(Cypher.node(\"User\").named(\"u\"), \"IS\"))\n\t\t\t\t.returning(Cypher.name(\"u\"))\n\t\t\t\t.build();\n\n\t\t\tStatementBuilder.OrderableOngoingReadingAndWithWithoutWhere with = Cypher\n\t\t\t\t.match(Cypher.node(\"Person\").named(\"p\"))\n\t\t\t\t.with(\"p\");\n\t\t\tStatement statement = ((numRows < 0) ? with.callInTransactions(subquery, \"p\")\n\t\t\t\t\t: with.callInTransactions(subquery, numRows, \"p\"))\n\t\t\t\t.returning(\"u\")\n\t\t\t\t.build();\n\n\t\t\tString expected = \"MATCH (p:`Person`) WITH p CALL {WITH p CREATE (p)-[:`IS`]->(u:`User`) RETURN u} IN TRANSACTIONS\";\n\t\t\tif (numRows > 0) {\n\t\t\t\texpected += \" OF \" + numRows + \" ROWS\";\n\t\t\t}\n\t\t\texpected += \" RETURN u\";\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"u\"));\n\t\t}\n\n\t\t@ParameterizedTest\n\t\t@ValueSource(ints = { -1, 23 })\n\t\tvoid afterRegularWithSymNameImport(int numRows) {\n\n\t\t\tSymbolicName p = Cypher.name(\"p\");\n\t\t\tResultStatement subquery = Cypher\n\t\t\t\t.create(Cypher.anyNode(p).relationshipTo(Cypher.node(\"User\").named(\"u\"), \"IS\"))\n\t\t\t\t.returning(Cypher.name(\"u\"))\n\t\t\t\t.build();\n\n\t\t\tStatementBuilder.OrderableOngoingReadingAndWithWithoutWhere with = Cypher\n\t\t\t\t.match(Cypher.node(\"Person\").named(p))\n\t\t\t\t.with(p);\n\t\t\tStatement statement = ((numRows < 0) ? with.callInTransactions(subquery, p)\n\t\t\t\t\t: with.callInTransactions(subquery, numRows, p))\n\t\t\t\t.returning(\"u\")\n\t\t\t\t.build();\n\n\t\t\tString expected = \"MATCH (p:`Person`) WITH p CALL {WITH p CREATE (p)-[:`IS`]->(u:`User`) RETURN u} IN TRANSACTIONS\";\n\t\t\tif (numRows > 0) {\n\t\t\t\texpected += \" OF \" + numRows + \" ROWS\";\n\t\t\t}\n\t\t\texpected += \" RETURN u\";\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(expected);\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"u\"));\n\t\t}\n\n\t\t@Test\n\t\tvoid nestedAfterProcedureCall() {\n\n\t\t\t// With with\n\t\t\tStatement statement = Cypher.call(\"dbms.components\")\n\t\t\t\t.yield(\"name\")\n\t\t\t\t.with(\"name\")\n\t\t\t\t.callInTransactions(Cypher.with(\"name\")\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(Cypher.name(\"name\")))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CALL dbms.components() YIELD name WITH name CALL {WITH name MATCH (n) WHERE n.name = name RETURN n} IN TRANSACTIONS RETURN n\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"n\"));\n\n\t\t\t// Without with\n\t\t\tstatement = Cypher.call(\"dbms.components\")\n\t\t\t\t.yield(\"name\")\n\t\t\t\t.callInTransactions(Cypher.with(\"name\")\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(Cypher.name(\"name\")))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"CALL dbms.components() YIELD name CALL {WITH name MATCH (n) WHERE n.name = name RETURN n} IN TRANSACTIONS RETURN n\");\n\n\t\t\t// After inQueryCall with with\n\t\t\tSymbolicName label = Cypher.name(\"label\");\n\t\t\tstatement = Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t.with(\"n\")\n\t\t\t\t.call(\"db.labels\")\n\t\t\t\t.yield(label)\n\t\t\t\t.with(label)\n\t\t\t\t.callInTransactions(Cypher.with(label)\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t\t.where(Cypher.property(\"n\", \"name\").isEqualTo(label))\n\t\t\t\t\t.returning(\"n\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n\")\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n) WITH n CALL db.labels() YIELD label WITH label CALL {WITH label MATCH (n) WHERE n.name = label RETURN n} IN TRANSACTIONS RETURN n\");\n\n\t\t\tassertThat(statement.getCatalog().getIdentifiableExpressions())\n\t\t\t\t.containsExactlyInAnyOrder(SymbolicName.of(\"n\"));\n\n\t\t\t// After inQueryCall without with\n\t\t\tstatement = Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t\t.with(\"n\")\n\t\t\t\t.call(\"db.labels\")\n\t\t\t\t.yield(label)\n\t\t\t\t.callInTransactions(Cypher.with(label)\n\t\t\t\t\t.match(Cypher.anyNode().named(\"n2\"))\n\t\t\t\t\t.where(Cypher.property(\"n2\", \"name\").isEqualTo(label))\n\t\t\t\t\t.returning(\"n2\")\n\t\t\t\t\t.build())\n\t\t\t\t.returning(\"n2\")\n\t\t\t\t.build();\n\t\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\t\"MATCH (n) WITH n CALL db.labels() YIELD label CALL {WITH label MATCH (n2) WHERE n2.name = label RETURN n2} IN TRANSACTIONS RETURN n2\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass CollectSubqueries {\n\n\t\tprivate final Node person = Cypher.node(\"Person\").named(\"person\");\n\n\t\tprivate final Property personName = this.person.property(\"name\");\n\n\t\tprivate final Node dog = Cypher.node(\"Dog\").named(\"dog\");\n\n\t\tprivate final Property dogName = this.dog.property(\"name\");\n\n\t\tprivate final Relationship hasDog = this.person.relationshipTo(this.dog, \"HAS_DOG\");\n\n\t\tprivate final Node cat = Cypher.node(\"Cat\").named(\"cat\");\n\n\t\t@Test\n\t\tvoid shouldCheckForReturnStatement() {\n\n\t\t\tvar nonReturnStatement = Cypher.create(Cypher.node(\"Foo\")).build();\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.collect(nonReturnStatement))\n\t\t\t\t.withMessage(\n\t\t\t\t\t\t\"The final RETURN clause in a subquery used with COLLECT is mandatory and the RETURN clause must return exactly one column.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid simple() {\n\n\t\t\tvar inner = Cypher.match(this.person.relationshipTo(this.dog, \"HAS_DOG\")).returning(this.dogName).build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.where(Cypher.literalOf(\"Ozzy\").in(Cypher.collect(inner)))\n\t\t\t\t.returning(this.person.property(\"name\").as(\"name\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\n\t\t\t\t\t\"MATCH (person:`Person`) WHERE 'Ozzy' IN COLLECT { MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`) RETURN dog.name } RETURN person.name AS name\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withWhereClause() {\n\n\t\t\tvar r = this.hasDog.named(\"r\");\n\t\t\tvar inner = Cypher.match(r)\n\t\t\t\t.where(r.property(\"since\").gt(Cypher.literalOf(2017)))\n\t\t\t\t.returning(this.dogName)\n\t\t\t\t.build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.returning(this.person.property(\"name\").as(\"name\"), Cypher.collect(inner).as(\"youngDogs\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) \" + \"RETURN person.name AS name, COLLECT {\"\n\t\t\t\t\t+ \" MATCH (person)-[r:`HAS_DOG`]->(dog:`Dog`)\" + \" WHERE r.since > 2017\" + \" RETURN dog.name \"\n\t\t\t\t\t+ \"} AS youngDogs\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withAUnion() {\n\n\t\t\tvar hasCat = this.person.relationshipTo(this.cat, \"HAS_CAT\");\n\t\t\tvar inner = Cypher.union(Cypher.match(this.hasDog).returning(this.dogName.as(\"petName\")).build(),\n\t\t\t\t\tCypher.match(hasCat).returning(this.cat.property(\"name\").as(\"petName\")).build());\n\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.returning(this.person.property(\"name\").as(\"name\"), Cypher.collect(inner).as(\"petNames\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) \" + \"RETURN person.name AS name, \"\n\t\t\t\t\t+ \"COLLECT {\" + \" MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`)\" + \" RETURN dog.name AS petName\"\n\t\t\t\t\t+ \" UNION\" + \" MATCH (person)-[:`HAS_CAT`]->(cat:`Cat`)\" + \" RETURN cat.name AS petName \"\n\t\t\t\t\t+ \"} AS petNames\");\n\t\t}\n\n\t\t@Test\n\t\tvoid withWith() {\n\n\t\t\tvar r = this.hasDog.named(\"r\");\n\t\t\tvar yearOfTheDog = Cypher.literalOf(2018).as(\"yearOfTheDog\");\n\t\t\tvar inner = Cypher.match(r).where(r.property(\"since\").eq(yearOfTheDog)).returning(this.dogName).build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.returning(this.person.property(\"name\").as(\"name\"),\n\t\t\t\t\t\tCypher.subqueryWith(yearOfTheDog).collect(inner).as(\"dogsOfTheYear\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) \" + \"RETURN person.name AS name, COLLECT {\"\n\t\t\t\t\t+ \" WITH 2018 AS yearOfTheDog\" + \" MATCH (person)-[r:`HAS_DOG`]->(dog:`Dog`)\"\n\t\t\t\t\t+ \" WHERE r.since = yearOfTheDog\" + \" RETURN dog.name \" + \"} AS dogsOfTheYear\");\n\t\t}\n\n\t\t@Test\n\t\tvoid inReturn() {\n\n\t\t\tvar toy = Cypher.node(\"Toy\").named(\"t\");\n\t\t\tvar inner = Cypher.match(this.hasDog)\n\t\t\t\t.match(this.dog.relationshipTo(toy, \"HAS_TOY\"))\n\t\t\t\t.returning(toy.property(\"name\"))\n\t\t\t\t.build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.returning(this.person.property(\"name\"), Cypher.collect(inner).as(\"toyNames\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) \" + \"RETURN person.name, \" + \"COLLECT {\"\n\t\t\t\t\t+ \" MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`)\" + \" MATCH (dog)-[:`HAS_TOY`]->(t:`Toy`)\"\n\t\t\t\t\t+ \" RETURN t.name \" + \"} AS toyNames\");\n\t\t}\n\n\t\t@Test\n\t\tvoid collectInSet() {\n\n\t\t\tvar inner = Cypher.match(this.hasDog).returning(this.dogName).build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.where(this.person.property(\"name\").eq(Cypher.literalOf(\"Peter\")))\n\t\t\t\t.set(this.person.property(\"dogNames\").to(Cypher.collect(inner)))\n\t\t\t\t.returning(this.person.property(\"dogNames\").as(\"dogNames\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) WHERE person.name = 'Peter' \"\n\t\t\t\t\t+ \"SET person.dogNames = COLLECT { MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`) RETURN dog.name } \"\n\t\t\t\t\t+ \"RETURN person.dogNames AS dogNames\");\n\t\t}\n\n\t\t@Test\n\t\tvoid inCase() {\n\n\t\t\tvar inner = Cypher.match(this.hasDog).returning(this.dogName).build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.returning(Cypher.caseExpression()\n\t\t\t\t\t.when(Cypher.collect(inner).eq(Cypher.listOf()))\n\t\t\t\t\t.then(Cypher.literalOf(\"No Dogs \").concat(this.personName))\n\t\t\t\t\t.elseDefault(this.personName)\n\t\t\t\t\t.as(\"result\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) \" + \"RETURN \" + \"CASE \"\n\t\t\t\t\t+ \"WHEN COLLECT { MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`) RETURN dog.name } = [] THEN ('No Dogs ' + person.name) \"\n\t\t\t\t\t+ \"ELSE person.name \" + \"END AS result\");\n\t\t}\n\n\t\t@Test\n\t\tvoid asGroupingKey() {\n\n\t\t\tvar inner = Cypher.match(this.hasDog).returning(this.dogName).build();\n\t\t\tvar stmt = Cypher.match(this.person)\n\t\t\t\t.returning(Cypher.collect(inner).as(\"dogNames\"),\n\t\t\t\t\t\tCypher.avg(this.person.property(\"age\")).as(\"averageAge\"))\n\t\t\t\t.orderBy(Cypher.name(\"dogNames\"))\n\t\t\t\t.build();\n\t\t\tassertThat(stmt.getCypher()).isEqualTo(\"MATCH (person:`Person`) \"\n\t\t\t\t\t+ \"RETURN COLLECT { MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`) RETURN dog.name } AS dogNames,\"\n\t\t\t\t\t+ \" avg(person.age) AS averageAge \" + \"ORDER BY dogNames\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/SymbolicNameTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n *\n */\npublic class SymbolicNameTests {\n\n\t@Nested\n\tclass ResolvedSymbolicNames {\n\n\t\t@Test\n\t\tvoid equalsShouldWorkSameValue() {\n\n\t\t\tSymbolicName name1 = SymbolicName.of(\"a\");\n\t\t\tSymbolicName name2 = name1;\n\t\t\tSymbolicName name3 = SymbolicName.of(\"a\");\n\n\t\t\tassertThat(name1).isEqualTo(name2).isEqualTo(name3);\n\t\t}\n\n\t\t@Test\n\t\tvoid equalsShouldWorkDifferentValue() {\n\n\t\t\tSymbolicName name1 = SymbolicName.of(\"a\");\n\t\t\tSymbolicName name2 = SymbolicName.of(\"b\");\n\n\t\t\tassertThat(name1).isNotEqualTo(name2);\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldNotEqualUnresolved() {\n\n\t\t\tSymbolicName name1 = SymbolicName.of(\"a\");\n\n\t\t\tassertThat(name1).isNotEqualTo(SymbolicName.unresolved());\n\t\t}\n\n\t\t@Test\n\t\tvoid sameResolvedNamesShouldHaveSameHashCodes() {\n\n\t\t\tSymbolicName name1 = SymbolicName.of(\"a\");\n\t\t\tSymbolicName name2 = SymbolicName.of(\"a\");\n\t\t\tassertThat(name1).hasSameHashCodeAs(name2);\n\t\t}\n\n\t\t@Test\n\t\tvoid differentResolvedNamesShouldHaveDifferentHashCodes() {\n\n\t\t\tSymbolicName name1 = SymbolicName.of(\"a\");\n\t\t\tSymbolicName name2 = SymbolicName.of(\"b\");\n\t\t\tassertThat(name1.hashCode()).isNotEqualTo(name2.hashCode());\n\t\t}\n\n\t\t@Test\n\t\tvoid toStringShouldWork() {\n\n\t\t\tSymbolicName name1 = SymbolicName.of(\"a\");\n\t\t\tassertThat(name1).hasToString(\"SymbolicName{cypher=a}\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass UnresolvedSymbolicNames {\n\n\t\t@Test\n\t\tvoid equalsShouldWorkSameValue() {\n\n\t\t\tSymbolicName name1 = SymbolicName.unresolved();\n\t\t\tSymbolicName name2 = name1;\n\t\t\tSymbolicName name3 = SymbolicName.unresolved();\n\n\t\t\tassertThat(name1).isEqualTo(name2).isNotEqualTo(name3);\n\t\t\tassertThat(name2).isNotEqualTo(name3);\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldNotEqualResolved() {\n\n\t\t\tSymbolicName name1 = SymbolicName.unresolved();\n\n\t\t\tassertThat(name1).isNotEqualTo(SymbolicName.of(\"a\"));\n\t\t}\n\n\t\t@Test\n\t\tvoid differentUnresolvedNamesShouldHaveDifferentHashCodes() {\n\n\t\t\tSymbolicName name1 = SymbolicName.unresolved();\n\t\t\tSymbolicName name2 = SymbolicName.unresolved();\n\t\t\tassertThat(name1.hashCode()).isNotEqualTo(name2.hashCode());\n\t\t}\n\n\t\t@Test\n\t\tvoid toStringShouldWork() {\n\n\t\t\tSymbolicName name1 = SymbolicName.unresolved();\n\t\t\tassertThat(name1).hasToString(\"Unresolved SymbolicName\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/TemporalLiteralTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.time.LocalTime;\nimport java.time.OffsetTime;\nimport java.time.ZoneId;\nimport java.time.ZoneOffset;\nimport java.time.ZonedDateTime;\nimport java.time.temporal.TemporalAccessor;\nimport java.time.temporal.TemporalField;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n *\n */\nclass TemporalLiteralTests {\n\n\t@Test\n\tvoid localDateShouldWork() {\n\n\t\tTemporalLiteral literal = new TemporalLiteral(LocalDate.of(2021, 3, 10));\n\t\tassertThat(literal.asString()).isEqualTo(\"date('2021-03-10')\");\n\t}\n\n\t@Test\n\tvoid localDateTimeShouldWork() {\n\n\t\tTemporalLiteral literal = new TemporalLiteral(LocalDateTime.of(2021, 3, 10, 15, 13, 0));\n\t\tassertThat(literal.asString()).isEqualTo(\"localdatetime('2021-03-10T15:13:00')\");\n\t}\n\n\t@Test\n\tvoid zonedDateTimeShouldWork() {\n\n\t\tTemporalLiteral literal = new TemporalLiteral(\n\t\t\t\tZonedDateTime.of(LocalDate.of(2021, 3, 10), LocalTime.of(15, 41, 0), ZoneId.of(\"Europe/Berlin\")));\n\t\tassertThat(literal.asString()).isEqualTo(\"datetime('2021-03-10T15:41:00+01:00[Europe/Berlin]')\");\n\t}\n\n\t@Test\n\tvoid localTimeShouldWork() {\n\n\t\tTemporalLiteral literal = new TemporalLiteral(LocalTime.of(15, 42));\n\t\tassertThat(literal.asString()).isEqualTo(\"localtime('15:42:00')\");\n\t}\n\n\t@Test\n\tvoid offsetTimeShouldWork() {\n\n\t\tTemporalLiteral literal = new TemporalLiteral(OffsetTime.of(LocalTime.of(15, 15, 0), ZoneOffset.ofHours(2)));\n\t\tassertThat(literal.asString()).isEqualTo(\"time('15:15:00+02:00')\");\n\t}\n\n\t@Test\n\tvoid shouldThrowAnExceptionOnUnsupportedTemporalAccessor() {\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> new TemporalLiteral(new TemporalAccessor() {\n\t\t\t@Override\n\t\t\tpublic boolean isSupported(TemporalField field) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic long getLong(TemporalField field) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/TestUtils.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\n\n/**\n * @author Michael J. Simons\n *\n */\nfinal class TestUtils {\n\n\tprivate TestUtils() {\n\t}\n\n\tstatic Method findMethod(Class<?> clazz, String name, Class<?>... paramTypes) {\n\t\ttry {\n\t\t\treturn clazz.getDeclaredMethod(name, paramTypes);\n\t\t}\n\t\tcatch (NoSuchMethodException ex) {\n\t\t\tthrow new RuntimeException(ex);\n\t\t}\n\t}\n\n\tstatic Object invokeMethod(Method method, Object target, Object... args) {\n\t\ttry {\n\t\t\treturn method.invoke(target, args);\n\t\t}\n\t\tcatch (InvocationTargetException ex) {\n\t\t\tThrowable targetException = ex.getTargetException();\n\t\t\tif (targetException instanceof RuntimeException) {\n\t\t\t\tthrow ((RuntimeException) targetException);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new RuntimeException(targetException);\n\t\t\t}\n\t\t}\n\t\tcatch (Exception ex) {\n\n\t\t\tthrow new RuntimeException(ex);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/ToStringSmokeTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatNoException;\n\n/**\n * @author Michael J. Simons\n */\nclass ToStringSmokeTests {\n\n\tstatic Stream<Arguments> toStringShouldWork() {\n\n\t\treturn Stream.of(Arguments.of(Cypher.node(\"Person\").named(\"n\"), \"(n:Person)\"),\n\t\t\t\tArguments.of(Cypher.node(\"Person\")\n\t\t\t\t\t.named(\"p\")\n\t\t\t\t\t.relationshipTo(Cypher.node(\"Movie\").named(\"m\"), \"PLAYED_IN\")\n\t\t\t\t\t.named(\"r\"), \"(p:Person)-[r:PLAYED_IN]->(m:Movie)\"),\n\t\t\t\tArguments.of(\n\t\t\t\t\t\tCypher.node(\"Person\")\n\t\t\t\t\t\t\t.named(\"p\")\n\t\t\t\t\t\t\t.relationshipTo(Cypher.node(\"Movie\").named(\"m\"), \"PLAYED_IN\")\n\t\t\t\t\t\t\t.named(\"r\")\n\t\t\t\t\t\t\t.relationshipFrom(Cypher.node(\"Person\").named(\"d\"), \"DIRECTED\"),\n\t\t\t\t\t\t\"(p:Person)-[r:PLAYED_IN]->(m:Movie)<-[:DIRECTED]-(d:Person)\"),\n\t\t\t\tArguments.of(Cypher.elementId(Cypher.anyNode(\"n\")), \"elementId(n)\"),\n\t\t\t\tArguments.of(Cypher.call(\"db.labels\").asFunction(), \"db.labels()\"),\n\t\t\t\tArguments.of(Cypher.literalOf(\"aString\"), \"'aString'\"), Arguments.of(Cypher.literalOf(1), \"1\"),\n\t\t\t\tArguments.of(Cypher.parameter(\"p\"), \"$p\"),\n\t\t\t\tArguments.of(Cypher.anyNode(\"n\").property(\"prop\"), \"n.prop\"));\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource\n\tvoid toStringShouldWork(Visitable visitable, String expected) {\n\t\tassertThat(visitable).hasToString(visitable.getClass().getSimpleName() + \"{cypher=\" + expected + \"}\");\n\t}\n\n\t@Test\n\tvoid mostConstructsShouldNotHaveDefaultToString() {\n\t\tvar statement = IssueRelatedIT.createSomewhatComplexStatement();\n\n\t\tstatement.accept(segment -> {\n\t\t\tif (segment.getClass().getPackage().getName().equals(\"org.neo4j.cypherdsl.core.internal\")\n\t\t\t\t\t|| segment instanceof Statement) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\n\t\t\t\tboolean hasOverwrittenToString = (segment.getClass()\n\t\t\t\t\t.getMethod(\"toString\")\n\t\t\t\t\t.getDeclaringClass() != Object.class);\n\t\t\t\tassertThat(hasOverwrittenToString).isTrue();\n\t\t\t\tassertThatNoException().isThrownBy(segment::toString);\n\t\t\t}\n\t\t\tcatch (NoSuchMethodException ex) {\n\t\t\t\tthrow new RuntimeException(ex);\n\t\t\t}\n\t\t});\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/TreeNodeTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.NoSuchElementException;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatExceptionOfType;\n\n/**\n * @author Michael J. Simons\n */\nclass TreeNodeTests {\n\n\tprivate static final TreeNode<Integer> ROOT;\n\n\tstatic {\n\t\tROOT = TreeNode.root(10);\n\t\tvar n2 = ROOT.append(2);\n\t\tROOT.append(34);\n\t\tvar n56 = ROOT.append(56);\n\t\tvar n100 = ROOT.append(100);\n\t\tn2.append(77);\n\t\tn2.append(88);\n\t\tvar n1 = n56.append(1);\n\t\tn1.append(23);\n\t\tn100.append(7);\n\t\tn100.append(8);\n\t\tn100.append(9);\n\t}\n\n\t@Test\n\tvoid breadthFirstSearchShouldWork() {\n\n\t\tvar it = ROOT.breadthFirst();\n\t\tassertThat(it).toIterable()\n\t\t\t.extracting(TreeNode::getValue)\n\t\t\t.containsExactly(10, 2, 34, 56, 100, 77, 88, 1, 7, 8, 9, 23);\n\n\t\tassertThatExceptionOfType(NoSuchElementException.class).isThrownBy(it::next);\n\t}\n\n\t@Test\n\tvoid preOrderShouldWork() {\n\n\t\tvar it = ROOT.preOrder();\n\t\tassertThat(it).toIterable()\n\t\t\t.extracting(TreeNode::getValue)\n\t\t\t.containsExactly(10, 2, 77, 88, 34, 56, 1, 23, 100, 7, 8, 9);\n\n\t\tassertThatExceptionOfType(NoSuchElementException.class).isThrownBy(it::next);\n\t}\n\n\t@Test\n\tvoid rootsBloodyRoots() {\n\t\tassertThat(ROOT.isRoot()).isTrue();\n\t}\n\n\t@Test\n\tvoid printShouldWork() {\n\n\t\tvar buffer = new StringBuilder();\n\t\tROOT.printTo(buffer::append, node -> node.getValue().toString());\n\t\tassertThat(buffer).hasToString(\"\"\"\n\t\t\t\t10\n\t\t\t\t├── 2\n\t\t\t\t│   ├── 77\n\t\t\t\t│   └── 88\n\t\t\t\t├── 34\n\t\t\t\t├── 56\n\t\t\t\t│   └── 1\n\t\t\t\t│       └── 23\n\t\t\t\t└── 100\n\t\t\t\t    ├── 7\n\t\t\t\t    ├── 8\n\t\t\t\t    └── 9\n\t\t\t\t\"\"\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/UseIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core;\n\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.CsvSource;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.StatementBuilder.OngoingReadingAndReturn;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Dialect;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n */\nclass UseIT {\n\n\tprivate final Renderer renderer = Renderer\n\t\t.getRenderer(Configuration.newConfig().withDialect(Dialect.NEO4J_5).build());\n\n\tprivate final OngoingReadingAndReturn ongoingInnerStatementDefinition = Cypher\n\t\t.call(Cypher.match(Cypher.node(\"Movie\").named(\"movie\")).returning(\"movie\").build())\n\t\t.returning(\"movie\");\n\n\tstatic Stream<Arguments> graphByNameShouldWork() {\n\t\treturn Stream.of(\n\t\t\t\tArguments.of(Cypher.literalOf(\"myComposite.myConstituent\"),\n\t\t\t\t\t\t\"USE graph.byName('myComposite.myConstituent') MATCH (n) RETURN n\"),\n\t\t\t\tArguments.of(Cypher.parameter(\"graphName\"), \"USE graph.byName($graphName) MATCH (n) RETURN n\"));\n\t}\n\n\t@ParameterizedTest\n\t@CsvSource(textBlock = \"\"\"\n\t\t\t       myDatabase, USE myDatabase MATCH (n) RETURN n\n\t\t\t       myComposite.myConstituent, USE myComposite.myConstituent MATCH (n) RETURN n\n\t\t\t\"\"\")\n\tvoid simpleUseShouldWork(String target, String expected) {\n\n\t\tvar statement = Cypher.match(Cypher.anyNode(\"n\")).returning(\"n\").build();\n\t\tvar cypher = Cypher.use(target, statement).getCypher();\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource\n\tvoid graphByNameShouldWork(Expression target, String expected) {\n\n\t\tvar statement = Cypher.match(Cypher.anyNode(\"n\")).returning(\"n\").build();\n\t\tvar cypher = \"\";\n\t\tif (target instanceof StringLiteral literal) {\n\t\t\tcypher = Cypher.use(literal, statement).getCypher();\n\t\t}\n\t\telse if (target instanceof Parameter<?> parameter) {\n\t\t\tcypher = Cypher.use(parameter, statement).getCypher();\n\t\t}\n\t\telse {\n\t\t\tAssertions.fail(\"Unexpected expression type in test.\");\n\t\t}\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@Test\n\tvoid usageInSubqueryShouldWork() {\n\n\t\tvar expected = \"\"\"\n\t\t\t\tUNWIND ['cineasts.latest', 'cineasts.upcoming'] AS graphName\n\t\t\t\tCALL (*) {\n\t\t\t\tUSE graph.byName(graphName)\n\t\t\t\t  MATCH (movie:`Movie`)\n\t\t\t\t  RETURN movie\n\t\t\t\t}\n\t\t\t\tRETURN movie.title AS title\n\t\t\t\t\"\"\".lines()\n\t\t\t.map(String::trim)\n\t\t\t.collect(Collectors.joining(\" \"))\n\t\t\t.replace(\"CALL (*) { \", \"CALL (*) {\")\n\t\t\t.replace(\" }\", \"}\");\n\n\t\tvar innerStatement = Cypher.match(Cypher.node(\"Movie\").named(\"movie\")).returning(\"movie\").build();\n\t\tvar cypher = Cypher.unwind(Cypher.literalOf(List.of(\"cineasts.latest\", \"cineasts.upcoming\")))\n\t\t\t.as(\"graphName\")\n\t\t\t.call(Cypher.use((Expression) Cypher.name(\"graphName\"), innerStatement))\n\t\t\t.returning(Cypher.name(\"movie\").property(\"title\").as(\"title\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@Test\n\tvoid useBeforeCall() {\n\n\t\tvar innerStatement = this.ongoingInnerStatementDefinition.build();\n\t\tvar cypher = Cypher.use(\"cineasts.latest\", innerStatement).getCypher();\n\t\tassertThat(cypher).isEqualTo(\"USE cineasts.latest CALL () {MATCH (movie:`Movie`) RETURN movie} RETURN movie\");\n\t}\n\n\t@Test\n\tvoid nestedUseShouldThrow() {\n\n\t\tvar innerStatement = Cypher.use(\"x\", this.ongoingInnerStatementDefinition.build());\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.use(\"y\", innerStatement))\n\t\t\t.withMessage(\"Nested USE clauses are not supported\");\n\t}\n\n\t@Test\n\tvoid useBeforeCallWithCallInTx() {\n\n\t\tvar title = Cypher.name(\"title\");\n\t\tvar movie = Cypher.node(\"Movie\", Cypher.mapOf(\"title\", title)).named(\"m\");\n\t\tvar innerStatement = Cypher.unwind(Cypher.parameter(\"newMovies\"))\n\t\t\t.as(title)\n\t\t\t.call(Cypher.with(title).merge(movie).returning(movie.elementId().as(\"id\")).build())\n\t\t\t.returning(\"id\")\n\t\t\t.build();\n\t\tvar cypher = this.renderer.render(Cypher.use(\"cineasts.latest\", innerStatement));\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"USE cineasts.latest UNWIND $newMovies AS title CALL {WITH title MERGE (m:`Movie` {title: title}) RETURN elementId(m) AS id} RETURN id\");\n\t}\n\n\t@Test\n\tvoid addExplain() {\n\n\t\tvar innerStatement = this.ongoingInnerStatementDefinition.build();\n\t\tvar cypher = Cypher.use(\"cineasts.latest\", innerStatement).explain().getCypher();\n\t\tassertThat(cypher)\n\t\t\t.isEqualTo(\"EXPLAIN USE cineasts.latest CALL () {MATCH (movie:`Movie`) RETURN movie} RETURN movie\");\n\t}\n\n\t@Test\n\tvoid innerProfileShouldThrow() {\n\n\t\tvar innerStatement = this.ongoingInnerStatementDefinition.profile();\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.use(\"x\", innerStatement))\n\t\t\t.withMessage(\"PROFILE'd statements are not supported inside USE clauses\");\n\t}\n\n\t@Test\n\tvoid innerExplainShouldThrow() {\n\n\t\tvar innerStatement = this.ongoingInnerStatementDefinition.explain();\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.use(\"x\", innerStatement))\n\t\t\t.withMessage(\"EXPLAIN'ed statements are not supported inside USE clauses\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/internal/LoadCSVTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport java.net.URI;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass LoadCSVTests {\n\n\t@Test\n\tvoid witherShouldWorkWithNullsOnBothEnds() {\n\n\t\tLoadCSV a = new LoadCSV(URI.create(\"file:///f.csv\"), true, \"a\");\n\t\tLoadCSV b = a.withFieldTerminator(null);\n\t\tassertThat(a).isSameAs(b);\n\t}\n\n\t@Test\n\tvoid witherShouldWorkWithEmptyValues() {\n\n\t\tLoadCSV a = new LoadCSV(URI.create(\"file:///f.csv\"), true, \"a\");\n\t\tLoadCSV b = a.withFieldTerminator(\"  \\t\");\n\t\tassertThat(a).isSameAs(b);\n\t\tassertThat(a.getFieldTerminator()).isNull();\n\t}\n\n\t@Test\n\tvoid witherShouldWorkWithNonEmptyValues() {\n\n\t\tLoadCSV a = new LoadCSV(URI.create(\"file:///f.csv\"), true, \"a\");\n\t\tLoadCSV b = a.withFieldTerminator(\";\");\n\t\tassertThat(a).isNotSameAs(b);\n\t\tassertThat(a.getFieldTerminator()).isNull();\n\t\tassertThat(b.getFieldTerminator()).isEqualTo(\";\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/internal/ReflectiveVisitorTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.internal;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.assertj.core.api.Assertions.assertThatExceptionOfType;\n\n/**\n * @author Michael J. Simons\n */\nclass ReflectiveVisitorTests {\n\n\t@Test\n\tvoid visitorShouldThrowDedicatedException() {\n\t\tSomeException cause = new SomeException();\n\t\tReflectiveVisitor visitor = new ReflectiveVisitor() {\n\t\t\t@Override\n\t\t\tprotected boolean preEnter(Visitable visitable) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tprotected void postLeave(Visitable visitable) {\n\t\t\t}\n\n\t\t\t@SuppressWarnings(\"unused\")\n\t\t\tvoid enter(ThrowingVisitable throwingVisitable) {\n\t\t\t\tthrow cause;\n\t\t\t}\n\t\t};\n\n\t\tVisitable v = new ThrowingVisitable();\n\t\tassertThatExceptionOfType(HandlerException.class).isThrownBy(() -> visitor.enter(v))\n\t\t\t.withRootCauseInstanceOf(SomeException.class);\n\t}\n\n\tstatic class ThrowingVisitable implements Visitable {\n\n\t}\n\n\tstatic class SomeException extends RuntimeException {\n\n\t\tprivate static final long serialVersionUID = -4170504879699181855L;\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/querydsl/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.querydsl;\n\nimport com.querydsl.core.annotations.QueryEntity;\n\n/**\n * @author Rickard Öberg\n */\n@QueryEntity\npublic class Person {\n\n\tString firstName;\n\n\tString lastName;\n\n\tint age;\n\n\tpublic String getFirstName() {\n\t\treturn this.firstName;\n\t}\n\n\tpublic int getAge() {\n\t\treturn this.age;\n\t}\n\n\tpublic String getLastName() {\n\t\treturn this.lastName;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/querydsl/Place.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.querydsl;\n\nimport com.querydsl.core.annotations.QueryEntity;\n\n/**\n * @author Rickard Öberg\n */\n@QueryEntity\npublic class Place {\n\n\tString name;\n\n\tpublic String getName() {\n\t\treturn this.name;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/querydsl/QueryDSLAdapterTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.querydsl;\n\nimport java.time.LocalDate;\nimport java.time.OffsetTime;\nimport java.time.ZoneId;\nimport java.time.ZoneOffset;\nimport java.time.ZonedDateTime;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.stream.Stream;\n\nimport com.querydsl.core.BooleanBuilder;\nimport com.querydsl.core.types.Ops;\nimport com.querydsl.core.types.Path;\nimport com.querydsl.core.types.Predicate;\nimport com.querydsl.core.types.dsl.Expressions;\nimport com.querydsl.core.types.dsl.Param;\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.Condition;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.Literal.UnsupportedLiteralException;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Statement;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static com.querydsl.core.alias.Alias.$;\nimport static com.querydsl.core.alias.Alias.alias;\nimport static com.querydsl.core.types.dsl.Expressions.asNumber;\nimport static com.querydsl.core.types.dsl.Expressions.asString;\nimport static com.querydsl.core.types.dsl.Expressions.booleanOperation;\nimport static com.querydsl.core.types.dsl.Expressions.constant;\nimport static com.querydsl.core.types.dsl.Expressions.dateOperation;\nimport static com.querydsl.core.types.dsl.Expressions.numberOperation;\nimport static com.querydsl.core.types.dsl.Expressions.predicate;\nimport static com.querydsl.core.types.dsl.Expressions.stringOperation;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * This is an integration test looking at two things:\n * <ol>\n * <li>The templates we defined for QueryDSL: They must resolve to semantically correct\n * Cypher.</li>\n * <li>Whether the {@link ToCypherFormatStringVisitor} actually creates syntactically\n * fragments.</li>\n * </ol>\n * As we deal with a lot of operators from QueryDSL, it's more economical to test these\n * two things together. An approach testing the templates in isolation would require\n * rendering them (\"converting\" to speak in terms of QueryDSL) as well, pretty much\n * repeating what we are doing in the {@link ToCypherFormatStringVisitor} again.\n *\n * @author Michael J. Simons\n *\n */\nclass QueryDSLAdapterTests {\n\n\tstatic Map<String, Object> expected(Object... args) {\n\t\tMap<String, Object> result = new HashMap<>();\n\t\tfor (int i = 0; i < args.length; i++) {\n\t\t\tresult.put(String.format(\"pcdsl%02d\", i + 1), args[i]);\n\t\t}\n\t\treturn result;\n\t}\n\n\tstatic Stream<Arguments> supportedOpsArgs() {\n\n\t\tStream.Builder<Arguments> r = Stream.builder();\n\n\t\t//@formatter:off\n\t\tr.add(Arguments.arguments(\"true = true AND false = true\", Expressions.TRUE.isTrue().and(Expressions.FALSE.isTrue()), Collections.emptyMap()));\n\t\tr.add(Arguments.arguments(\"NOT true\", Expressions.TRUE.not(), Collections.emptyMap()));\n\t\tr.add(Arguments.arguments(\"true = true OR false = true\", Expressions.TRUE.isTrue().or(Expressions.FALSE.isTrue()), Collections.emptyMap()));\n\t\tr.add(Arguments.arguments(\"NOT (true XOR false)\", booleanOperation(Ops.XNOR,  Expressions.TRUE,  Expressions.FALSE), Collections.emptyMap()));\n\t\tr.add(Arguments.arguments(\"true XOR false\", booleanOperation(Ops.XOR,  Expressions.TRUE,  Expressions.FALSE), Collections.emptyMap()));\n\n\t\tr.add(Arguments.arguments(\"size($pcdsl01) = 0\", booleanOperation(Ops.COL_IS_EMPTY, constant(Arrays.asList(\"x\"))), expected(Collections.singletonList(\"x\"))));\n\t\tr.add(Arguments.arguments(\"size($pcdsl01) > $pcdsl02\", numberOperation(Integer.class, Ops.COL_SIZE, constant(Arrays.asList(\"x\"))).gt(1), expected(Collections.singletonList(\"x\"), 1)));\n\t\tr.add(Arguments.arguments(\"size($pcdsl01) > $pcdsl02\", numberOperation(Integer.class, Ops.COL_SIZE, constant(new String[]{\"x\"})).gt(1), expected(new String[]{\"x\"}, 1)));\n\n\t\tMap<String, String> aMap = new HashMap<>();\n\t\taMap.put(\"1\", \"a\");\n\t\taMap.put(\"2\", \"b\");\n\t\tr.add(Arguments.arguments(\"size(keys($pcdsl01)) > $pcdsl02\", numberOperation(Integer.class, Ops.MAP_SIZE, constant(aMap)).gt(1), expected(aMap, 1)));\n\t\tr.add(Arguments.arguments(\"size(keys($pcdsl01)) = 0\", booleanOperation(Ops.MAP_IS_EMPTY, constant(aMap)), expected(aMap)));\n\t\tr.add(Arguments.arguments(\"any(v in keys($pcdsl01) where v = $pcdsl02)\", booleanOperation(Ops.CONTAINS_KEY, constant(aMap), asString(\"1\")), expected(aMap, \"1\")));\n\t\tr.add(Arguments.arguments(\"any(v in [k IN KEYS($pcdsl01) | $pcdsl01[k]] where v = $pcdsl02)\", booleanOperation(Ops.CONTAINS_VALUE, constant(aMap), asString(\"b\")), expected(aMap, \"b\")));\n\n\t\tr.add(Arguments.arguments(\"size($pcdsl01 + $pcdsl02) = $pcdsl03\", stringOperation(Ops.CONCAT, asString(\"a\"), asString(\"b\")).length().eq(2), expected(\"a\", \"b\", 2)));\n\t\tr.add(Arguments.arguments(\"toLower($pcdsl01) = $pcdsl02\", stringOperation(Ops.LOWER, asString(\"A\")).eq(asString(\"a\")), expected(\"A\", \"a\")));\n\t\tr.add(Arguments.arguments(\"substring($pcdsl01, 1) = $pcdsl02\", stringOperation(Ops.SUBSTR_1ARG, asString(\"1234\"), Expressions.ONE).eq(asString(\"234\")), expected(\"1234\", \"234\")));\n\t\tr.add(Arguments.arguments(\"substring($pcdsl01, 1, 2) = $pcdsl02\", stringOperation(Ops.SUBSTR_2ARGS, asString(\"1234\"), Expressions.ONE, Expressions.TWO).eq(asString(\"23\")), expected(\"1234\", \"23\")));\n\t\tr.add(Arguments.arguments(\"trim($pcdsl01) = $pcdsl02\", stringOperation(Ops.TRIM, asString(\" A \")).eq(asString(\"A\")), expected(\" A \", \"A\")));\n\t\tr.add(Arguments.arguments(\"toUpper($pcdsl01) = $pcdsl02\", stringOperation(Ops.UPPER, asString(\"a\")).eq(asString(\"A\")), expected(\"a\", \"A\")));\n\t\tr.add(Arguments.arguments(\"$pcdsl01 =~ $pcdsl02\", booleanOperation(Ops.MATCHES, asString(\"a\"), asString(\"A\")), expected(\"a\", \"A\")));\n\t\tr.add(Arguments.arguments(\"$pcdsl01 =~ ('(?i)' + $pcdsl02)\", booleanOperation(Ops.MATCHES_IC, asString(\"a\"), asString(\"A\")), expected(\"a\", \"A\")));\n\t\tr.add(Arguments.arguments(\"$pcdsl01 =~ ('(?i)' + $pcdsl02)\", booleanOperation(Ops.MATCHES_IC, asString(\"a\"), asString(\"A\")), expected(\"a\", \"A\")));\n\t\tr.add(Arguments.arguments(\"$pcdsl01 STARTS WITH $pcdsl02\", booleanOperation(Ops.STARTS_WITH, asString(\"ABC\"), asString(\"a\")), expected(\"ABC\", \"a\")));\n\t\tr.add(Arguments.arguments(\"toLower($pcdsl01) STARTS WITH toLower($pcdsl02)\", booleanOperation(Ops.STARTS_WITH_IC, asString(\"ABC\"), asString(\"a\")), expected(\"ABC\", \"a\")));\n\t\tr.add(Arguments.arguments(\"$pcdsl01 ENDS WITH $pcdsl02\", booleanOperation(Ops.ENDS_WITH, asString(\"ABC\"), asString(\"c\")), expected(\"ABC\", \"c\")));\n\t\tr.add(Arguments.arguments(\"toLower($pcdsl01) ENDS WITH toLower($pcdsl02)\", booleanOperation(Ops.ENDS_WITH_IC, asString(\"ABC\"), asString(\"c\")), expected(\"ABC\", \"c\")));\n\t\tr.add(Arguments.arguments(\"$pcdsl01 CONTAINS $pcdsl02\", booleanOperation(Ops.STRING_CONTAINS, asString(\"ABC\"), asString(\"c\")), expected(\"ABC\", \"c\")));\n\t\tr.add(Arguments.arguments(\"toLower($pcdsl01) CONTAINS toLower($pcdsl02)\", booleanOperation(Ops.STRING_CONTAINS_IC, asString(\"ABC\"), asString(\"c\")), expected(\"ABC\", \"c\")));\n\t\tr.add(Arguments.arguments(\"substring($pcdsl01, 2, 1) = $pcdsl02\", Expressions.operation(Character.class, Ops.CHAR_AT, asString(\"1234\"), Expressions.TWO).eq('3'), expected(\"1234\", '3')));\n\t\tr.add(Arguments.arguments(\"size($pcdsl01) = $pcdsl02\", asString(\"ABC\").length().eq(3), expected(\"ABC\", 3)));\n\t\tr.add(Arguments.arguments(\"$pcdsl01 =~ '.*' + $pcdsl02 + '.*'\", booleanOperation(Ops.LIKE, asString(\"ABC\"), asString(\"a\")), expected(\"ABC\", \"a\")));\n\t\tr.add(Arguments.arguments(\"$pcdsl01 =~ '(?i).*' + $pcdsl02 + '.*'\", booleanOperation(Ops.LIKE_IC, asString(\"ABC\"), asString(\"a\")), expected(\"ABC\", \"a\")));\n\t\tr.add(Arguments.arguments(\"size(left($pcdsl01, $pcdsl02)) = $pcdsl02\", stringOperation(Ops.StringOps.LEFT, asString(\"ABCD\"), asNumber(3)).length().eq(3), expected(\"ABCD\", 3)));\n\t\tr.add(Arguments.arguments(\"size(right($pcdsl01, $pcdsl02)) = $pcdsl02\", stringOperation(Ops.StringOps.RIGHT, asString(\"ABCD\"), asNumber(3)).length().eq(3), expected(\"ABCD\", 3)));\n\t\tr.add(Arguments.arguments(\"size(ltrim($pcdsl01)) = $pcdsl02\", stringOperation(Ops.StringOps.LTRIM, asString(\" ABCD\")).length().eq(4), expected(\" ABCD\", 4)));\n\t\tr.add(Arguments.arguments(\"size(rtrim($pcdsl01)) = $pcdsl02\", stringOperation(Ops.StringOps.RTRIM, asString(\"ABCD \")).length().eq(4), expected(\"ABCD \", 4)));\n\n\t\tZonedDateTime t = ZonedDateTime.of(2021, 3, 10, 15, 50, 0, 0, ZoneId.of(\"Europe/Berlin\"));\n\t\tr.add(Arguments.arguments(\"datetime() >= $pcdsl01\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE).goe(t), expected(t)));\n\t\tLocalDate l = LocalDate.of(2021, 3, 10);\n\t\tr.add(Arguments.arguments(\"date() >= $pcdsl01\", dateOperation(LocalDate.class, Ops.DateTimeOps.CURRENT_DATE).goe(l), expected(l)));\n\t\tOffsetTime ot = OffsetTime.of(15, 53, 0, 0, ZoneOffset.UTC);\n\t\tr.add(Arguments.arguments(\"time() >= $pcdsl01\", dateOperation(OffsetTime.class, Ops.DateTimeOps.CURRENT_TIME).goe(ot), expected(ot)));\n\t\tr.add(Arguments.arguments(\"datetime().epochmillis >= $pcdsl01\", dateOperation(Long.class, Ops.DateTimeOps.CURRENT_TIMESTAMP).goe(23L), expected(23L)));\n\t\tr.add(Arguments.arguments(\"date($pcdsl01) >= $pcdsl02\", dateOperation(LocalDate.class, Ops.DateTimeOps.DATE, Expressions.asString(\"2021-03-10\")).goe(l), expected(\"2021-03-10\", l)));\n\n\t\tr.add(Arguments.arguments(\"datetime().millisecond >= $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.MILLISECOND, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(23), expected(23)));\n\t\tr.add(Arguments.arguments(\"datetime().second >= $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.SECOND, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(23), expected(23)));\n\t\tr.add(Arguments.arguments(\"datetime().minute >= $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.MINUTE, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(23), expected(23)));\n\t\tr.add(Arguments.arguments(\"datetime().hour >= $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.HOUR, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(23), expected(23)));\n\t\tr.add(Arguments.arguments(\"datetime().week >= $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.WEEK, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(23), expected(23)));\n\t\tr.add(Arguments.arguments(\"datetime().month >= $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.MONTH, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(23), expected(23)));\n\t\tr.add(Arguments.arguments(\"datetime().year >= $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.YEAR, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(23), expected(23)));\n\t\tr.add(Arguments.arguments(\"datetime().weekYear >= $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.YEAR_WEEK, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(23), expected(23)));\n\t\tr.add(Arguments.arguments(\"datetime().dayOfWeek >= $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.DAY_OF_WEEK, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(23), expected(23)));\n\n\t\tt = ZonedDateTime.of(2021, 3, 10, 16, 48, 0, 0, ZoneId.of(\"Europe/Berlin\"));\n\t\tr.add(Arguments.arguments(\"datetime() + duration({years: $pcdsl01}) >= $pcdsl02\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.ADD_YEARS, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), asNumber(23)).goe(t), expected(23, t)));\n\t\tr.add(Arguments.arguments(\"datetime() + duration({months: $pcdsl01}) >= $pcdsl02\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.ADD_MONTHS, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), asNumber(23)).goe(t), expected(23, t)));\n\t\tr.add(Arguments.arguments(\"datetime() + duration({weeks: $pcdsl01}) >= $pcdsl02\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.ADD_WEEKS, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), asNumber(23)).goe(t), expected(23, t)));\n\t\tr.add(Arguments.arguments(\"datetime() + duration({days: $pcdsl01}) >= $pcdsl02\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.ADD_DAYS, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), asNumber(23)).goe(t), expected(23, t)));\n\t\tr.add(Arguments.arguments(\"datetime() + duration({hours: $pcdsl01}) >= $pcdsl02\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.ADD_HOURS, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), asNumber(23)).goe(t), expected(23, t)));\n\t\tr.add(Arguments.arguments(\"datetime() + duration({minutes: $pcdsl01}) >= $pcdsl02\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.ADD_MINUTES, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), asNumber(23)).goe(t), expected(23, t)));\n\t\tr.add(Arguments.arguments(\"datetime() + duration({seconds: $pcdsl01}) >= $pcdsl02\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.ADD_SECONDS, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), asNumber(23)).goe(t), expected(23, t)));\n\n\t\tr.add(Arguments.arguments(\"duration.between(datetime(), datetime()).years = $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.DIFF_YEARS, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).eq(0), expected(0)));\n\t\tr.add(Arguments.arguments(\"duration.between(datetime(), datetime()).months = $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.DIFF_MONTHS, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).eq(0), expected(0)));\n\t\tr.add(Arguments.arguments(\"duration.between(datetime(), datetime()).weeks = $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.DIFF_WEEKS, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).eq(0), expected(0)));\n\t\tr.add(Arguments.arguments(\"duration.between(datetime(), datetime()).days = $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.DIFF_DAYS, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).eq(0), expected(0)));\n\t\tr.add(Arguments.arguments(\"duration.between(datetime(), datetime()).hours = $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.DIFF_HOURS, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).eq(0), expected(0)));\n\t\tr.add(Arguments.arguments(\"duration.between(datetime(), datetime()).minutes = $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.DIFF_MINUTES, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).eq(0), expected(0)));\n\t\tr.add(Arguments.arguments(\"duration.between(datetime(), datetime()).seconds = $pcdsl01\", dateOperation(Integer.class, Ops.DateTimeOps.DIFF_SECONDS, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE), dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).eq(0), expected(0)));\n\n\t\tt = ZonedDateTime.of(2021, 3, 10, 17, 02, 0, 0, ZoneId.of(\"Europe/Berlin\"));\n\t\tr.add(Arguments.arguments(\"date.truncate('year', datetime()) >= $pcdsl01\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.TRUNC_YEAR, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(t), expected(t)));\n\t\tr.add(Arguments.arguments(\"date.truncate('month', datetime()) >= $pcdsl01\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.TRUNC_MONTH, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(t), expected(t)));\n\t\tr.add(Arguments.arguments(\"date.truncate('week', datetime()) >= $pcdsl01\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.TRUNC_WEEK, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(t), expected(t)));\n\t\tr.add(Arguments.arguments(\"date.truncate('day', datetime()) >= $pcdsl01\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.TRUNC_DAY, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(t), expected(t)));\n\t\tr.add(Arguments.arguments(\"datetime.truncate('hour', datetime()) >= $pcdsl01\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.TRUNC_HOUR, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(t), expected(t)));\n\t\tr.add(Arguments.arguments(\"datetime.truncate('minute', datetime()) >= $pcdsl01\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.TRUNC_MINUTE, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(t), expected(t)));\n\t\tr.add(Arguments.arguments(\"datetime.truncate('second', datetime()) >= $pcdsl01\", dateOperation(ZonedDateTime.class, Ops.DateTimeOps.TRUNC_SECOND, dateOperation(ZonedDateTime.class, Ops.DateTimeOps.SYSDATE)).goe(t), expected(t)));\n\n\t\tr.add(Arguments.arguments(\"abs($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.ABS, asNumber(1)).gt(1), expected(1, 1.0)));\n\t\tr.add(Arguments.arguments(\"acos($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.ACOS, asNumber(1)).gt(1), expected(1, 1.0)));\n\t\tr.add(Arguments.arguments(\"asin($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.ASIN, asNumber(1)).gt(1), expected(1, 1.0)));\n\t\tr.add(Arguments.arguments(\"atan($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.ATAN, asNumber(1)).gt(1), expected(1, 1.0)));\n\t\tr.add(Arguments.arguments(\"ceil($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.CEIL, asNumber(1)).gt(1), expected(1, 1.0)));\n\t\tr.add(Arguments.arguments(\"cos($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.COS, asNumber(1)).gt(1), expected(1, 1.0)));\n\t\tr.add(Arguments.arguments(\"cot($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.COT, asNumber(1)).gt(1), expected(1, 1.0)));\n\t\tr.add(Arguments.arguments(\"degrees($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.DEG, asNumber(1)).gt(1), expected(1, 1.0)));\n\t\tr.add(Arguments.arguments(\"tan($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.TAN, asNumber(1)).gt(1), expected(1,  1.0)));\n\t\tr.add(Arguments.arguments(\"sqrt($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.SQRT, asNumber(4)).gt(1), expected(4, 1.0)));\n\t\tr.add(Arguments.arguments(\"sign($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.SIGN, asNumber(1)).gt(1), expected(1, 1.0)));\n\t\tr.add(Arguments.arguments(\"sin($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.SIN, asNumber(1)).gt(1), expected(1, 1.0)));\n\t\tr.add(Arguments.arguments(\"round($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.ROUND, asNumber(1)).gt(1), expected(1, 1.0)));\n\t\tr.add(Arguments.arguments(\"round($pcdsl01, $pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.ROUND2, asNumber(1), asNumber(1)).gt(1), expected(1, 1.0)));\n\t\tr.add(Arguments.arguments(\"radians($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.RAD, asNumber(1)).gt(1), expected(1, 1.0)));\n\t\tr.add(Arguments.arguments(\"CASE WHEN $pcdsl01 < $pcdsl02 THEN $pcdsl01 ELSE $pcdsl02 END > $pcdsl03\", numberOperation(Double.class, Ops.MathOps.MIN, asNumber(1), asNumber(2)).gt(1), expected(1, 2, 1.0)));\n\t\tr.add(Arguments.arguments(\"CASE WHEN $pcdsl01 > $pcdsl02 THEN $pcdsl01 ELSE $pcdsl02 END > $pcdsl03\", numberOperation(Double.class, Ops.MathOps.MAX, asNumber(1), asNumber(2)).gt(1), expected(1, 2, 1.0)));\n\t\tr.add(Arguments.arguments(\"floor($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.FLOOR, asNumber(1.1)).gt(1), expected(1.1, 1.0)));\n\t\tr.add(Arguments.arguments(\"exp($pcdsl01) > $pcdsl02\", numberOperation(Double.class, Ops.MathOps.EXP, asNumber(1)).gt(1), expected(1, 1.0)));\n\n\t\tPredicate p = Expressions.cases().when(Expressions.TRUE).then(Expressions.asNumber(1))\n\t\t\t.when(Expressions.FALSE).then(Expressions.asNumber(2))\n\t\t\t.otherwise(Expressions.asNumber(3)).gt(3);\n\t\tr.add(Arguments.arguments(\"(CASE WHEN true THEN $pcdsl01 WHEN false THEN $pcdsl02 ELSE $pcdsl03 END) > $pcdsl03\", p, expected(1, 2, 3)));\n\t\t//@formatter:on\n\n\t\treturn r.build();\n\t}\n\n\tstatic Stream<Arguments> unsupportedOpsShouldBeRecognizedBeforeHandArgs() {\n\n\t\tStream.Builder<Arguments> r = Stream.builder();\n\t\tr.add(Arguments.arguments(numberOperation(Integer.class, Ops.INDEX_OF, asString(\"ABC\"), asString(\"B\")).eq(1)));\n\t\tr.add(Arguments.arguments(\n\t\t\t\tnumberOperation(Integer.class, Ops.INDEX_OF_2ARGS, asString(\"ABC\"), asString(\"B\"), asNumber(3)).eq(1)));\n\n\t\treturn r.build();\n\t}\n\n\t@MethodSource(\"supportedOpsArgs\")\n\t@ParameterizedTest(name = \"{index} {0}\")\n\tvoid supportedOpsWithParameters(String expectedFragment, Predicate predicate,\n\t\t\tMap<String, Object> expectedParameters) {\n\n\t\tStatement statement = Cypher.with(Cypher.literalOf(1).as(\"e\"))\n\t\t\t.where(Cypher.adapt(predicate).asCondition())\n\t\t\t.returning(\"e\")\n\t\t\t.build();\n\n\t\tstatement.setRenderConstantsAsParameters(true);\n\t\tassertThat(statement.getCatalog().getParameters()).containsExactlyEntriesOf(expectedParameters);\n\t\tassertThat(statement.getCypher()).isEqualTo(\"WITH 1 AS e WHERE \" + expectedFragment + \" RETURN e\");\n\t}\n\n\t@MethodSource(\"supportedOpsArgs\")\n\t@ParameterizedTest(name = \"{index} {0}\")\n\tvoid supportedOpsWithLiterals(String expectedFragment, Predicate predicate,\n\t\t\tMap<String, Object> expectedParameters) {\n\n\t\tStatement statement = Cypher.with(Cypher.literalOf(1).as(\"e\"))\n\t\t\t.where(Cypher.adapt(predicate).asCondition())\n\t\t\t.returning(\"e\")\n\t\t\t.build();\n\n\t\tString expectedString = \"WITH 1 AS e WHERE \" + expectedFragment + \" RETURN e\";\n\t\tMap<String, Object> finalExpectedParameters = new HashMap<>();\n\t\tfor (Map.Entry<String, Object> entry : expectedParameters.entrySet()) {\n\t\t\tString k = entry.getKey();\n\t\t\tObject v = entry.getValue();\n\t\t\ttry {\n\t\t\t\tString replacement = Cypher.literalOf(v).asString();\n\t\t\t\texpectedString = expectedString.replaceAll(java.util.regex.Pattern.quote(\"$\" + k), replacement);\n\t\t\t}\n\t\t\tcatch (UnsupportedLiteralException ex) {\n\t\t\t\tfinalExpectedParameters.put(k, v);\n\t\t\t}\n\t\t}\n\t\tassertThat(statement.getCatalog().getParameters()).containsExactlyEntriesOf(finalExpectedParameters);\n\t\tassertThat(statement.getCypher()).isEqualTo(expectedString);\n\t}\n\n\t@MethodSource(\"unsupportedOpsShouldBeRecognizedBeforeHandArgs\")\n\t@ParameterizedTest\n\tvoid unsupportedOpsShouldBeRecognizedBeforeHand(Predicate predicate) {\n\n\t\tAssertions.assertThatIllegalArgumentException().isThrownBy(() -> Cypher.adapt(predicate).asCondition());\n\t}\n\n\t@Test\n\tvoid queryingByPathBasedOnClassShouldWork() {\n\n\t\tPath<Person> person = Expressions.path(Person.class, \"n\");\n\t\tPath<String> personFirstName = Expressions.path(String.class, person, \"firstName\");\n\t\tPath<Integer> personAge = Expressions.path(Integer.class, person, \"age\");\n\t\tBooleanBuilder expr = new BooleanBuilder(predicate(Ops.EQ, personFirstName, constant(\"P\")))\n\t\t\t.and(predicate(Ops.GT, personAge, constant(25)));\n\n\t\tStatement statement = Cypher.match(Cypher.adapt(person).asNode())\n\t\t\t.where(Cypher.adapt(expr).asCondition())\n\t\t\t.returning(Cypher.adapt(person).asName())\n\t\t\t.build();\n\t\tassertThat(statement.getCatalog().getParameters()).isEmpty();\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(\"MATCH (n:`Person`) WHERE n.firstName = 'P' AND n.age > 25 RETURN n\");\n\t}\n\n\t@Test\n\tvoid queryingByProxyShouldWork() {\n\n\t\tPerson person = alias(Person.class, \"n\");\n\t\tPredicate p = $(person.getFirstName()).eq(\"P\").and($(person.getAge()).gt(25));\n\n\t\tStatement statement = Cypher.match(Cypher.node(\"Person\").named(\"n\"))\n\t\t\t.where(Cypher.adapt(p).asCondition())\n\t\t\t.returning(Cypher.name(person.toString()))\n\t\t\t.build();\n\t\tassertThat(statement.getCatalog().getParameters()).isEmpty();\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(\"MATCH (n:`Person`) WHERE n.firstName = 'P' AND n.age > 25 RETURN n\");\n\t}\n\n\t@Test\n\tvoid queryingByQClassShouldWork() {\n\n\t\tQPerson person = QPerson.person;\n\t\tPredicate p = person.firstName.eq(\"P\").and(person.age.gt(25));\n\n\t\tStatement statement = Cypher.match(Cypher.adapt(person).asNode())\n\t\t\t.where(Cypher.adapt(p).asCondition())\n\t\t\t.returning(Cypher.adapt(person).asName())\n\t\t\t.build();\n\t\tassertThat(statement.getCatalog().getParameters()).isEmpty();\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(\"MATCH (person:`Person`) WHERE person.firstName = 'P' AND person.age > 25 RETURN person\");\n\t}\n\n\t@Test\n\tvoid pathsShouldBeTurnedIntoExpressions() {\n\n\t\tQPerson person = QPerson.person;\n\t\tStatement statement = Cypher.match(Cypher.adapt(person).asNode())\n\t\t\t.where(Cypher.adapt(person.firstName.eq(\"Rickard\")).asCondition())\n\t\t\t.returning(Cypher.adapt(person.firstName).asExpression())\n\t\t\t.orderBy(Cypher.adapt(person.firstName).asExpression().descending())\n\t\t\t.build();\n\n\t\tassertThat(statement.getCatalog().getParameters()).isEmpty();\n\t\tassertThat(statement.getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (person:`Person`) WHERE person.firstName = 'Rickard' RETURN person.firstName ORDER BY person.firstName DESC\");\n\t}\n\n\t@Test\n\tvoid qClassToNodeShouldWork() {\n\n\t\t// tag::query-dsl-simple[]\n\t\tQPerson n = new QPerson(\"n\"); // <.>\n\t\tStatement statement = Cypher.match(Cypher.adapt(n).asNode()) // <.>\n\t\t\t.where(Cypher.adapt(n.firstName.eq(\"P\").and(n.age.gt(25))).asCondition()) // <.>\n\t\t\t.returning(Cypher.adapt(n).asName()) // <.>\n\t\t\t.build();\n\n\t\tassertThat(statement.getCatalog().getParameters()).isEmpty();\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(\"MATCH (n:`Person`) WHERE n.firstName = 'P' AND n.age > 25 RETURN n\");\n\t\t// end::query-dsl-simple[]\n\t}\n\n\t@Test\n\tvoid qClassToNodeShouldWorkNoConstants() {\n\n\t\t// tag::query-dsl-simple-avoid-constants[]\n\t\tQPerson n = new QPerson(\"n\");\n\t\tStatement statement = Cypher.match(Cypher.adapt(n).asNode())\n\t\t\t.where(Cypher.adapt(n.firstName.eq(\"P\").and(n.age.gt(25))).asCondition())\n\t\t\t.returning(Cypher.adapt(n).asName())\n\t\t\t.build();\n\n\t\tstatement.setRenderConstantsAsParameters(true); // <.>\n\t\tassertThat(statement.getCatalog().getParameters()).containsEntry(\"pcdsl01\", \"P\"); // <.>\n\t\tassertThat(statement.getCatalog().getParameters()).containsEntry(\"pcdsl02\", 25);\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(\"MATCH (n:`Person`) WHERE n.firstName = $pcdsl01 AND n.age > $pcdsl02 RETURN n\"); // <.>\n\t\t// end::query-dsl-simple-avoid-constants[]\n\t}\n\n\t@Test\n\tvoid changingModeShouldWork() {\n\n\t\tQPerson n = new QPerson(\"n\");\n\t\tStatement statement = Cypher.match(Cypher.adapt(n).asNode())\n\t\t\t.where(Cypher.adapt(n.firstName.eq(\"P\").and(n.age.gt(25))).asCondition())\n\t\t\t.returning(Cypher.adapt(n).asName())\n\t\t\t.build();\n\n\t\tstatement.setRenderConstantsAsParameters(true); // <.>\n\t\tassertThat(statement.getCatalog().getParameters()).containsEntry(\"pcdsl01\", \"P\"); // <.>\n\t\tassertThat(statement.getCatalog().getParameters()).containsEntry(\"pcdsl02\", 25);\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(\"MATCH (n:`Person`) WHERE n.firstName = $pcdsl01 AND n.age > $pcdsl02 RETURN n\"); // <.>\n\n\t\tstatement.setRenderConstantsAsParameters(false);\n\t\tassertThat(statement.getCatalog().getParameters()).isEmpty();\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(\"MATCH (n:`Person`) WHERE n.firstName = 'P' AND n.age > 25 RETURN n\");\n\t}\n\n\t@Test\n\tvoid prettyPrinterShouldAlwaysUseConstants() {\n\n\t\tQPerson n = new QPerson(\"n\");\n\t\tStatement statement = Cypher.match(Cypher.adapt(n).asNode())\n\t\t\t.where(Cypher.adapt(n.firstName.eq(\"P\").and(n.age.gt(25))).asCondition())\n\t\t\t.returning(Cypher.adapt(n).asName())\n\t\t\t.build();\n\n\t\tstatement.setRenderConstantsAsParameters(true);\n\t\tassertThat(statement.getCatalog().getParameters()).containsEntry(\"pcdsl01\", \"P\");\n\t\tassertThat(statement.getCatalog().getParameters()).containsEntry(\"pcdsl02\", 25);\n\t\tassertThat(Renderer.getRenderer(Configuration.prettyPrinting()).render(statement)).isEqualTo(\"\"\"\n\t\t\t\tMATCH (n:Person)\n\t\t\t\tWHERE n.firstName = 'P' AND n.age > 25\n\t\t\t\tRETURN n\"\"\");\n\t}\n\n\t@Test\n\tvoid parametersShouldBeRendered() {\n\n\t\t// tag::query-dsl-parameters[]\n\t\tQPerson n = new QPerson(\"n\");\n\t\tStatement statement = Cypher.match(Cypher.adapt(n).asNode())\n\t\t\t.where(Cypher.adapt(\n\t\t\t\t\tn.firstName.eq(new Param<>(String.class, \"name\")).and(n.age.gt(new Param<>(Integer.class, \"age\"))) // <.>\n\t\t\t).asCondition())\n\t\t\t.returning(Cypher.adapt(n).asName())\n\t\t\t.build();\n\n\t\tassertThat(statement.getCatalog().getParameterNames()).hasSize(2); // <.>\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(\"MATCH (n:`Person`) WHERE n.firstName = $name AND n.age > $age RETURN n\");\n\t\t// end::query-dsl-parameters[]\n\t}\n\n\t@Test\n\tvoid regexShouldBeSupported() {\n\n\t\tQPerson n = new QPerson(\"n\");\n\t\tStatement statement = Cypher.match(Cypher.adapt(n).asNode())\n\t\t\t.where(Cypher.adapt(n.firstName.matches(\"(?i).*rick.*\")).asCondition())\n\t\t\t.returning(Cypher.adapt(n).asName())\n\t\t\t.build();\n\n\t\tassertThat(statement.getCatalog().getParameterNames()).isEmpty();\n\t\tassertThat(statement.getCypher()).isEqualTo(\"MATCH (n:`Person`) WHERE n.firstName =~ '(?i).*rick.*' RETURN n\");\n\t}\n\n\t@Test\n\tvoid existShouldWork() {\n\n\t\tQPerson n = new QPerson(\"n\");\n\t\tStatement statement = Cypher.match(Cypher.adapt(n).asNode())\n\t\t\t.where(Cypher.adapt(Expressions.predicate(Ops.EXISTS, n.firstName)).asCondition())\n\t\t\t.returning(Cypher.adapt(n).asName())\n\t\t\t.build();\n\n\t\tassertThat(statement.getCatalog().getParameterNames()).isEmpty();\n\t\tassertThat(statement.getCypher()).isEqualTo(\"MATCH (n:`Person`) WHERE exists(n.firstName) RETURN n\");\n\t}\n\n\t@Test\n\tvoid shouldNotAdaptArbitraryThingsAsCondition() {\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.adapt(Expressions.TWO).asCondition())\n\t\t\t.withMessage(\"Only Query-DSL predicates can be turned into Cypher-DSL's predicates.\");\n\t}\n\n\t@Test\n\tvoid shouldNotAdaptArbitraryThingsAsNodes() {\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.adapt(Expressions.TWO).asNode())\n\t\t\t.withMessage(\"Only Query-DSL paths can be turned into nodes.\");\n\t}\n\n\t@Test\n\tvoid shouldNotAdaptArbitraryThingsAsNames() {\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> Cypher.adapt(Expressions.TWO).asName())\n\t\t\t.withMessage(\"Only Query-DSL paths can be turned into names.\");\n\t}\n\n\t@Test\n\tvoid emptyBooleanBuilder() {\n\n\t\tCondition condition = Cypher.adapt(new BooleanBuilder()).asCondition();\n\t\tStatement statement = Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t.where(condition)\n\t\t\t.returning(Cypher.name(\"n\"))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCatalog().getParameterNames()).isEmpty();\n\t\tassertThat(statement.getCypher()).isEqualTo(\"MATCH (n) RETURN n\");\n\t}\n\n\t@Test\n\tvoid booleanBuilder() {\n\n\t\tCondition condition = Cypher.adapt(new BooleanBuilder().and(Expressions.FALSE).and(Expressions.TRUE))\n\t\t\t.asCondition();\n\t\tStatement statement = Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t.where(condition)\n\t\t\t.returning(Cypher.name(\"n\"))\n\t\t\t.build();\n\n\t\tassertThat(statement.getCatalog().getParameterNames()).isEmpty();\n\t\tassertThat(statement.getCypher()).isEqualTo(\"MATCH (n) WHERE false AND true RETURN n\");\n\t}\n\n\t@Test\n\tvoid communityExample() {\n\n\t\tQPerson user = QPerson.person;\n\n\t\tPredicate predicate = user.firstName.equalsIgnoreCase(\"dave\")\n\t\t\t.and(user.lastName.startsWithIgnoreCase(\"mathews\"));\n\n\t\tNode p = Cypher.node(\"Entity\").named(\"p\");\n\t\tString cypher = Cypher.match(p).where(Cypher.adapt(predicate).asCondition()).returning(p).build().getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (p:`Entity`) WHERE toLower(person.firstName) = 'dave' AND toLower(person.lastName) STARTS WITH 'mathews' RETURN p\");\n\t}\n\n\t@Test\n\tvoid communityExampleWithWorkaround() {\n\n\t\tQPerson user = QPerson.person;\n\n\t\tPredicate predicate = user.firstName.toLowerCase()\n\t\t\t.eq(\"dave\".toLowerCase())\n\t\t\t.and(user.lastName.startsWithIgnoreCase(\"mathews\"));\n\n\t\tNode p = Cypher.node(\"Entity\").named(\"p\");\n\t\tString cypher = Cypher.match(p).where(Cypher.adapt(predicate).asCondition()).returning(p).build().getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (p:`Entity`) WHERE toLower(person.firstName) = 'dave' AND toLower(person.lastName) STARTS WITH 'mathews' RETURN p\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/querydsl/Stuff.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.querydsl;\n\nimport com.querydsl.core.annotations.QueryEntity;\n\n/**\n * @author Rickard Öberg\n */\n@QueryEntity\npublic class Stuff {\n\n\tString name;\n\n\tpublic String getName() {\n\t\treturn this.name;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/querydsl/UnsupportedOperatorExceptionTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.querydsl;\n\nimport com.querydsl.core.types.Ops;\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\n/**\n * @author Michael J. Simons\n */\nclass UnsupportedOperatorExceptionTests {\n\n\t@Test\n\tvoid unsupportedOperatorShouldBeAccessible() {\n\n\t\tAssertions.assertThat(new UnsupportedOperatorException(Ops.MathOps.ABS).getUnsupportedOperator())\n\t\t\t.isEqualTo(Ops.MathOps.ABS);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/renderer/ConfigurableRendererTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport java.util.EnumSet;\nimport java.util.Map;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.Cypher;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass ConfigurableRendererTests {\n\n\t@Test\n\tvoid cacheShouldWork() {\n\n\t\tvar statement = Cypher.match(Cypher.node(\"Movie\").named(\"n\")).returning(Cypher.name(\"n\").property(\"f\")).build();\n\n\t\tvar cypher1 = Renderer.getDefaultRenderer().render(statement);\n\t\tvar cypher2 = Renderer.getDefaultRenderer().render(statement);\n\t\tassertThat(cypher1).isSameAs(cypher2);\n\n\t\tvar statement2 = Cypher.match(Cypher.node(\"Movie\").named(\"n\"))\n\t\t\t.returning(Cypher.name(\"n\").property(\"f\"))\n\t\t\t.build();\n\t\tvar cypher3 = Renderer.getDefaultRenderer().render(statement2);\n\t\tassertThat(cypher2).isNotSameAs(cypher3);\n\t}\n\n\t@Test // GH-596\n\tvoid shouldGenerateConstantNamesPerSchema() {\n\n\t\tvar actor = Cypher.node(\"Actor\").named(\"a\");\n\t\tvar cool = Cypher.parameter(\"cool\");\n\t\tvar statement = Cypher.with(Cypher.literalOf(\"The Matrix\").as(Cypher.name(\"title\")))\n\t\t\t.match(Cypher.node(\"Movie\")\n\t\t\t\t.named(\"n\")\n\t\t\t\t.withProperties(\"foo\", Cypher.literalOf(\"bazbar\"))\n\t\t\t\t.relationshipFrom(actor, \"ACTED_IN\")\n\t\t\t\t.named(\"r\"))\n\t\t\t.where(Cypher.name(\"n\").property(\"title\").eq(Cypher.name(\"title\")))\n\t\t\t.and(Cypher.name(\"a\").property(\"name\").eq(Cypher.literalOf(\"Keanu Reeves\")))\n\t\t\t.and(actor.property(\"born\").isEqualTo(Cypher.parameter(\"born\")))\n\t\t\t.and(actor.property(\"cool\").isEqualTo(cool))\n\t\t\t.and(actor.property(\"cool2\").isEqualTo(cool))\n\t\t\t.and(actor.property(\"whatever\").isEqualTo(Cypher.parameter(\"born\")))\n\t\t\t.and(Cypher.name(\"r\").property(\"x\").isEqualTo(Cypher.anonParameter(\"foo\")))\n\t\t\t.returning(Cypher.name(\"n\").property(\"f\"))\n\t\t\t.build();\n\n\t\tvar cypher1 = Renderer.getRenderer(Configuration.newConfig().withGeneratedNames(true).build())\n\t\t\t.render(statement);\n\n\t\tvar expectedGeneratedNames = \"WITH 'The Matrix' AS v0 \"\n\t\t\t\t+ \"MATCH (v1:`Movie` {foo: 'bazbar'})<-[v2:`ACTED_IN`]-(v3:`Actor`) \"\n\t\t\t\t+ \"WHERE (v1.title = v0 AND v3.name = 'Keanu Reeves' AND v3.born = $p0 AND \"\n\t\t\t\t+ \"v3.cool = $p1 AND v3.cool2 = $p1 AND v3.whatever = $p0 AND v2.x = $pcdsl01) RETURN v1.f\";\n\n\t\tvar expectedDefault = \"WITH 'The Matrix' AS title \"\n\t\t\t\t+ \"MATCH (n:`Movie` {foo: 'bazbar'})<-[r:`ACTED_IN`]-(a:`Actor`) \"\n\t\t\t\t+ \"WHERE (n.title = title AND a.name = 'Keanu Reeves' AND a.born = $born AND \"\n\t\t\t\t+ \"a.cool = $cool AND a.cool2 = $cool AND a.whatever = $born AND r.x = $pcdsl01) RETURN n.f\";\n\n\t\tassertThat(cypher1).isEqualTo(expectedGeneratedNames);\n\t\tassertThat(statement.getCatalog().getRenamedParameters()).containsExactly(Map.entry(\"born\", \"p0\"),\n\t\t\t\tMap.entry(\"cool\", \"p1\"));\n\n\t\t// Compare a second rendering\n\t\tvar cypher2 = Renderer.getRenderer(Configuration.newConfig().withGeneratedNames(true).build())\n\t\t\t.render(statement);\n\t\tassertThat(cypher2).isEqualTo(expectedGeneratedNames);\n\t\tassertThat(cypher1).isSameAs(cypher2);\n\n\t\tassertThat(statement.getCypher()).isEqualTo(expectedDefault);\n\t}\n\n\t@Test // GH-645\n\tvoid shouldExportSymbolicNames() {\n\n\t\tvar stmnt = Cypher.match(Cypher.node(\"N\").named(\"n\"))\n\t\t\t.call(Cypher.match(Cypher.anyNode(\"m\")).returning(Cypher.name(\"m\")).build())\n\t\t\t.returning(\"n\", \"m\")\n\t\t\t.build();\n\t\tassertThat(Renderer\n\t\t\t.getRenderer(Configuration.newConfig()\n\t\t\t\t.withGeneratedNames(EnumSet.complementOf(EnumSet.of(Configuration.GeneratedNames.ENTITY_NAMES)))\n\t\t\t\t.build())\n\t\t\t.render(stmnt)).isEqualTo(\"MATCH (n:`N`) CALL (*) {MATCH (m) RETURN m} RETURN n, m\");\n\t}\n\n\t@Test // GH-645\n\tvoid shouldExportNamedAsSymbolicNames() {\n\n\t\tvar m = Cypher.anyNode(\"m\");\n\t\tvar stmnt = Cypher.match(Cypher.node(\"N\").named(\"n\"))\n\t\t\t.call(Cypher.match(m).returning(m).build())\n\t\t\t.returning(\"n\", \"m\")\n\t\t\t.build();\n\t\tassertThat(Renderer\n\t\t\t.getRenderer(Configuration.newConfig()\n\t\t\t\t.withGeneratedNames(EnumSet.complementOf(EnumSet.of(Configuration.GeneratedNames.ENTITY_NAMES)))\n\t\t\t\t.build())\n\t\t\t.render(stmnt)).isEqualTo(\"MATCH (n:`N`) CALL (*) {MATCH (m) RETURN m} RETURN n, m\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/renderer/ConfigurationTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n *\n */\nclass ConfigurationTests {\n\n\t@Test\n\tvoid dialectShouldBeIncludedInEquals() {\n\n\t\tConfiguration cfg0 = Configuration.newConfig().build();\n\t\tConfiguration cfg1 = Configuration.newConfig().withDialect(Dialect.NEO4J_5_DEFAULT_CYPHER).build();\n\t\tConfiguration cfg2 = Configuration.newConfig().withDialect(Dialect.NEO4J_4).build();\n\n\t\tassertThat(cfg0).isEqualTo(cfg1).isNotEqualTo(cfg2);\n\t}\n\n\t@Test\n\tvoid dialectShouldBeIncludedInHash() {\n\n\t\tConfiguration cfg0 = Configuration.newConfig().build();\n\t\tConfiguration cfg1 = Configuration.newConfig().withDialect(Dialect.NEO4J_5_DEFAULT_CYPHER).build();\n\t\tConfiguration cfg2 = Configuration.newConfig().withDialect(Dialect.NEO4J_4).build();\n\n\t\tassertThat(cfg0).hasSameHashCodeAs(cfg1).doesNotHaveSameHashCodeAs(cfg2);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/renderer/DefaultVisitorTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.CsvSource;\nimport org.junit.jupiter.params.provider.EnumSource;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass DefaultVisitorTests {\n\n\tprivate final DefaultVisitor visitor = new DefaultVisitor(null);\n\n\t@ParameterizedTest\n\t@CsvSource({ \"ALabel, `ALabel`\", \"A Label, `A Label`\", \"A `Label, `A ``Label`\", \"`A `Label, ```A ``Label`\",\n\t\t\t\"Spring Data Neo4j⚡️RX, `Spring Data Neo4j⚡️RX`\" })\n\tvoid shouldCorrectlyEscapeNames(String name, String expectedEscapedName) {\n\n\t\tassertThat(this.visitor.escapeName(name)).hasValue(expectedEscapedName);\n\t}\n\n\t@Test\n\tvoid shouldNotTryToEscapeNullNames() {\n\n\t\tassertThat(this.visitor.escapeName(null)).isEmpty();\n\t}\n\n\t@EnumSource(TestEnum.class)\n\t@ParameterizedTest\n\tvoid underscoresInEnumsShouldBeRemoved(TestEnum testEnum) {\n\n\t\tDefaultVisitor visitorUnderTest = new DefaultVisitor(null);\n\t\tvisitorUnderTest.enter(testEnum);\n\t\tassertThat(visitorUnderTest.builder).hasToString(testEnum.expected);\n\t}\n\n\t@ParameterizedTest\n\t@CsvSource({ \"ABC, ABC\", \"A C, `A C`\", \"A` C, `A`` C`\", \"A`` C, `A`` C`\", \"ALabel, ALabel\", \"A Label, `A Label`\",\n\t\t\t\"A `Label, `A ``Label`\", \"`A `Label, ```A ``Label`\", \"Spring Data Neo4j⚡️RX, `Spring Data Neo4j⚡️RX`\",\n\t\t\t\"Foo \\u0060, `Foo ```\", // This is the backtick itself in the string\n\t\t\t\"Foo \\\\u0060, `Foo ```\", // This is the backtick unicode escaped so that\n\t\t\t\t\t\t\t\t\t\t// without further processing `foo \\u0060` would\n\t\t\t\t\t\t\t\t\t\t// end up at Cypher,\n\t\t\t\"`, ````\", \"\\u0060, ````\", \"```, ``````\", \"\\u0060\\u0060\\u0060, ``````\", \"Hello`, `Hello```\",\n\t\t\t\"Hi````there, `Hi````there`\", \"Hi`````there, `Hi``````there`\", \"`a`b`c`, ```a``b``c```\",\n\t\t\t\"\\u0060a`b`c\\u0060d\\u0060, ```a``b``c``d```\" })\n\tvoid shouldEscapeIfNecessary(String name, String expectedEscapedName) {\n\n\t\tassertThat(this.visitor.escapeIfNecessary(name)).isEqualTo(expectedEscapedName);\n\t}\n\n\t@Test\n\tvoid shouldNotUnnecessaryEscape() {\n\n\t\tassertThat(this.visitor.escapeIfNecessary(\" \")).isEqualTo(\"` `\");\n\t\tassertThat(this.visitor.escapeIfNecessary(null)).isNull();\n\t\tassertThat(this.visitor.escapeIfNecessary(\"a\")).isEqualTo(\"a\");\n\t}\n\n\tenum TestEnum {\n\n\t\tNO(\"NO\"), ONE_UNDERSCORE(\"ONE UNDERSCORE\"), THOSE_ARE_MORE_UNDERSCORES(\"THOSE ARE MORE UNDERSCORES\");\n\n\t\tString expected;\n\n\t\tTestEnum(String expected) {\n\t\t\tthis.expected = expected + \" \";\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/java/org/neo4j/cypherdsl/core/renderer/PrettyPrintingVisitorTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.core.renderer;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.CsvSource;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Andreas Berger\n * @author Michael J. Simons\n */\nclass PrettyPrintingVisitorTests {\n\n\tprivate final PrettyPrintingVisitor prettyPrintingVisitor = new PrettyPrintingVisitor(null,\n\t\t\tConfiguration.newConfig()\n\t\t\t\t.alwaysEscapeNames(false)\n\t\t\t\t.withIndentStyle(Configuration.IndentStyle.TAB)\n\t\t\t\t.withIndentSize(4)\n\t\t\t\t.build());\n\n\t@ParameterizedTest\n\t@CsvSource({ \"ALabel, ALabel\", \"A Label, `A Label`\", \"A `Label, `A ``Label`\", \"`A `Label, ```A ``Label`\",\n\t\t\t\"Spring Data Neo4j⚡️RX, `Spring Data Neo4j⚡️RX`\" })\n\tvoid shouldCorrectlyEscapeNames(String name, String expectedEscapedName) {\n\n\t\tassertThat(this.prettyPrintingVisitor.escapeName(name)).hasValue(expectedEscapedName);\n\t}\n\n\t@Test\n\tvoid shouldNotTryToEscapeNullNames() {\n\n\t\tassertThat(this.prettyPrintingVisitor.escapeName(null)).isEmpty();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker",
    "content": "mock-maker-inline\n"
  },
  {
    "path": "neo4j-cypher-dsl-bom/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-parent</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-bom</artifactId>\n\n\t<packaging>pom</packaging>\n\t<name>Neo4j Cypher DSL (BOM)</name>\n\t<description>The BOM for the Neo4j Cypher DSL.</description>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-dsl</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-dsl-codegen-core</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-dsl-codegen-ogm</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-dsl-codegen-sdn6</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-dsl-parser</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-dsl-schema-name-support</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.codehaus.mojo</groupId>\n\t\t\t\t<artifactId>flatten-maven-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"override\">\n\t\t\t\t\t<updatePomFile>true</updatePomFile>\n\t\t\t\t\t<flattenMode>bom</flattenMode>\n\t\t\t\t\t<pomElements>\n\t\t\t\t\t\t<properties>remove</properties>\n\t\t\t\t\t</pomElements>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/annotations/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-build</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-build-annotations</artifactId>\n\n\t<name>Neo4j Cypher DSL (Build Utils: Annotations)</name>\n\t<description>Annotations for minimum GraalVM support.</description>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-install-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<compilerArgument>-proc:none</compilerArgument>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/annotations/src/main/java/module-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * For internal use only: Marks classes for inclusion in reflection-config.json for GraalVM.\n *\n * @author Michael J. Simons\n * @since 2023.0.0\n */\nmodule org.neo4j.cypherdsl.build.annotations {\n\n\texports org.neo4j.cypherdsl.build.annotations;\n}"
  },
  {
    "path": "neo4j-cypher-dsl-build/annotations/src/main/java/org/neo4j/cypherdsl/build/annotations/RegisterForReflection.java",
    "content": "/*\n * Copyright (c) 2019-2025 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.build.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * Used to mark classes to be included in `reflection-config.json` so that it doesn't need\n * updates when new reflective visitors and the like are added.\n * <p>\n * A thin documentation about the file format can be found <a href=\n * \"https://github.com/oracle/graal/blob/master/docs/reference-manual/native-image/Reflection.md\">here</a>.\n * For now, only {@code allDeclaredMethods} is supported.\n * <p>\n * In the future, support can be added for\n * <ul>\n * <li><code>allPublicConstructors</code></li>\n * <li><code>allPublicMethods</code></li>\n * <li><code>allPublicFields</code></li>\n * <li><code>allDeclaredConstructors</code></li>\n * <li><code>allDeclaredFields</code></li>\n * </ul>\n *\n * @author Michael J. Simons\n * @since 2022.2.2\n */\n@Retention(RetentionPolicy.CLASS)\n@Target(ElementType.TYPE)\npublic @interface RegisterForReflection {\n\n\t/**\n\t * {@return true if all declared methods should be marked for inclusion}\n\t */\n\tboolean allDeclaredMethods() default true;\n\n\t/**\n\t * {@return true if all declared constructors should be marked for inclusion}\n\t */\n\tboolean allDeclaredConstructors() default false;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/annotations/src/main/java/org/neo4j/cypherdsl/build/annotations/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2025 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Utilities to make our lives a bit easier with GraalVM native image. Designed and\n * catered for our own needs, not meant to be consumed by other libraries.\n */\npackage org.neo4j.cypherdsl.build.annotations;\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-parent</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-build</artifactId>\n\t<packaging>pom</packaging>\n\n\t<name>Neo4j Cypher DSL (Build Utils)</name>\n\t<description>Annotations and processors for minimum GraalVM support.</description>\n\n\t<modules>\n\t\t<module>annotations</module>\n\t\t<module>processor</module>\n\t</modules>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-install-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/processor/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-build</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-build-proc</artifactId>\n\n\t<name>Neo4j Cypher DSL (Build Utils: Processor)</name>\n\t<description>Annotations and processors for minimum GraalVM support.</description>\n\n\t<properties>\n\t\t<java-module-name>org.neo4j.cypherdsl.build.proc</java-module-name>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>com.fasterxml.jackson.core</groupId>\n\t\t\t<artifactId>jackson-databind</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl-build-annotations</artifactId>\n\t\t\t<version>${project.version}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.google.testing.compile</groupId>\n\t\t\t<artifactId>compile-testing</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.assertj</groupId>\n\t\t\t<artifactId>assertj-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-install-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<compilerArgument>-proc:none</compilerArgument>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-jar-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<archive>\n\t\t\t\t\t\t<manifestEntries>\n\t\t\t\t\t\t\t<Automatic-Module-Name>${java-module-name}</Automatic-Module-Name>\n\t\t\t\t\t\t</manifestEntries>\n\t\t\t\t\t</archive>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/processor/src/main/java/org/neo4j/cypherdsl/build/processor/Entry.java",
    "content": "/*\n * Copyright (c) 2019-2025 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.build.processor;\n\nimport com.fasterxml.jackson.annotation.JsonAutoDetect;\nimport com.fasterxml.jackson.annotation.JsonInclude;\n\n/**\n * An entry that should find its way into GraalVM reflection-config.json.\n *\n * @author Michael J. Simons\n */\n@JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.NON_PRIVATE,\n\t\tisGetterVisibility = JsonAutoDetect.Visibility.NON_PRIVATE)\nfinal class Entry {\n\n\tprivate final String name;\n\n\tprivate boolean allDeclaredMethods;\n\n\tprivate boolean allDeclaredConstructors;\n\n\tEntry(String name) {\n\t\tthis.name = name;\n\t}\n\n\tString getName() {\n\t\treturn this.name;\n\t}\n\n\t@JsonInclude(JsonInclude.Include.NON_DEFAULT)\n\tboolean isAllDeclaredMethods() {\n\t\treturn this.allDeclaredMethods;\n\t}\n\n\tvoid setAllDeclaredMethods(boolean allDeclaredMethods) {\n\t\tthis.allDeclaredMethods = allDeclaredMethods;\n\t}\n\n\t@JsonInclude(JsonInclude.Include.NON_DEFAULT)\n\tboolean isAllDeclaredConstructors() {\n\t\treturn this.allDeclaredConstructors;\n\t}\n\n\tvoid setAllDeclaredConstructors(boolean allDeclaredConstructors) {\n\t\tthis.allDeclaredConstructors = allDeclaredConstructors;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/processor/src/main/java/org/neo4j/cypherdsl/build/processor/RegisterForReflectionProcessor.java",
    "content": "/*\n * Copyright (c) 2019-2025 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.build.processor;\n\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.util.Collection;\nimport java.util.Comparator;\nimport java.util.Set;\nimport java.util.TreeSet;\n\nimport javax.annotation.processing.AbstractProcessor;\nimport javax.annotation.processing.RoundEnvironment;\nimport javax.annotation.processing.SupportedAnnotationTypes;\nimport javax.annotation.processing.SupportedOptions;\nimport javax.lang.model.SourceVersion;\nimport javax.lang.model.element.TypeElement;\nimport javax.tools.Diagnostic;\nimport javax.tools.FileObject;\nimport javax.tools.StandardLocation;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.SerializationFeature;\nimport org.neo4j.cypherdsl.build.annotations.RegisterForReflection;\n\n/**\n * Processor reacting on {@code @RegisterForReflection}.\n *\n * @author Michael J. Simons\n * @since 2022.2.2\n */\n@SupportedAnnotationTypes(\"org.neo4j.cypherdsl.build.annotations.RegisterForReflection\")\n@SupportedOptions(RegisterForReflectionProcessor.NATIVE_IMAGE_SUBDIR_OPTION)\npublic final class RegisterForReflectionProcessor extends AbstractProcessor {\n\n\tstatic final String NATIVE_IMAGE_SUBDIR_OPTION = \"org.neo4j.cypherdsl.build.native_config_dir\";\n\n\tprivate static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);\n\n\tprivate final Collection<Entry> entries = new TreeSet<>(Comparator.comparing(Entry::getName));\n\n\tstatic boolean registersElements(RegisterForReflection registerForReflection) {\n\t\treturn registerForReflection.allDeclaredMethods() || registerForReflection.allDeclaredConstructors();\n\t}\n\n\t@Override\n\tpublic SourceVersion getSupportedSourceVersion() {\n\t\treturn SourceVersion.latestSupported();\n\t}\n\n\t@Override\n\tpublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {\n\n\t\tif (roundEnv.processingOver() && !this.entries.isEmpty()) {\n\t\t\ttry {\n\t\t\t\tString subDir = this.processingEnv.getOptions().getOrDefault(NATIVE_IMAGE_SUBDIR_OPTION, \"\");\n\t\t\t\tif (!(subDir.isEmpty() || subDir.endsWith(\"/\"))) {\n\t\t\t\t\tsubDir += \"/\";\n\t\t\t\t}\n\t\t\t\tString reflectionConfigPath = String.format(\"META-INF/native-image/%sreflection-config.json\", subDir);\n\t\t\t\tFileObject fileObject = this.processingEnv.getFiler()\n\t\t\t\t\t.createResource(StandardLocation.CLASS_OUTPUT, \"\", reflectionConfigPath);\n\t\t\t\ttry (OutputStream oos = fileObject.openOutputStream()) {\n\t\t\t\t\tOBJECT_MAPPER.writeValue(oos, this.entries);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (IOException ex) {\n\t\t\t\tthis.processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, ex.getMessage());\n\t\t\t}\n\t\t}\n\t\telse if (!annotations.isEmpty()) {\n\t\t\troundEnv.getElementsAnnotatedWith(RegisterForReflection.class)\n\t\t\t\t.stream()\n\t\t\t\t.filter(e -> e.getKind().isClass() && registersElements(e.getAnnotation(RegisterForReflection.class)))\n\t\t\t\t.map(TypeElement.class::cast)\n\t\t\t\t.map(e -> {\n\t\t\t\t\tRegisterForReflection registerForReflection = e.getAnnotation(RegisterForReflection.class);\n\t\t\t\t\tEntry entry = new Entry(e.getQualifiedName().toString());\n\t\t\t\t\tentry.setAllDeclaredMethods(registerForReflection.allDeclaredMethods());\n\t\t\t\t\tentry.setAllDeclaredConstructors(registerForReflection.allDeclaredConstructors());\n\t\t\t\t\treturn entry;\n\t\t\t\t})\n\t\t\t\t.forEach(this.entries::add);\n\t\t}\n\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/processor/src/main/java/org/neo4j/cypherdsl/build/processor/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2025 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Contains the processors for the built-time annotations.\n */\npackage org.neo4j.cypherdsl.build.processor;\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor",
    "content": "org.neo4j.cypherdsl.build.processor.RegisterForReflectionProcessor\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/processor/src/test/java/org/neo4j/cypherdsl/build/processor/RegisterForReflectionProcessorTests.java",
    "content": "/*\n * Copyright (c) 2019-2025 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.build.processor;\n\nimport java.io.IOException;\nimport java.io.UncheckedIOException;\nimport java.util.Objects;\nimport java.util.stream.IntStream;\n\nimport javax.tools.JavaFileObject;\nimport javax.tools.StandardLocation;\n\nimport com.google.testing.compile.Compilation;\nimport com.google.testing.compile.Compiler;\nimport com.google.testing.compile.JavaFileObjects;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass RegisterForReflectionProcessorTests {\n\n\tstatic Compiler getCompiler(Object... options) {\n\n\t\tObject[] defaultOptions = new Object[] { \"--release\", \"17\" };\n\n\t\tObject[] finalOptions = new Object[options.length + defaultOptions.length];\n\t\tSystem.arraycopy(defaultOptions, 0, finalOptions, 0, defaultOptions.length);\n\t\tSystem.arraycopy(options, 0, finalOptions, defaultOptions.length, options.length);\n\n\t\treturn Compiler.javac().withOptions(finalOptions);\n\t}\n\n\t@Test\n\tvoid shouldOnlyGenerateReflectionConfigWithContentWhenClassesArePresent() {\n\t\tJavaFileObject[] resources = IntStream.range(0, 4).mapToObj(this::getTestClassN).toArray(JavaFileObject[]::new);\n\n\t\tCompilation compilation = getCompiler(\"-Aorg.neo4j.cypherdsl.build.native_config_dir=foo/bar\")\n\t\t\t.withProcessors(new RegisterForReflectionProcessor())\n\t\t\t.compile(resources);\n\n\t\tassertThat(compilation.status()).isEqualTo(Compilation.Status.SUCCESS);\n\t\tassertThat(compilation.warnings()).isEmpty();\n\t\tassertThat(compilation.generatedFile(StandardLocation.CLASS_OUTPUT,\n\t\t\t\t\"META-INF/native-image/foo/bar/reflection-config.json\"))\n\t\t\t.map(f -> {\n\t\t\t\ttry {\n\t\t\t\t\treturn f.getCharContent(true);\n\t\t\t\t}\n\t\t\t\tcatch (IOException ex) {\n\t\t\t\t\tthrow new UncheckedIOException(ex);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.hasValue(\"\"\"\n\t\t\t\t\t[ {\n\t\t\t\t\t  \"name\" : \"org.neo4j.cypherdsl.build.test.Class0\",\n\t\t\t\t\t  \"allDeclaredMethods\" : true\n\t\t\t\t\t}, {\n\t\t\t\t\t  \"name\" : \"org.neo4j.cypherdsl.build.test.Class3\",\n\t\t\t\t\t  \"allDeclaredConstructors\" : true\n\t\t\t\t\t} ]\"\"\");\n\t}\n\n\t@Test\n\tvoid shouldHandleEmptyDir() {\n\t\tCompilation compilation = getCompiler().withProcessors(new RegisterForReflectionProcessor())\n\t\t\t.compile(getTestClassN(0));\n\n\t\tassertThat(compilation.status()).isEqualTo(Compilation.Status.SUCCESS);\n\t\tassertThat(compilation.warnings()).isEmpty();\n\t\tassertThat(compilation.generatedFile(StandardLocation.CLASS_OUTPUT,\n\t\t\t\t\"META-INF/native-image/reflection-config.json\"))\n\t\t\t.isPresent();\n\t}\n\n\t@Test\n\tvoid shouldHandleSlash() {\n\t\tCompilation compilation = getCompiler(\"-Aorg.neo4j.cypherdsl.build.native_config_dir=foo/\")\n\t\t\t.withProcessors(new RegisterForReflectionProcessor())\n\t\t\t.compile(getTestClassN(0));\n\n\t\tassertThat(compilation.status()).isEqualTo(Compilation.Status.SUCCESS);\n\t\tassertThat(compilation.warnings()).isEmpty();\n\t\tassertThat(compilation.generatedFile(StandardLocation.CLASS_OUTPUT,\n\t\t\t\t\"META-INF/native-image/foo/reflection-config.json\"))\n\t\t\t.isPresent();\n\t}\n\n\t@Test\n\tvoid shouldNotGenerateEmpty() {\n\t\tJavaFileObject[] resources = IntStream.range(1, 3).mapToObj(this::getTestClassN).toArray(JavaFileObject[]::new);\n\n\t\tCompilation compilation = getCompiler(\"-Aorg.neo4j.cypherdsl.build.native_config_dir=foo/bar\")\n\t\t\t.withProcessors(new RegisterForReflectionProcessor())\n\t\t\t.compile(resources);\n\n\t\tassertThat(compilation.status()).isEqualTo(Compilation.Status.SUCCESS);\n\t\tassertThat(compilation.warnings()).isEmpty();\n\t\tassertThat(compilation.generatedFile(StandardLocation.CLASS_OUTPUT,\n\t\t\t\t\"META-INF/native-image/foo/bar/reflection-config.json\"))\n\t\t\t.isEmpty();\n\t}\n\n\tprivate JavaFileObject getTestClassN(int i) {\n\t\treturn JavaFileObjects.forResource(\n\t\t\t\tObjects.requireNonNull(this.getClass().getResource(String.format(\"/test_classes/Class%d.java\", i))));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/processor/src/test/resources/test_classes/Class0.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.build.test;\n\nimport org.neo4j.cypherdsl.build.annotations.RegisterForReflection;\n\n@RegisterForReflection\npublic class Class0 {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/processor/src/test/resources/test_classes/Class1.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.build.test;\n\nimport org.neo4j.cypherdsl.build.annotations.RegisterForReflection;\n\n@RegisterForReflection(allDeclaredMethods = false)\npublic class Class1 {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/processor/src/test/resources/test_classes/Class2.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.build.test;\n\npublic class Class2 {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-build/processor/src/test/resources/test_classes/Class3.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.build.test;\n\nimport org.neo4j.cypherdsl.build.annotations.RegisterForReflection;\n\n@RegisterForReflection(allDeclaredMethods = false, allDeclaredConstructors = true)\npublic class Class3 {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-codegen</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-codegen-core</artifactId>\n\t<name>Code Generator (Core)</name>\n\t<description>Core module for the Cypher DSL code generation.</description>\n\n\t<properties>\n\t\t<covered-ratio-complexity>0.1</covered-ratio-complexity>\n\t\t<covered-ratio-instructions>0.1</covered-ratio-instructions>\n\t\t<sonar.coverage.jacoco.xmlReportPaths>${basedir}/../../${aggregate.report.dir}</sonar.coverage.jacoco.xmlReportPaths>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>com.squareup</groupId>\n\t\t\t<artifactId>javapoet</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.google.testing.compile</groupId>\n\t\t\t<artifactId>compile-testing</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.assertj</groupId>\n\t\t\t<artifactId>assertj-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/module-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * @author Michael J. Simons\n * @since 2023.0.0\n */\n@SuppressWarnings({\"requires-automatic\"}) // javapoet\nmodule org.neo4j.cypherdsl.codegen.core {\n\n\trequires java.compiler;\n\n\trequires com.squareup.javapoet;\n\trequires transitive org.apiguardian.api;\n\trequires transitive org.neo4j.cypherdsl.core;\n\n\texports org.neo4j.cypherdsl.codegen.core;\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/AbstractClassNameGenerator.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Shared type name generator for the default naming strategies for generated node and\n * relationship implementations.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\nabstract class AbstractClassNameGenerator {\n\n\t/**\n\t * Strips away invalid identifiers, returns an initial upper case name.\n\t * @param suggestedName some arbitrary suggested name\n\t * @return a String builder for further processing.\n\t */\n\tfinal StringBuilder generateTypeName(String suggestedName) {\n\n\t\tStringBuilder sb = new StringBuilder();\n\n\t\tint codePoint;\n\t\tint i = 0;\n\t\twhile (i < suggestedName.length()) {\n\t\t\tcodePoint = suggestedName.codePointAt(i);\n\t\t\tif (Identifiers.isValidAt(i, codePoint)) {\n\t\t\t\tif (sb.isEmpty()) {\n\t\t\t\t\tcodePoint = Character.toUpperCase(codePoint);\n\t\t\t\t}\n\t\t\t\tsb.append(Character.toChars(codePoint));\n\t\t\t}\n\t\t\ti += Character.charCount(codePoint);\n\t\t}\n\n\t\treturn sb;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/AbstractMappingAnnotationProcessor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport java.io.IOException;\nimport java.io.Writer;\nimport java.util.AbstractMap;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\nimport javax.annotation.processing.AbstractProcessor;\nimport javax.annotation.processing.Filer;\nimport javax.annotation.processing.Messager;\nimport javax.annotation.processing.ProcessingEnvironment;\nimport javax.annotation.processing.RoundEnvironment;\nimport javax.lang.model.SourceVersion;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.ElementKind;\nimport javax.lang.model.element.NestingKind;\nimport javax.lang.model.element.PackageElement;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.type.DeclaredType;\nimport javax.lang.model.type.TypeKind;\nimport javax.lang.model.type.TypeMirror;\nimport javax.lang.model.util.SimpleElementVisitor8;\nimport javax.lang.model.util.Types;\nimport javax.tools.Diagnostic;\nimport javax.tools.JavaFileObject;\n\n/**\n * Base class to build generators based on Neo4j supported object mapping frameworks (we\n * ship with support for SDN6+ and Neo4j-OGM).\n *\n * @author Michael J. Simons\n * @since 2025.0.0\n */\npublic abstract class AbstractMappingAnnotationProcessor extends AbstractProcessor {\n\n\tprotected Messager messager;\n\n\tprotected Types typeUtils;\n\n\tprotected Filer filer;\n\n\tprotected Configuration configuration;\n\n\t/**\n\t * Default constructor is required by the annotation processor system of Java.\n\t */\n\tpublic AbstractMappingAnnotationProcessor() {\n\t}\n\n\t/**\n\t * Reads all supported from the processing environment and creates a suitable\n\t * {@link Configuration}.\n\t * @param processingEnv the processing environment\n\t * @return a working configuration\n\t */\n\tprotected static Configuration createConfiguration(ProcessingEnvironment processingEnv) {\n\t\tConfiguration.Builder builder = Configuration.newConfig();\n\t\tMap<String, String> options = processingEnv.getOptions();\n\t\tif (options.containsKey(Configuration.PROPERTY_PREFIX)) {\n\t\t\tbuilder.withPrefix(options.get(Configuration.PROPERTY_PREFIX));\n\t\t}\n\t\tif (options.containsKey(Configuration.PROPERTY_SUFFIX)) {\n\t\t\tbuilder.withSuffix(options.get(Configuration.PROPERTY_SUFFIX));\n\t\t}\n\t\tif (options.containsKey(Configuration.PROPERTY_INDENT_STYLE)) {\n\t\t\tbuilder\n\t\t\t\t.withIndentStyle(Configuration.IndentStyle.valueOf(options.get(Configuration.PROPERTY_INDENT_STYLE)));\n\t\t}\n\t\tif (options.containsKey(Configuration.PROPERTY_INDENT_SIZE)) {\n\t\t\tbuilder.withIndentSize(Integer.parseInt(options.get(Configuration.PROPERTY_INDENT_SIZE)));\n\t\t}\n\t\treturn builder.withTimestamp(options.getOrDefault(Configuration.PROPERTY_TIMESTAMP, null))\n\t\t\t.withAddAtGenerated(\n\t\t\t\t\tBoolean.parseBoolean(options.getOrDefault(Configuration.PROPERTY_ADD_AT_GENERATED, \"true\")))\n\t\t\t.withTarget(processingEnv.getSourceVersion().equals(SourceVersion.RELEASE_8)\n\t\t\t\t\t? Configuration.JavaVersion.RELEASE_8 : Configuration.JavaVersion.RELEASE_11)\n\t\t\t.withExcludes(options.get(Configuration.PROPERTY_EXCLUDES))\n\t\t\t.build();\n\t}\n\n\t/**\n\t * Checks if the definitions contain either all the same or no properties at all.\n\t * @param definitions a list of all relationship definitions for one owning node\n\t * @return true if all definitions have no or the same set of properties\n\t */\n\tprotected static boolean sameOrNoProperties(\n\t\t\tList<Map.Entry<NodeModelBuilder, RelationshipPropertyDefinition>> definitions) {\n\n\t\tboolean same = true;\n\t\tSet<PropertyDefinition> properties = null;\n\t\tfor (Map.Entry<NodeModelBuilder, RelationshipPropertyDefinition> definition : definitions) {\n\t\t\tSet<PropertyDefinition> newProperties = definition.getValue().getProperties();\n\t\t\tif (properties == null) {\n\t\t\t\tproperties = newProperties;\n\t\t\t}\n\t\t\telse if (properties.size() != newProperties.size() || !properties.containsAll(newProperties)) {\n\t\t\t\tsame = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn same;\n\t}\n\n\t/**\n\t * Returns all types annotated with {@code annotation} found in the environment of\n\t * this round.\n\t * @param annotation the annotation to search for\n\t * @param from the environment to extract from\n\t * @return a set of type elements that match the given annotation\n\t */\n\tprotected Set<TypeElement> getTypesAnnotatedWith(TypeElement annotation, RoundEnvironment from) {\n\t\treturn from.getElementsAnnotatedWith(annotation)\n\t\t\t.stream()\n\t\t\t.filter(e -> e.getKind().isClass())\n\t\t\t.map(TypeElement.class::cast)\n\t\t\t.filter(t -> !this.configuration.exclude(t.getQualifiedName().toString()))\n\t\t\t.collect(Collectors.toSet());\n\t}\n\n\t@Override\n\tpublic final synchronized void init(ProcessingEnvironment processingEnv) {\n\t\tsuper.init(processingEnv);\n\n\t\tthis.typeUtils = processingEnv.getTypeUtils();\n\t\tthis.filer = processingEnv.getFiler();\n\t\tthis.messager = processingEnv.getMessager();\n\n\t\tthis.configuration = createConfiguration(processingEnv);\n\n\t\tinitFrameworkSpecific(processingEnv);\n\t}\n\n\t/**\n\t * Do your framework specific initialisation here, such as figuring out your actual\n\t * annotations.\n\t * @param processingEnv the current processing env\n\t */\n\tprotected abstract void initFrameworkSpecific(ProcessingEnvironment processingEnv);\n\n\t@Override\n\tpublic final SourceVersion getSupportedSourceVersion() {\n\t\treturn SourceVersion.latestSupported();\n\t}\n\n\t/**\n\t * Creates {@link NodeModelBuilder node builder} for all classes annotated with\n\t * {@code @Node}. The node builders won't have any properties associated with them.\n\t * This is done in the next step.\n\t * <p>\n\t * The reason for not populating the properties in one go in this step is simple: When\n\t * one annotated node class refers to another, we can be sure that this property is\n\t * not a simple property but a relationship property, without going through other\n\t * expensive checks. But to be able to do this, we must know the annotated classes\n\t * upfront.\n\t * @param classesAnnotatedWithNode the set of annotated classes\n\t * @return a map from type to a node builder for that type\n\t */\n\tprotected final Map<TypeElement, NodeModelBuilder> populateListOfNodes(Set<TypeElement> classesAnnotatedWithNode) {\n\n\t\tMap<TypeElement, NodeModelBuilder> result = new HashMap<>();\n\t\tclassesAnnotatedWithNode.forEach(annotatedClass -> {\n\n\t\t\tString qualifiedName = annotatedClass.getQualifiedName().toString();\n\t\t\tString suggestedTypeName = annotatedClass.getSimpleName().toString();\n\t\t\tString packageName = null;\n\n\t\t\tList<String> subpackages = new LinkedList<>();\n\t\t\tElement enclosingElement = annotatedClass.getEnclosingElement();\n\t\t\twhile (!(enclosingElement == null || enclosingElement.getKind().equals(ElementKind.PACKAGE))) {\n\t\t\t\tsubpackages.add(0, enclosingElement.getSimpleName().toString().toLowerCase(Locale.ROOT));\n\t\t\t\tenclosingElement = enclosingElement.getEnclosingElement();\n\t\t\t}\n\n\t\t\tif (enclosingElement == null) {\n\t\t\t\tint lastDot = qualifiedName.lastIndexOf('.');\n\t\t\t\tif (lastDot > 0) {\n\t\t\t\t\tpackageName = qualifiedName.substring(0, lastDot);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (enclosingElement.getKind().equals(ElementKind.PACKAGE)) {\n\t\t\t\tString q = ((PackageElement) enclosingElement).getQualifiedName().toString();\n\t\t\t\tpackageName = q + ((q.isEmpty() || subpackages.isEmpty()) ? \"\" : \".\") + String.join(\".\", subpackages);\n\t\t\t}\n\n\t\t\tNodeModelBuilder builder = NodeModelBuilder.create(this.configuration, packageName, suggestedTypeName)\n\t\t\t\t.addLabels(getLabel(annotatedClass));\n\n\t\t\tresult.put(annotatedClass, builder);\n\t\t});\n\t\treturn Collections.unmodifiableMap(result);\n\t}\n\n\t/**\n\t * Finds labels on the annotated element. If there's no label specified on the node\n\t * annotation, the simple class name is used. Otherwise, all labels in declaration\n\t * order (primary, value, labels) are used.\n\t * @param annotatedClass the annotated class\n\t * @return a collection of labels\n\t */\n\tprotected abstract Collection<String> getLabel(TypeElement annotatedClass);\n\n\tprotected final void writeSourceFiles(Collection<ModelBuilder<?>> builders) throws IOException {\n\n\t\tfor (ModelBuilder<?> nodeModelBuilder : builders) {\n\t\t\tJavaFileObject jfo = this.filer.createSourceFile(nodeModelBuilder.getCanonicalClassName());\n\t\t\ttry (Writer writer = jfo.openWriter()) {\n\t\t\t\tnodeModelBuilder.writeTo(writer);\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected abstract PropertiesAndRelationshipGrouping newPropertiesAndRelationshipGrouping();\n\n\t/**\n\t * Turns an element into a property description.\n\t * @param e the element to transform\n\t * @return a new property description\n\t */\n\tprotected abstract PropertyDefinition asPropertyDefinition(Element e);\n\n\t/**\n\t * This populates the properties of all node builders and returns all identifiable\n\t * relationships. Why is this done as a side effect? The tests for relationships are\n\t * rather expensive and may need to instantiate classes. When this is unavoidable, it\n\t * makes sense to use that information right away and not do it a second time later\n\t * one-\n\t * @param nodeBuilders the map of all node builders for all annotated classes\n\t * @return a map from a node builder to a list of fields describing relationships\n\t */\n\tprotected final Map<NodeModelBuilder, List<Element>> populateNodePropertiesAndCollectRelationshipFields(\n\t\t\tMap<TypeElement, NodeModelBuilder> nodeBuilders) {\n\n\t\tMap<NodeModelBuilder, List<Element>> relationshipFields = new HashMap<>();\n\t\tnodeBuilders.forEach((type, nodeImplBuilder) -> {\n\n\t\t\tvar groupPropertiesAndRelationships = newPropertiesAndRelationshipGrouping();\n\t\t\ttype.getEnclosedElements().forEach(groupPropertiesAndRelationships::apply);\n\t\t\tMap<FieldType, List<Element>> fields = groupPropertiesAndRelationships.getResult();\n\n\t\t\tnodeImplBuilder.addProperties(fields.get(FieldType.P).stream().map(this::asPropertyDefinition).toList());\n\n\t\t\trelationshipFields.put(nodeImplBuilder, fields.get(FieldType.R));\n\t\t});\n\t\treturn Collections.unmodifiableMap(relationshipFields);\n\t}\n\n\tprotected abstract RelationshipPropertyDefinition asRelationshipDefinition(NodeModelBuilder owner, Element e,\n\t\t\tMap<TypeElement, Map.Entry<TypeElement, List<PropertyDefinition>>> relationshipProperties,\n\t\t\tMap<TypeElement, NodeModelBuilder> nodeBuilders);\n\n\t/**\n\t * This takes the list of all know fields pointing to relationships and computes a map\n\t * with relationship types and their definitions. A specific relationship type may\n\t * have been used between several other nodes.\n\t * @param allRelationshipFields all known relationship files\n\t * @param relationshipProperties a map of properties discovered for relationships\n\t * @param nodeBuilders the current list of node builders to work with\n\t * @return a map from a relationship type to a list of definitions. The definition\n\t * including the node builders themselves. The entry in the list is (start,\n\t * definition)\n\t */\n\tprotected final Map<String, List<Map.Entry<NodeModelBuilder, RelationshipPropertyDefinition>>> computeRelationshipDefinitions(\n\t\t\tMap<NodeModelBuilder, List<Element>> allRelationshipFields,\n\t\t\tMap<TypeElement, Map.Entry<TypeElement, List<PropertyDefinition>>> relationshipProperties,\n\t\t\tMap<TypeElement, NodeModelBuilder> nodeBuilders) {\n\n\t\trecord F(String type, NodeModelBuilder definingType, RelationshipPropertyDefinition definition,\n\t\t\t\tboolean outgoing) {\n\t\t}\n\n\t\tMap<String, List<Map.Entry<NodeModelBuilder, RelationshipPropertyDefinition>>> definitions = new HashMap<>();\n\t\tMap<String, List<F>> hlp = allRelationshipFields.entrySet().stream().flatMap((e) -> {\n\t\t\tvar start = e.getKey();\n\t\t\tvar l = e.getValue();\n\t\t\treturn l.stream().map(f -> {\n\t\t\t\tRelationshipPropertyDefinition propertyDefinition = asRelationshipDefinition(start, f,\n\t\t\t\t\t\trelationshipProperties, nodeBuilders);\n\n\t\t\t\tif (propertyDefinition == null) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\treturn new F(propertyDefinition.getType(), start, propertyDefinition,\n\t\t\t\t\t\tpropertyDefinition.getStart() == start);\n\t\t\t});\n\t\t}).filter(Objects::nonNull).collect(Collectors.groupingBy(F::type));\n\n\t\t// This finds bidirectional definitions per type.\n\t\t// it will filter out incoming (that is, include only the outgoing definition in\n\t\t// the metamodel)\n\t\t//\n\t\thlp.forEach((type, definitionsPerType) -> {\n\t\t\tdefinitionsPerType.forEach(x -> {\n\t\t\t\tif (definitionsPerType.size() == 1 || x.outgoing()\n\t\t\t\t\t\t|| definitionsPerType.stream()\n\t\t\t\t\t\t\t.noneMatch(x2 -> x2.outgoing && x2.definition().getStart() == x.definition().getStart()\n\t\t\t\t\t\t\t\t\t&& x2.definition().getEnd() == x.definition().getEnd())) {\n\t\t\t\t\tdefinitions.computeIfAbsent(x.definition().getType(), k -> new ArrayList<>())\n\t\t\t\t\t\t.add(new AbstractMap.SimpleEntry<>(x.definingType(), x.definition()));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.messager.printMessage(Diagnostic.Kind.WARNING,\n\t\t\t\t\t\t\t\"Bidirectional mappings are not supported for the static meta model (Relationship: %s)\"\n\t\t\t\t\t\t\t\t.formatted(type));\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\treturn Collections.unmodifiableMap(definitions);\n\t}\n\n\t/**\n\t * Creates and populates the list of relationships from their definitions. It also\n\t * registered the freshly generated relationship builders with the previously created\n\t * node builders.\n\t * @param relationshipDefinitions definitions by type and owner\n\t * @return map of builder per type. Can be multiple builders in case of different\n\t * relationship property classes with different properties.\n\t */\n\tprotected final Map<String, List<RelationshipModelBuilder>> populateListOfRelationships(\n\t\t\tMap<String, List<Map.Entry<NodeModelBuilder, RelationshipPropertyDefinition>>> relationshipDefinitions) {\n\t\tMap<String, List<RelationshipModelBuilder>> result = new HashMap<>();\n\n\t\tfor (var entry : relationshipDefinitions.entrySet()) {\n\t\t\tString type = entry.getKey();\n\t\t\tList<Map.Entry<NodeModelBuilder, RelationshipPropertyDefinition>> allDefinitions = entry.getValue();\n\t\t\tallDefinitions.stream()\n\t\t\t\t.collect(Collectors.groupingBy(pd -> pd.getValue().getStart().getPackageName()))\n\t\t\t\t.forEach((packageName, definitions) -> {\n\t\t\t\t\tRelationshipModelBuilder relationshipBuilder = null;\n\n\t\t\t\t\t// Simple case: All unique types\n\t\t\t\t\tif (definitions.size() == 1) {\n\t\t\t\t\t\tNodeModelBuilder owner = definitions.get(0).getKey();\n\t\t\t\t\t\tRelationshipPropertyDefinition definition = definitions.get(0).getValue();\n\n\t\t\t\t\t\trelationshipBuilder = RelationshipModelBuilder.create(this.configuration,\n\t\t\t\t\t\t\t\towner.getPackageName(), type);\n\t\t\t\t\t\trelationshipBuilder.setStartNode(definition.getStart());\n\t\t\t\t\t\trelationshipBuilder.setEndNode(definition.getEnd());\n\t\t\t\t\t\trelationshipBuilder.addProperties(definition.getProperties());\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tSet<NodeModelBuilder> owners = definitions.stream()\n\t\t\t\t\t\t\t.map(Map.Entry::getKey)\n\t\t\t\t\t\t\t.collect(Collectors.toSet());\n\t\t\t\t\t\t// Exactly one owner, but variable targets\n\t\t\t\t\t\tif (owners.size() == 1) {\n\t\t\t\t\t\t\tNodeModelBuilder owner = owners.stream().findFirst().get();\n\n\t\t\t\t\t\t\tMap<Boolean, List<RelationshipPropertyDefinition>> ownerAtStartOrEnd = definitions.stream()\n\t\t\t\t\t\t\t\t.map(Map.Entry::getValue)\n\t\t\t\t\t\t\t\t.collect(Collectors.partitioningBy(p -> p.getStart() == owner));\n\n\t\t\t\t\t\t\tif (sameOrNoProperties(definitions)) {\n\t\t\t\t\t\t\t\trelationshipBuilder = RelationshipModelBuilder.create(this.configuration,\n\t\t\t\t\t\t\t\t\t\towner.getPackageName(), type);\n\t\t\t\t\t\t\t\trelationshipBuilder.addProperties(definitions.get(0).getValue().getProperties());\n\t\t\t\t\t\t\t\tif (ownerAtStartOrEnd.get(true).isEmpty()) {\n\t\t\t\t\t\t\t\t\trelationshipBuilder.setEndNode(owner);\n\t\t\t\t\t\t\t\t\trelationshipBuilder.setStartNode(\n\t\t\t\t\t\t\t\t\t\t\tuniqueNodeBuilder(definitions, RelationshipPropertyDefinition::getStart));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if (ownerAtStartOrEnd.get(false).isEmpty()) {\n\t\t\t\t\t\t\t\t\trelationshipBuilder.setStartNode(owner);\n\t\t\t\t\t\t\t\t\trelationshipBuilder.setEndNode(\n\t\t\t\t\t\t\t\t\t\t\tuniqueNodeBuilder(definitions, RelationshipPropertyDefinition::getEnd));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tList<RelationshipModelBuilder> newBuilders = new ArrayList<>();\n\t\t\t\t\t\t\t\tfor (Map.Entry<NodeModelBuilder, RelationshipPropertyDefinition> definition : definitions) {\n\n\t\t\t\t\t\t\t\t\tRelationshipPropertyDefinition propertyDefinition = definition.getValue();\n\t\t\t\t\t\t\t\t\tRelationshipModelBuilder newBuilder = RelationshipModelBuilder.create(\n\t\t\t\t\t\t\t\t\t\t\tthis.configuration, owner.getPackageName(), type,\n\t\t\t\t\t\t\t\t\t\t\ttype + \"_\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t+ propertyDefinition.getEnd()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t.getPlainClassName()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t.toUpperCase(Locale.ROOT));\n\t\t\t\t\t\t\t\t\tnewBuilder.addProperties(propertyDefinition.getProperties());\n\t\t\t\t\t\t\t\t\tif (ownerAtStartOrEnd.get(true).isEmpty()) {\n\t\t\t\t\t\t\t\t\t\tnewBuilder.setStartNode(propertyDefinition.getStart());\n\t\t\t\t\t\t\t\t\t\tnewBuilder.setEndNode(owner);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse if (ownerAtStartOrEnd.get(false).isEmpty()) {\n\t\t\t\t\t\t\t\t\t\tnewBuilder.setStartNode(owner);\n\t\t\t\t\t\t\t\t\t\tnewBuilder.setEndNode(propertyDefinition.getEnd());\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tdefinition.getKey()\n\t\t\t\t\t\t\t\t\t\t.addRelationshipDefinition(propertyDefinition.withBuilder(newBuilder));\n\t\t\t\t\t\t\t\t\tnewBuilders.add(newBuilder);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tresult.put(type, Collections.unmodifiableList(newBuilders));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (owners.size() > 1) {\n\t\t\t\t\t\t\tvar intermediateBuilders = new HashMap<String, LocalRelBuilderState>();\n\t\t\t\t\t\t\tfor (var owner : owners) {\n\t\t\t\t\t\t\t\tfor (Map.Entry<NodeModelBuilder, RelationshipPropertyDefinition> definition : definitions) {\n\t\t\t\t\t\t\t\t\tvar start = definition.getValue().getStart();\n\t\t\t\t\t\t\t\t\tvar end = definition.getValue().getEnd();\n\t\t\t\t\t\t\t\t\tif (intermediateBuilders.containsKey(type)) {\n\t\t\t\t\t\t\t\t\t\tvar intermediateBuilder = intermediateBuilders.get(type);\n\t\t\t\t\t\t\t\t\t\tif (intermediateBuilder.start != start) {\n\t\t\t\t\t\t\t\t\t\t\tintermediateBuilder.start = null;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (intermediateBuilder.end != end) {\n\t\t\t\t\t\t\t\t\t\t\tintermediateBuilder.end = null;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tvar localRelationshipBuilder = RelationshipModelBuilder\n\t\t\t\t\t\t\t\t\t\t\t.create(this.configuration, owner.getPackageName(), type);\n\t\t\t\t\t\t\t\t\t\tintermediateBuilders.put(type,\n\t\t\t\t\t\t\t\t\t\t\t\tnew LocalRelBuilderState(localRelationshipBuilder, start, end));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Go over all half finished builders and close them\n\t\t\t\t\t\t\tintermediateBuilders.forEach((t, intermediateBuilder) -> {\n\t\t\t\t\t\t\t\tvar finalBuilder = intermediateBuilder.value;\n\t\t\t\t\t\t\t\tfinalBuilder.setStartNode(intermediateBuilder.start);\n\t\t\t\t\t\t\t\tfinalBuilder.setEndNode(intermediateBuilder.end);\n\t\t\t\t\t\t\t\t// now that we have seen all definitions per type, we can\n\t\t\t\t\t\t\t\t// assign them proper\n\t\t\t\t\t\t\t\tfor (Map.Entry<NodeModelBuilder, RelationshipPropertyDefinition> definition : definitions) {\n\t\t\t\t\t\t\t\t\tif (definition.getValue().getType().equals(t)) {\n\t\t\t\t\t\t\t\t\t\tvar finishedDefinition = definition.getValue().withBuilder(finalBuilder);\n\t\t\t\t\t\t\t\t\t\tdefinition.getKey().addRelationshipDefinition(finishedDefinition);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tvar builders = result.computeIfAbsent(type, ignored -> new ArrayList<>());\n\t\t\t\t\t\t\t\tbuilders.add(finalBuilder);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// A single builder created for all definitions\n\t\t\t\t\t// Multiple builders have been taken care of independent.\n\t\t\t\t\tif (relationshipBuilder != null) {\n\t\t\t\t\t\tfor (Map.Entry<NodeModelBuilder, RelationshipPropertyDefinition> definition : definitions) {\n\t\t\t\t\t\t\tRelationshipPropertyDefinition finishedDefinition = definition.getValue()\n\t\t\t\t\t\t\t\t.withBuilder(relationshipBuilder);\n\t\t\t\t\t\t\tdefinition.getKey().addRelationshipDefinition(finishedDefinition);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar builders = result.computeIfAbsent(type, ignored -> new ArrayList<>());\n\t\t\t\t\t\tbuilders.add(relationshipBuilder);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}\n\t\treturn Collections.unmodifiableMap(result);\n\t}\n\n\tprivate static NodeModelBuilder uniqueNodeBuilder(\n\t\t\tList<Map.Entry<NodeModelBuilder, RelationshipPropertyDefinition>> definitions,\n\t\t\tFunction<RelationshipPropertyDefinition, NodeModelBuilder> mapper) {\n\t\tvar hlp = definitions.stream().map(Map.Entry::getValue).map(mapper).distinct().toList();\n\t\tif (hlp.size() == 1) {\n\t\t\treturn hlp.get(0);\n\t\t}\n\t\treturn null;\n\t}\n\n\tprotected final boolean describesEnum(TypeMirror typeMirror) {\n\t\tList<? extends TypeMirror> superTypes = this.typeUtils.directSupertypes(typeMirror);\n\t\tif (!(superTypes.size() == 1 && superTypes.get(0).getKind().equals(TypeKind.DECLARED))) {\n\t\t\treturn false;\n\t\t}\n\n\t\tTypeMirror tm = superTypes.get(0);\n\t\tString name = ((DeclaredType) tm).asElement()\n\t\t\t.accept(new TypeElementVisitor<>(newTypeElementNameFunction()), null);\n\t\treturn Enum.class.getName().equals(name);\n\t}\n\n\tprotected final Function<TypeElement, String> newTypeElementNameFunction() {\n\t\treturn new TypeElementNameFunction();\n\t}\n\n\tprotected enum FieldType {\n\n\t\tP, R\n\n\t}\n\n\tprotected interface PropertiesAndRelationshipGrouping {\n\n\t\tvoid apply(Element element);\n\n\t\tMap<FieldType, List<Element>> getResult();\n\n\t}\n\n\t/**\n\t * Recursively extracts a loadable and instantiable name from a canonical class name\n\t * by checking whether the current element is a nesting type. If so, the enclosing\n\t * element will be visited and the elements simple name will be appended with a\n\t * {@literal $}.\n\t */\n\tprivate static final class TypeElementNameFunction implements Function<TypeElement, String> {\n\n\t\t@Override\n\t\tpublic String apply(TypeElement typeElement) {\n\t\t\tNestingKind nestingKind = typeElement.getNestingKind();\n\t\t\tif (nestingKind.isNested()) {\n\t\t\t\treturn typeElement.getEnclosingElement().accept(new TypeElementVisitor<>(this), null) + \"$\"\n\t\t\t\t\t\t+ typeElement.getSimpleName();\n\t\t\t}\n\t\t\treturn typeElement.getQualifiedName().toString();\n\t\t}\n\n\t}\n\n\t/**\n\t * Utility class that can be used to extract a {@link TypeElement} from a type or\n\t * anything else that one can retrieve from the actual element.\n\t *\n\t * @param <E> the type of the returned value\n\t */\n\tprotected static class TypeElementVisitor<E> extends SimpleElementVisitor8<E, Void> {\n\n\t\tprivate final Function<TypeElement, E> delegate;\n\n\t\tpublic TypeElementVisitor(Function<TypeElement, E> delegate) {\n\t\t\tthis.delegate = delegate;\n\t\t}\n\n\t\t@Override\n\t\tpublic E visitType(TypeElement e, Void unused) {\n\t\t\treturn this.delegate.apply(e);\n\t\t}\n\n\t}\n\n\tprivate static class LocalRelBuilderState {\n\n\t\tRelationshipModelBuilder value;\n\n\t\tNodeModelBuilder start;\n\n\t\tNodeModelBuilder end;\n\n\t\tLocalRelBuilderState(RelationshipModelBuilder value, NodeModelBuilder start, NodeModelBuilder end) {\n\t\t\tthis.value = value;\n\t\t\tthis.end = end;\n\t\t\tthis.start = start;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/AbstractModelBuilder.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport java.io.IOException;\nimport java.io.UncheckedIOException;\nimport java.nio.file.Path;\nimport java.time.Clock;\nimport java.time.ZonedDateTime;\nimport java.time.format.DateTimeFormatter;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.function.Supplier;\nimport java.util.stream.Stream;\n\nimport javax.lang.model.element.Modifier;\n\nimport com.squareup.javapoet.AnnotationSpec;\nimport com.squareup.javapoet.ClassName;\nimport com.squareup.javapoet.CodeBlock;\nimport com.squareup.javapoet.FieldSpec;\nimport com.squareup.javapoet.JavaFile;\nimport com.squareup.javapoet.TypeSpec;\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.codegen.core.Configuration.JavaVersion;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Base class with some shared state and information for builders of {@link NodeBase} and\n * {@link RelationshipBase}.\n *\n * @param <T> concrete type of this builder\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\nabstract class AbstractModelBuilder<T extends ModelBuilder<?>> implements ModelBuilder<T> {\n\n\tprotected static final ClassName TYPE_NAME_NODE = ClassName.get(Node.class);\n\n\tprotected static final ClassName TYPE_NAME_NODE_BASE = ClassName.get(NodeBase.class);\n\n\tprotected static final ClassName TYPE_NAME_SYMBOLIC_NAME = ClassName.get(SymbolicName.class);\n\n\tprotected static final ClassName TYPE_NAME_LIST = ClassName.get(List.class);\n\n\tprotected static final ClassName TYPE_NAME_MAP_EXPRESSION = ClassName.get(MapExpression.class);\n\n\t/**\n\t * Generator for field names.\n\t */\n\tprotected final FieldNameGenerator fieldNameGenerator;\n\n\t/**\n\t * The fully qualified name of the generated class.\n\t */\n\tprotected final ClassName className;\n\n\t/**\n\t * Simple, undecorated class name.\n\t */\n\tprotected final String plainClassName;\n\n\t/**\n\t * A set of fields to generate.\n\t */\n\tprotected final Set<PropertyDefinition> properties = new LinkedHashSet<>();\n\n\tprivate final JavaVersion target;\n\n\tprivate final String indent;\n\n\t/**\n\t * Will be initialized with Double-checked locking into an unmodifiable\n\t * {@link JavaFile}, no need to worry.\n\t */\n\t@SuppressWarnings(\"squid:S3077\")\n\tprivate volatile JavaFile javaFile;\n\n\tprivate Clock clock = Clock.systemDefaultZone();\n\n\tprivate boolean addAtGenerated = true;\n\n\tAbstractModelBuilder(FieldNameGenerator fieldNameGenerator, ClassName className, String plainClassName,\n\t\t\tJavaVersion target, String indent) {\n\n\t\tthis.fieldNameGenerator = fieldNameGenerator;\n\t\tthis.className = className;\n\t\tthis.plainClassName = plainClassName;\n\t\tthis.target = target;\n\t\tthis.indent = indent;\n\t}\n\n\t/**\n\t * Internal utility method to extract the actual class name while trying to avoid best\n\t * guesses.\n\t * @param optionalSource the source from which to extract the class name to be\n\t * generated\n\t * @return a class name\n\t */\n\tstatic ClassName extractClassName(ModelBuilder<?> optionalSource) {\n\n\t\tif (optionalSource == null) {\n\t\t\treturn null;\n\t\t}\n\t\telse if (optionalSource instanceof NodeImplBuilder builder) {\n\t\t\treturn builder.getClassName();\n\t\t}\n\t\telse if (optionalSource instanceof RelationshipImplBuilder builder) {\n\t\t\treturn builder.getClassName();\n\t\t}\n\t\telse {\n\t\t\treturn ClassName.bestGuess(optionalSource.getCanonicalClassName());\n\t\t}\n\t}\n\n\t/**\n\t * Central method to trigger building of the {@link #javaFile} if that has not been\n\t * done yet. {@link #buildJavaFile()} is supposed to fail when it realizes the build\n\t * has already been done.\n\t * @return a JavaPoet {@link JavaFile} that can be written to file or string.\n\t */\n\tprotected abstract JavaFile buildJavaFile();\n\n\t@Override\n\tpublic final T addProperty(String newProperty) {\n\n\t\treturn addProperty(PropertyDefinition.create(newProperty, newProperty));\n\t}\n\n\t@Override\n\tpublic final T addProperty(PropertyDefinition newProperty) {\n\n\t\treturn addProperties(Collections.singleton(newProperty));\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic final T addProperties(Collection<PropertyDefinition> newProperties) {\n\n\t\treturn (T) callOnlyWithoutJavaFilePresent(() -> {\n\t\t\tthis.properties.addAll(newProperties);\n\t\t\treturn this;\n\t\t});\n\t}\n\n\t@Override\n\tpublic final String getPackageName() {\n\t\treturn this.className.packageName();\n\t}\n\n\t@Override\n\tpublic final String getCanonicalClassName() {\n\t\treturn this.className.canonicalName();\n\t}\n\n\t@Override\n\tpublic final String getPlainClassName() {\n\t\treturn this.plainClassName;\n\t}\n\n\t@Override\n\tpublic final void writeTo(Path path) {\n\n\t\ttry {\n\t\t\tgetJavaFile().writeTo(path);\n\t\t}\n\t\tcatch (IOException ex) {\n\t\t\tthrow new UncheckedIOException(ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic final void writeTo(Appendable appendable) {\n\t\ttry {\n\t\t\tgetJavaFile().writeTo(appendable);\n\t\t}\n\t\tcatch (IOException ex) {\n\t\t\tthrow new UncheckedIOException(ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic final String writeToString() {\n\n\t\ttry {\n\t\t\tStringBuilder out = new StringBuilder();\n\t\t\tgetJavaFile().writeTo(out);\n\t\t\treturn out.toString();\n\t\t}\n\t\tcatch (IOException ex) {\n\t\t\tthrow new UncheckedIOException(ex);\n\t\t}\n\t}\n\n\t@Override\n\tpublic final String getFieldName() {\n\t\treturn this.fieldNameGenerator.generate(getPlainClassName());\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tfinal T apply(Configuration configuration) {\n\t\tconfiguration.getClock().ifPresent(c -> this.clock = c);\n\t\tthis.addAtGenerated = configuration.isAddAtGenerated();\n\t\treturn (T) this;\n\t}\n\n\t/**\n\t * Makes sure that no Java file has been created before modifying the builder.\n\t * @param <V> the type of the value of the objects supplied\n\t * @param c a supplier of arbitrary code\n\t * @return the value created for a property unless a source file was already present\n\t */\n\tfinal <V> V callOnlyWithoutJavaFilePresent(Supplier<V> c) {\n\n\t\tsynchronized (this) {\n\t\t\tif (this.javaFile == null) {\n\t\t\t\treturn c.get();\n\t\t\t}\n\t\t}\n\t\tthrow new IllegalStateException(\"Class has already been generated, cannot add properties.\");\n\t}\n\n\t/**\n\t * Adds information about the generated class.\n\t * @param builder the builder that should be decorated\n\t * @return a type builder.\n\t */\n\tfinal TypeSpec.Builder addGenerated(TypeSpec.Builder builder) {\n\n\t\tClassName nameOfAtGenerated;\n\t\tif (this.target == JavaVersion.RELEASE_8) {\n\t\t\tnameOfAtGenerated = ClassName.get(\"javax.annotation\", \"Generated\");\n\t\t}\n\t\telse if (this.target == JavaVersion.RELEASE_11 && this.addAtGenerated) {\n\t\t\tnameOfAtGenerated = ClassName.get(\"javax.annotation.processing\", \"Generated\");\n\t\t}\n\t\telse {\n\t\t\tnameOfAtGenerated = null;\n\t\t}\n\n\t\tString comment = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\";\n\t\tif (nameOfAtGenerated == null) {\n\t\t\tbuilder.addJavadoc(CodeBlock.of(comment));\n\t\t}\n\t\telse {\n\t\t\tAnnotationSpec spec = AnnotationSpec.builder(nameOfAtGenerated)\n\t\t\t\t.addMember(\"value\", \"$S\", getClass().getName())\n\t\t\t\t.addMember(\"date\", \"$S\", ZonedDateTime.now(this.clock).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME))\n\t\t\t\t.addMember(\"comments\", \"$S\", comment)\n\t\t\t\t.build();\n\t\t\tbuilder.addAnnotation(spec);\n\t\t}\n\t\treturn builder;\n\t}\n\n\t/**\n\t * Turns the property definitions into field spec.\n\t * @return a stream of field specs\n\t */\n\tfinal Stream<FieldSpec> generateFieldSpecsFromProperties() {\n\t\treturn this.properties.stream().map(p -> {\n\n\t\t\tString fieldName;\n\t\t\tCodeBlock initializer;\n\t\t\tif (p.getNameInDomain() == null) {\n\t\t\t\tfieldName = p.getNameInGraph();\n\t\t\t\tinitializer = CodeBlock.of(\"this.property($S)\", p.getNameInGraph());\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfieldName = p.getNameInDomain();\n\t\t\t\tinitializer = CodeBlock.of(\"this.property($S).referencedAs($S)\", p.getNameInGraph(),\n\t\t\t\t\t\tp.getNameInDomain());\n\t\t\t}\n\n\t\t\treturn FieldSpec\n\t\t\t\t.builder(Property.class, this.fieldNameGenerator.generate(fieldName), Modifier.PUBLIC, Modifier.FINAL)\n\t\t\t\t.initializer(initializer)\n\t\t\t\t.build();\n\t\t});\n\t}\n\n\t/**\n\t * Prepares a file builder for the given type.\n\t * @param typeSpec the type that should be written\n\t * @return a builder with some shared settings like indent etc. applied.\n\t */\n\tfinal JavaFile.Builder prepareFileBuilder(TypeSpec typeSpec) {\n\t\treturn JavaFile.builder(getPackageName(), typeSpec).skipJavaLangImports(true).indent(this.indent);\n\t}\n\n\t/**\n\t * {@return the internal class name used by JavaPoet}\n\t */\n\tfinal ClassName getClassName() {\n\t\treturn this.className;\n\t}\n\n\tprivate JavaFile getJavaFile() {\n\n\t\tJavaFile result = this.javaFile;\n\t\tif (result == null) {\n\t\t\tsynchronized (this) {\n\t\t\t\tresult = this.javaFile;\n\t\t\t\tif (result == null) {\n\t\t\t\t\tthis.javaFile = buildJavaFile();\n\t\t\t\t\tresult = this.javaFile;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/ClassNameGenerator.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Strategy interface for generating class names for {@link NodeBase} or\n * {@link RelationshipBase}.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\n@FunctionalInterface\npublic interface ClassNameGenerator {\n\n\t/**\n\t * Generates a valid Java class based on a suggestion. Most of the time the suggestion\n\t * will either be a simple string, maybe an existing class name or the concatenated\n\t * labels of a node as returned by {@code db.schema.nodeTypeProperties}.\n\t * <p>\n\t * Any implementation must remove invalid identifier parts.\n\t * @param suggestedName basically an arbitrary string suggesting a type name.\n\t * @return a pair of names: A valid identifier for a type and matching field name.\n\t */\n\tString generate(String suggestedName);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/Configuration.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport java.nio.file.Path;\nimport java.time.Clock;\nimport java.time.ZonedDateTime;\nimport java.time.format.DateTimeFormatter;\nimport java.util.Arrays;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.function.Predicate;\nimport java.util.function.UnaryOperator;\nimport java.util.stream.Collectors;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.EXPERIMENTAL;\n\n/**\n * Main configuration objects for all aspects of code generation.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = EXPERIMENTAL, since = \"2021.1.0\")\npublic final class Configuration {\n\n\t/**\n\t * Lookup key to be used in an annotations processors environment options for prefixes\n\t * to be used.\n\t */\n\tpublic static final String PROPERTY_PREFIX = \"org.neo4j.cypherdsl.codegen.prefix\";\n\n\t/**\n\t * Lookup key to be used in an annotations processors environment options for suffixes\n\t * to be used.\n\t */\n\tpublic static final String PROPERTY_SUFFIX = \"org.neo4j.cypherdsl.codegen.suffix\";\n\n\t/**\n\t * Lookup key to be used in an annotations processors environment options for the\n\t * indent style to be used.\n\t */\n\tpublic static final String PROPERTY_INDENT_STYLE = \"org.neo4j.cypherdsl.codegen.indent_style\";\n\n\t/**\n\t * Lookup key to be used in an annotations processors environment options for the\n\t * indent size to be used.\n\t */\n\tpublic static final String PROPERTY_INDENT_SIZE = \"org.neo4j.cypherdsl.codegen.indent_size\";\n\n\t/**\n\t * Lookup key to be used in an annotations processors environment options for the\n\t * timestamp to be used.\n\t */\n\tpublic static final String PROPERTY_TIMESTAMP = \"org.neo4j.cypherdsl.codegen.timestamp\";\n\n\t/**\n\t * Lookup key to be used in an annotations processors environment options for the flag\n\t * whether generated code should be marked.\n\t */\n\tpublic static final String PROPERTY_ADD_AT_GENERATED = \"org.neo4j.cypherdsl.codegen.add_at_generated\";\n\n\t/**\n\t * Lookup key to be used in an annotations processors environment options for a comma\n\t * separated list of types that should be excluded from being processed.\n\t */\n\tpublic static final String PROPERTY_EXCLUDES = \"org.neo4j.cypherdsl.codegen.excludes\";\n\n\tprivate static final Configuration DEFAULT_CONFIG = newConfig().build();\n\n\t/**\n\t * Defines decoration for generated type names, applies to both nodes and\n\t * relationships.\n\t */\n\tprivate final UnaryOperator<String> typeNameDecorator;\n\n\t/**\n\t * Defines how classes representing nodes should be named.\n\t */\n\tprivate final ClassNameGenerator nodeNameGenerator;\n\n\t/**\n\t * Defines how classes representing relationships should be named.\n\t */\n\tprivate final ClassNameGenerator relationshipNameGenerator;\n\n\tprivate final FieldNameGenerator fieldNameGenerator;\n\n\t/**\n\t * On which Java version should the generated classes be compilable? Defaults to Java\n\t * Release 8.\n\t */\n\tprivate final JavaVersion target;\n\n\t/**\n\t * The fully qualified name of the Java package into which the classes should be\n\t * generated.\n\t */\n\tprivate final String defaultPackage;\n\n\t/**\n\t * The path into which the Java classes should be generated. A package structure\n\t * matching {@link #defaultPackage} will be created.\n\t */\n\tprivate final Optional<Path> path;\n\n\t/**\n\t * The indention string used in the generated source files.\n\t */\n\tprivate final String indent;\n\n\t/**\n\t * Optional clock to use while generation things.\n\t */\n\tprivate final Optional<Clock> clock;\n\n\t/**\n\t * Flag if the {@code @Generated}-annotation should be added. On JDK9+ on the module\n\t * path it would require jdk.compiler. If you don't want it, disable it with this\n\t * flag.\n\t */\n\tprivate final boolean addAtGenerated;\n\n\t/**\n\t * Set of qualified names to exclude from processing.\n\t */\n\tprivate final Set<String> excludes;\n\n\tprivate Configuration(UnaryOperator<String> typeNameDecorator, ClassNameGenerator nodeNameGenerator,\n\t\t\tClassNameGenerator relationshipNameGenerator, FieldNameGenerator fieldNameGenerator, JavaVersion target,\n\t\t\tString defaultPackage, Path path, String indent, Clock clock, boolean addAtGenerated,\n\t\t\tSet<String> excludes) {\n\t\tthis.typeNameDecorator = typeNameDecorator;\n\t\tthis.nodeNameGenerator = nodeNameGenerator;\n\t\tthis.relationshipNameGenerator = relationshipNameGenerator;\n\t\tthis.fieldNameGenerator = fieldNameGenerator;\n\t\tthis.target = target;\n\t\tthis.defaultPackage = defaultPackage;\n\t\tthis.path = Optional.ofNullable(path);\n\t\tthis.indent = indent;\n\t\tthis.clock = Optional.ofNullable(clock);\n\t\tthis.addAtGenerated = addAtGenerated;\n\t\tthis.excludes = excludes;\n\t}\n\n\t/**\n\t * {@return an instance of the default configuration}\n\t */\n\tpublic static Configuration defaultConfig() {\n\t\treturn DEFAULT_CONFIG;\n\t}\n\n\t/**\n\t * Starts building new configuration.\n\t * @return a new builder\n\t */\n\tpublic static Builder newConfig() {\n\t\treturn Builder.newConfig();\n\t}\n\n\t/**\n\t * Starts building a new configuration for the given path.\n\t * @param path the path into which code should be generated\n\t * @return a new builder\n\t */\n\tpublic static Builder newConfig(final Path path) {\n\t\treturn Builder.newConfig(path);\n\t}\n\n\t/**\n\t * {@return the generator for node names}\n\t */\n\tpublic ClassNameGenerator getNodeNameGenerator() {\n\t\treturn this.nodeNameGenerator;\n\t}\n\n\t/**\n\t * {@return the generator for class names}\n\t */\n\tpublic ClassNameGenerator getRelationshipNameGenerator() {\n\t\treturn this.relationshipNameGenerator;\n\t}\n\n\t/**\n\t * {@return the generator for constant field names}\n\t */\n\tpublic FieldNameGenerator getConstantFieldNameGenerator() {\n\t\treturn this.fieldNameGenerator;\n\t}\n\n\t/**\n\t * {@return the target java version of the generated code}\n\t */\n\tpublic JavaVersion getTarget() {\n\t\treturn this.target;\n\t}\n\n\t/**\n\t * {@return the default package name to use}\n\t */\n\tpublic String getDefaultPackage() {\n\t\treturn this.defaultPackage;\n\t}\n\n\t/**\n\t * {@return the path to generate code into}\n\t */\n\tpublic Optional<Path> getPath() {\n\t\treturn this.path;\n\t}\n\n\t/**\n\t * {@return the decorator that applies pre- and suffixes to typenames}\n\t */\n\tpublic UnaryOperator<String> getTypeNameDecorator() {\n\t\treturn this.typeNameDecorator;\n\t}\n\n\t/**\n\t * {@return the string to be used as indent}\n\t */\n\tpublic String getIndent() {\n\t\treturn this.indent;\n\t}\n\n\t/**\n\t * {@return an optional clock, different from the system.}\n\t */\n\tpublic Optional<Clock> getClock() {\n\t\treturn this.clock;\n\t}\n\n\t/**\n\t * {@return literal <code>true</code> if generated code is marked as such}\n\t */\n\tpublic boolean isAddAtGenerated() {\n\t\treturn this.addAtGenerated;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (this == o) {\n\t\t\treturn true;\n\t\t}\n\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\treturn false;\n\t\t}\n\t\tConfiguration that = (Configuration) o;\n\t\treturn this.typeNameDecorator.equals(that.typeNameDecorator)\n\t\t\t\t&& this.nodeNameGenerator.equals(that.nodeNameGenerator)\n\t\t\t\t&& this.relationshipNameGenerator.equals(that.relationshipNameGenerator)\n\t\t\t\t&& this.fieldNameGenerator.equals(that.fieldNameGenerator) && this.target == that.target\n\t\t\t\t&& this.defaultPackage.equals(that.defaultPackage) && this.path.equals(that.path)\n\t\t\t\t&& this.indent.equals(that.indent) && this.clock.equals(that.clock)\n\t\t\t\t&& this.addAtGenerated == that.addAtGenerated;\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn Objects.hash(this.typeNameDecorator, this.nodeNameGenerator, this.relationshipNameGenerator,\n\t\t\t\tthis.fieldNameGenerator, this.target, this.defaultPackage, this.path, this.indent, this.clock,\n\t\t\t\tthis.addAtGenerated);\n\t}\n\n\t/**\n\t * Returns {@literal true} if the type with the given name should be excluded.\n\t * @param qualifiedName the type name to be checked\n\t * @return {@literal true} if the type with the given name should be excluded\n\t */\n\tboolean exclude(String qualifiedName) {\n\t\treturn this.excludes.contains(qualifiedName);\n\t}\n\n\t/**\n\t * Enum for the available indent styles.\n\t */\n\tpublic enum IndentStyle {\n\n\t\t/** Use tabs for indentation. */\n\t\tTAB,\n\t\t/** Use a configurable number of spaces for indentation. */\n\t\tSPACE\n\n\t}\n\n\t/**\n\t * The target Java baseline.\n\t */\n\tpublic enum JavaVersion {\n\n\t\t/**\n\t\t * Generated code should compile on Java 8.\n\t\t */\n\t\tRELEASE_8,\n\t\t/**\n\t\t * Generated code should compile on Java 11 or higher.\n\t\t */\n\t\tRELEASE_11\n\n\t}\n\n\t/**\n\t * Use this builder to create new\n\t * {@link org.neo4j.cypherdsl.core.renderer.Configuration} instances.\n\t */\n\t@SuppressWarnings(\"HiddenField\")\n\tpublic static final class Builder {\n\n\t\tprivate ClassNameGenerator nodeNameGenerator = new NodeNameGenerator();\n\n\t\tprivate ClassNameGenerator relationshipNameGenerator = new RelationshipNameGenerator();\n\n\t\tprivate FieldNameGenerator fieldNameGenerator = FieldNameGenerator.Default.INSTANCE;\n\n\t\tprivate JavaVersion target = JavaVersion.RELEASE_11;\n\n\t\tprivate String defaultPackage = \"\";\n\n\t\tprivate Path path;\n\n\t\tprivate String prefix;\n\n\t\tprivate String suffix = \"_\";\n\n\t\tprivate IndentStyle indentStyle = IndentStyle.TAB;\n\n\t\tprivate int indentSize = 2;\n\n\t\tprivate String timestamp;\n\n\t\tprivate boolean addAtGenerated = false;\n\n\t\tprivate Set<String> excludes = Set.of();\n\n\t\tprivate Builder() {\n\t\t}\n\n\t\tstatic Builder newConfig() {\n\t\t\treturn new Builder();\n\t\t}\n\n\t\tstatic Builder newConfig(final Path path) {\n\t\t\treturn new Builder().withPath(path);\n\t\t}\n\n\t\t/**\n\t\t * Changes the node name generator.\n\t\t * @param nodeNameGenerator a new generator\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withNodeNameGenerator(ClassNameGenerator nodeNameGenerator) {\n\n\t\t\tif (nodeNameGenerator == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"A class name generator for nodes is required.\");\n\t\t\t}\n\t\t\tthis.nodeNameGenerator = nodeNameGenerator;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Changes the relationship name generator.\n\t\t * @param relationshipNameGenerator a new generator\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withRelationshipNameGenerator(ClassNameGenerator relationshipNameGenerator) {\n\n\t\t\tif (relationshipNameGenerator == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"A class name generator for relationships is required.\");\n\t\t\t}\n\t\t\tthis.relationshipNameGenerator = relationshipNameGenerator;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Changes the field name generator.\n\t\t * @param fieldNameGenerator a new generator\n\t\t * @return this builder\n\t\t * @since 2023.8.0\n\t\t */\n\t\tpublic Builder withFieldNameGenerator(FieldNameGenerator fieldNameGenerator) {\n\n\t\t\tif (fieldNameGenerator == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"A field name generator is required.\");\n\t\t\t}\n\t\t\tthis.fieldNameGenerator = fieldNameGenerator;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configures the targeted Java version.\n\t\t * @param target the new target version\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withTarget(JavaVersion target) {\n\n\t\t\tif (target == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"A java version is required.\");\n\t\t\t}\n\t\t\tthis.target = target;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configures the default target package.\n\t\t * @param defaultPackage the target package\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withDefaultPackage(String defaultPackage) {\n\n\t\t\tif (defaultPackage == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"A default package is required.\");\n\t\t\t}\n\t\t\tthis.defaultPackage = defaultPackage;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configures a static timestamp for the builder to be used.\n\t\t * @param timestamp timestamp to write into the generated classes. Uses the\n\t\t * current time when no timestamp is given. Expected format is\n\t\t * {@link DateTimeFormatter#ISO_OFFSET_DATE_TIME}.\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withTimestamp(String timestamp) {\n\n\t\t\tthis.timestamp = timestamp;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * A path is not always necessary, for example in an annotation processor.\n\t\t * @param path a path into which the files should be written\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withPath(Path path) {\n\n\t\t\tthis.path = path;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configure a prefix for the generated classes. Will only be used when no other\n\t\t * naming generator is configured.\n\t\t * @param prefix prepended to the names of generated classes.\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withPrefix(String prefix) {\n\n\t\t\tthis.prefix = prefix;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configure a suffix for the generated classes. Will only be used when no other\n\t\t * naming generator is configured.\n\t\t * @param suffix appended to the names of generated classes.\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withSuffix(String suffix) {\n\n\t\t\tthis.suffix = suffix;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Should generated sources be marked as such.\n\t\t * @param addAtGenerated set to {@literal true} to mark generated sources as\n\t\t * generated\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withAddAtGenerated(boolean addAtGenerated) {\n\n\t\t\tthis.addAtGenerated = addAtGenerated;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configures the indentation style, aka Tabs vs. Spaces, I'll be watching.\n\t\t * @param indentStyle the style to use\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withIndentStyle(IndentStyle indentStyle) {\n\n\t\t\tif (indentStyle == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"Indent style is required.\");\n\t\t\t}\n\t\t\tthis.indentStyle = indentStyle;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configures the indent size.\n\t\t * @param indentSize the number of indents to use\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withIndentSize(int indentSize) {\n\t\t\tthis.indentSize = indentSize;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configures the types to exclude.\n\t\t * @param excludes if {@literal null} or empty, no types will be excluded\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withExcludes(String excludes) {\n\t\t\tif (excludes == null || excludes.isBlank()) {\n\t\t\t\tthis.excludes = Set.of();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.excludes = Arrays.stream(excludes.split(\",\"))\n\t\t\t\t\t.map(String::trim)\n\t\t\t\t\t.filter(Predicate.not(String::isBlank))\n\t\t\t\t\t.collect(Collectors.toUnmodifiableSet());\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * {@return a new, immutable configuration}\n\t\t */\n\t\tpublic Configuration build() {\n\n\t\t\tUnaryOperator<String> typeNameDecorator;\n\t\t\tif (this.prefix == null && this.suffix == null) {\n\t\t\t\ttypeNameDecorator = UnaryOperator.identity();\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttypeNameDecorator = s -> ((this.prefix != null) ? this.prefix.trim() : \"\") + s\n\t\t\t\t\t\t+ ((this.suffix != null) ? this.suffix.trim() : \"\");\n\t\t\t}\n\n\t\t\tString indent;\n\t\t\tif (this.indentStyle == IndentStyle.TAB) {\n\t\t\t\tindent = \"\\t\";\n\t\t\t}\n\t\t\telse {\n\t\t\t\tindent = \" \".repeat(Math.max(0, this.indentSize));\n\t\t\t}\n\n\t\t\tClock clock = null;\n\t\t\tif (this.timestamp != null && !this.timestamp.isEmpty()) {\n\t\t\t\tZonedDateTime z = ZonedDateTime.from(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(this.timestamp));\n\t\t\t\tclock = Clock.fixed(z.toInstant(), z.getZone());\n\t\t\t}\n\t\t\treturn new Configuration(typeNameDecorator, this.nodeNameGenerator, this.relationshipNameGenerator,\n\t\t\t\t\tthis.fieldNameGenerator, this.target, this.defaultPackage, this.path, indent, clock,\n\t\t\t\t\tthis.addAtGenerated, this.excludes);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/FieldNameGenerator.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\n/**\n * A generator for constant field names.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@FunctionalInterface\npublic interface FieldNameGenerator {\n\n\t/**\n\t * Generates a new name for constant field.\n\t * @param name the name of a node or relationship\n\t * @return a valid constant field name\n\t */\n\tString generate(String name);\n\n\t/**\n\t * Single instance of the default {@link FieldNameGenerator}.\n\t */\n\tenum Default implements FieldNameGenerator {\n\n\t\t/**\n\t\t * Singleton holder.\n\t\t */\n\t\tINSTANCE;\n\n\t\t@Override\n\t\tpublic String generate(String name) {\n\t\t\tStringBuilder sb = new StringBuilder();\n\n\t\t\tint codePoint;\n\t\t\tint previousIndex = 0;\n\t\t\tboolean prevWasLower = false;\n\t\t\tboolean nextIsLower = false;\n\t\t\tint i = 0;\n\t\t\twhile (i < name.length()) {\n\t\t\t\tcodePoint = name.codePointAt(i);\n\t\t\t\tif (Identifiers.isValidAt(i, codePoint)) {\n\t\t\t\t\tif (nextIsLower || Character.isLowerCase(codePoint)) {\n\t\t\t\t\t\tprevWasLower = true;\n\t\t\t\t\t\tnextIsLower = false;\n\t\t\t\t\t\tif (!(sb.isEmpty() || Character.isLetter(name.codePointAt(previousIndex)))) {\n\t\t\t\t\t\t\tsb.append(\"_\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcodePoint = Character.toUpperCase(codePoint);\n\t\t\t\t\t}\n\t\t\t\t\telse if (!sb.isEmpty() && (prevWasLower\n\t\t\t\t\t\t\t|| i + 1 < name.length() && Character.isLowerCase(name.codePointAt(i + 1)))) {\n\t\t\t\t\t\tsb.append(\"_\");\n\t\t\t\t\t\tnextIsLower = true;\n\t\t\t\t\t}\n\t\t\t\t\tsb.append(Character.toChars(codePoint));\n\t\t\t\t}\n\t\t\t\tpreviousIndex = i;\n\t\t\t\ti += Character.charCount(codePoint);\n\t\t\t}\n\t\t\treturn sb.toString();\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/Identifiers.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\n/**\n * Utilities for dealing with identifiers.\n *\n * @author Michael J. Simons\n */\nfinal class Identifiers {\n\n\tprivate Identifiers() {\n\t}\n\n\t/**\n\t * A convenience method to decide whether a given {@code codePoint} is a valid Java\n\t * identifier at the given position {@code p}.\n\t * @param p position on which the {@code codePoint} is supposed to be used as\n\t * identifier\n\t * @param codePoint a codepoint\n\t * @return true if the codePoint could be used as part of an identifier at the given\n\t * position\n\t */\n\tstatic boolean isValidAt(int p, int codePoint) {\n\t\treturn p == 0 && Character.isJavaIdentifierStart(codePoint)\n\t\t\t\t|| p > 0 && Character.isJavaIdentifierPart(codePoint);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/ModelBuilder.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport java.io.IOException;\nimport java.nio.file.Path;\nimport java.util.Collection;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.EXPERIMENTAL;\n\n/**\n * Shared interface for model builder. This interface and the concrete classes\n * implementing it is considered to be public API.\n *\n * @param <SELF> a type representing the concrete model builder itself\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = EXPERIMENTAL, since = \"2021.1.0\")\npublic interface ModelBuilder<SELF extends ModelBuilder<?>> {\n\n\t/**\n\t * Adds a single new property to this model.\n\t * @param newProperty the new property\n\t * @return this builder\n\t * @throws IllegalStateException when this builder has already been used to create\n\t * Java class.\n\t */\n\tSELF addProperty(String newProperty);\n\n\t/**\n\t * Adds a single new property to this model.\n\t * @param newProperty the new property\n\t * @return this builder\n\t * @throws IllegalStateException when this builder has already been used to create\n\t * Java class.\n\t */\n\tSELF addProperty(PropertyDefinition newProperty);\n\n\t/**\n\t * Adds a collection of properties to this model.\n\t * @param newProperties a new collection of properties\n\t * @return this builder\n\t * @throws IllegalStateException when this builder has already been used to create\n\t * Java class.\n\t */\n\tSELF addProperties(Collection<PropertyDefinition> newProperties);\n\n\t/**\n\t * {@return the qualified package name or an empty string for the default package}\n\t */\n\tString getPackageName();\n\n\t/**\n\t * {@return the canonical class name}\n\t */\n\tString getCanonicalClassName();\n\n\t/**\n\t * {@return the simple class name without any pre- or suffix}\n\t */\n\tString getPlainClassName();\n\n\t/**\n\t * Triggers the creation of the final model and writes it as a Java class file to the\n\t * given path. It is safe to call this method several times or any of the other\n\t * {@code writeTo} methods, but changing the builder after this method has been called\n\t * will lead to an {@link IllegalStateException}.\n\t * @param path the path to write this model to.\n\t * @throws java.io.UncheckedIOException in case IO fails, any {@link IOException} is\n\t * wrapped and rethrown.\n\t */\n\tvoid writeTo(Path path);\n\n\t/**\n\t * Triggers the creation of the final model and returns a Java class definition as\n\t * string. It is safe to call this method several times or any of the other\n\t * {@code writeTo} methods, but changing the builder after this method has been called\n\t * will lead to an {@link IllegalStateException}.\n\t * @return the generated class as a string\n\t * @throws java.io.UncheckedIOException in case IO fails, any {@link IOException} is\n\t * wrapped and rethrown.\n\t */\n\tString writeToString();\n\n\t/**\n\t * Triggers the creation of the final model and appends it to the given\n\t * {@link Appendable} as Java class. It is safe to call this method several times or\n\t * any of the other {@code writeTo} methods, but changing the builder after this\n\t * method has been called will lead to an {@link IllegalStateException}.\n\t * <p>\n\t * An appendable that is also closable will still be open after passing it to this\n\t * method.\n\t * @param appendable to where the generated source should be appended to\n\t * @throws java.io.UncheckedIOException in case IO fails, any {@link IOException} is\n\t * wrapped and rethrown.\n\t */\n\tvoid writeTo(Appendable appendable);\n\n\t/**\n\t * Returns a field name suitable for storing an instance of the class generated by *\n\t * this builder.\n\t * @return a field name suitable for storing an instance of the class generated by\n\t * this builder\n\t */\n\tString getFieldName();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/NodeImplBuilder.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.function.Function;\nimport java.util.stream.Stream;\n\nimport javax.lang.model.element.Modifier;\n\nimport com.squareup.javapoet.AnnotationSpec;\nimport com.squareup.javapoet.ClassName;\nimport com.squareup.javapoet.CodeBlock;\nimport com.squareup.javapoet.FieldSpec;\nimport com.squareup.javapoet.JavaFile;\nimport com.squareup.javapoet.MethodSpec;\nimport com.squareup.javapoet.ParameterSpec;\nimport com.squareup.javapoet.ParameterizedTypeName;\nimport com.squareup.javapoet.TypeName;\nimport com.squareup.javapoet.TypeSpec;\nimport com.squareup.javapoet.TypeVariableName;\nimport com.squareup.javapoet.WildcardTypeName;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\n\n/**\n * This is a builder. It builds classes extending {@link NodeBase}. The workflow is as\n * follows: Create an instance via {@link #create(Configuration, String, String)},\n * defining the target package (fully qualified name) as well as the type. Unless\n * {@link #writeTo(java.nio.file.Path)} or {@link #writeToString()} is called, additional\n * labels and properties can be added with {@link #addLabels(Collection)} and\n * {@link #addProperty(String)}. A call to any of the {@code writeToXXX} methods will\n * trigger the generation of source code and after that, this instance becomes effectively\n * immutable.\n *\n * @author Michael J. Simons\n * @author Andreas Berger\n * @since 2021.1.0\n */\nfinal class NodeImplBuilder extends AbstractModelBuilder<NodeModelBuilder> implements NodeModelBuilder {\n\n\tprivate static final ClassName TYPE_NAME_NODE_LABEL = ClassName.get(NodeLabel.class);\n\n\tprivate final Set<String> labels = new LinkedHashSet<>();\n\n\tprivate final Set<RelationshipPropertyDefinition> relationshipDefinitions = new LinkedHashSet<>();\n\n\tprivate final Set<RelationshipFactoryDefinition> relationshipMethodDefinitions = new LinkedHashSet<>();\n\n\tprivate NodeModelBuilder baseModel;\n\n\tprivate TypeVariableName self;\n\n\tprivate boolean extensible;\n\n\tprivate NodeImplBuilder(Configuration configuration, ClassName className, String fieldName) {\n\t\tsuper(configuration.getConstantFieldNameGenerator(), className, fieldName, configuration.getTarget(),\n\t\t\t\tconfiguration.getIndent());\n\t\tthis.self = TypeVariableName.get(\"SELF\", className);\n\t}\n\n\tstatic NodeModelBuilder create(Configuration configuration, String packageName, String suggestedTypeName) {\n\n\t\tString className = configuration.getNodeNameGenerator().generate(suggestedTypeName);\n\t\tString usedPackageName = (packageName != null) ? packageName : configuration.getDefaultPackage();\n\t\tNodeImplBuilder builder = new NodeImplBuilder(configuration,\n\t\t\t\tClassName.get(usedPackageName, configuration.getTypeNameDecorator().apply(className)), className);\n\t\treturn builder.apply(configuration);\n\t}\n\n\tprivate static boolean isSelfReferential(RelationshipPropertyDefinition rpd) {\n\t\treturn rpd.getStart() == rpd.getEnd();\n\t}\n\n\tprivate static boolean isNotSelfReferential(RelationshipPropertyDefinition rpd) {\n\t\treturn !isSelfReferential(rpd);\n\t}\n\n\tstatic String capitalize(String str) {\n\n\t\tif (str == null || str.isBlank()) {\n\t\t\treturn str;\n\t\t}\n\t\telse {\n\t\t\tchar baseChar = str.charAt(0);\n\t\t\tchar updatedChar = Character.toUpperCase(baseChar);\n\t\t\tif (baseChar == updatedChar) {\n\t\t\t\treturn str;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tchar[] chars = str.toCharArray();\n\t\t\t\tchars[0] = updatedChar;\n\t\t\t\treturn new String(chars);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic NodeModelBuilder addLabel(String newLabel) {\n\n\t\treturn addLabels((newLabel != null) ? Collections.singleton(newLabel) : Collections.emptyList());\n\t}\n\n\t@Override\n\tpublic NodeModelBuilder addLabels(Collection<String> newLabels) {\n\n\t\treturn callOnlyWithoutJavaFilePresent(() -> {\n\t\t\tif (newLabels != null) {\n\t\t\t\tthis.labels.addAll(newLabels);\n\t\t\t}\n\t\t\treturn this;\n\t\t});\n\t}\n\n\t@Override\n\tpublic NodeModelBuilder addRelationshipDefinition(RelationshipPropertyDefinition definition) {\n\n\t\treturn callOnlyWithoutJavaFilePresent(() -> {\n\t\t\tif (definition != null) {\n\t\t\t\tthis.relationshipDefinitions.add(definition);\n\t\t\t}\n\t\t\treturn this;\n\t\t});\n\t}\n\n\t@Override\n\tpublic NodeModelBuilder addRelationshipFactory(RelationshipFactoryDefinition definition) {\n\t\treturn callOnlyWithoutJavaFilePresent(() -> {\n\t\t\tif (definition != null) {\n\t\t\t\tthis.relationshipMethodDefinitions.add(definition);\n\t\t\t}\n\t\t\treturn this;\n\t\t});\n\t}\n\n\t@Override\n\tpublic NodeModelBuilder setBaseNodeModel(NodeModelBuilder baseNodeModel) {\n\t\treturn callOnlyWithoutJavaFilePresent(() -> {\n\t\t\tthis.baseModel = baseNodeModel;\n\t\t\treturn this;\n\t\t});\n\t}\n\n\t@Override\n\tpublic NodeModelBuilder setExtensible(boolean isExtensible) {\n\t\treturn callOnlyWithoutJavaFilePresent(() -> {\n\t\t\tsynchronized (NodeImplBuilder.this) {\n\t\t\t\tthis.extensible = isExtensible;\n\t\t\t\tif (this.extensible) {\n\t\t\t\t\tthis.self = TypeVariableName.get(\"SELF\",\n\t\t\t\t\t\t\tParameterizedTypeName.get(this.className, WildcardTypeName.subtypeOf(Object.class)));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.self = TypeVariableName.get(\"SELF\", this.className);\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic boolean isExtensible() {\n\t\treturn this.extensible;\n\t}\n\n\tprivate MethodSpec buildDefaultConstructor(FieldSpec primaryLabelField) {\n\n\t\tvar superCallBuilder = CodeBlock.builder().add(\"super(\");\n\t\tsuperCallBuilder.add(CodeBlock.of(\"$N\", primaryLabelField));\n\t\tif (this.labels.size() > 1) {\n\t\t\tsuperCallBuilder.add(\", \");\n\t\t\tsuperCallBuilder\n\t\t\t\t.add(CodeBlock.join(this.labels.stream().skip(1).map(l -> CodeBlock.of(\"$S\", l)).toList(), \", \"));\n\t\t}\n\t\tsuperCallBuilder.add(\")\");\n\n\t\treturn MethodSpec.constructorBuilder()\n\t\t\t.addModifiers(Modifier.PUBLIC)\n\t\t\t.addStatement(superCallBuilder.build())\n\t\t\t.build();\n\t}\n\n\tprivate MethodSpec buildConstructorForInheritance(FieldSpec primaryLabelField) {\n\n\t\tvar primaryLabelParam = ParameterSpec.builder(String.class, \"primaryLabel\").build();\n\t\tvar additionalLabels = ParameterSpec.builder(String[].class, \"additionalLabels\").build();\n\n\t\tCodeBlock.Builder superCallBuilder = CodeBlock.builder().add(\"super(\");\n\t\tsuperCallBuilder.add(CodeBlock.of(\"$N\", primaryLabelParam));\n\t\tsuperCallBuilder.add(\", \");\n\t\tsuperCallBuilder.add(CodeBlock.of(\"$T.concat($T.stream($N), $T.of($N\", Stream.class, Arrays.class,\n\t\t\t\tadditionalLabels, Stream.class, primaryLabelField));\n\t\tif (this.labels.size() > 1) {\n\t\t\tsuperCallBuilder.add(\", \");\n\t\t\tsuperCallBuilder\n\t\t\t\t.add(CodeBlock.join(this.labels.stream().skip(1).map(l -> CodeBlock.of(\"$S\", l)).toList(), \", \"));\n\t\t}\n\t\tsuperCallBuilder.add(\")).toArray($T[]::new))\", String.class);\n\n\t\treturn MethodSpec.constructorBuilder()\n\t\t\t.addModifiers(Modifier.PROTECTED)\n\t\t\t.addParameter(primaryLabelParam)\n\t\t\t.addParameter(additionalLabels)\n\t\t\t.varargs()\n\t\t\t.addStatement(superCallBuilder.build())\n\t\t\t.build();\n\t}\n\n\tprivate MethodSpec buildCreateMethod() {\n\t\tParameterSpec symbolicName = ParameterSpec.builder(TYPE_NAME_SYMBOLIC_NAME, \"symbolicName\").build();\n\t\tParameterSpec labelsParameter = ParameterSpec\n\t\t\t.builder(ParameterizedTypeName.get(TYPE_NAME_LIST, TYPE_NAME_NODE_LABEL), \"labels\")\n\t\t\t.build();\n\t\tParameterSpec properties = ParameterSpec.builder(ClassName.get(Properties.class), \"properties\").build();\n\n\t\tMethodSpec.Builder builder = MethodSpec.methodBuilder(\"create\")\n\t\t\t.addModifiers(Modifier.PROTECTED)\n\t\t\t.addParameter(symbolicName)\n\t\t\t.addParameter(labelsParameter)\n\t\t\t.addParameter(properties);\n\t\tif (this.baseModel != null) {\n\t\t\tbuilder.addAnnotation(Override.class);\n\t\t}\n\t\tif (this.extensible) {\n\t\t\tbuilder.addAnnotation(\n\t\t\t\t\tAnnotationSpec.builder(SuppressWarnings.class).addMember(\"value\", \"\\\"unchecked\\\"\").build());\n\t\t\tbuilder\n\t\t\t\t.addStatement(\"return ($T) new $T<>($N, $N, $N)\", this.self, this.className, symbolicName,\n\t\t\t\t\t\tlabelsParameter, properties)\n\t\t\t\t.returns(this.self);\n\t\t}\n\t\telse {\n\t\t\tbuilder.addStatement(\"return new $T($N, $N, $N)\", this.className, symbolicName, labelsParameter, properties)\n\t\t\t\t.returns(this.className);\n\t\t}\n\t\treturn builder.build();\n\t}\n\n\tprivate MethodSpec buildCopyConstructor() {\n\n\t\tParameterSpec symbolicName = ParameterSpec.builder(TYPE_NAME_SYMBOLIC_NAME, \"symbolicName\").build();\n\t\tParameterSpec labelsParameter = ParameterSpec\n\t\t\t.builder(ParameterizedTypeName.get(TYPE_NAME_LIST, TYPE_NAME_NODE_LABEL), \"labels\")\n\t\t\t.build();\n\t\tParameterSpec properties = ParameterSpec.builder(ClassName.get(Properties.class), \"properties\").build();\n\t\treturn MethodSpec.constructorBuilder()\n\t\t\t.addModifiers(this.extensible ? Modifier.PROTECTED : Modifier.PRIVATE)\n\t\t\t.addParameter(symbolicName)\n\t\t\t.addParameter(labelsParameter)\n\t\t\t.addParameter(properties)\n\t\t\t.addStatement(\"super($N, $N, $N)\", symbolicName, labelsParameter, properties)\n\t\t\t.build();\n\n\t}\n\n\tprivate MethodSpec buildNamedMethod() {\n\n\t\tParameterSpec newSymbolicName = ParameterSpec.builder(TYPE_NAME_SYMBOLIC_NAME, \"newSymbolicName\").build();\n\t\tMethodSpec.Builder builder = MethodSpec.methodBuilder(\"named\")\n\t\t\t.addAnnotation(Override.class)\n\t\t\t.addModifiers(Modifier.PUBLIC)\n\t\t\t.addParameter(newSymbolicName);\n\t\tif (this.extensible) {\n\t\t\tbuilder.returns(this.self).addStatement(\"return create($N, getLabels(), getProperties())\", newSymbolicName);\n\t\t}\n\t\telse {\n\t\t\tbuilder.returns(this.className)\n\t\t\t\t.addStatement(\"return new $T($N, getLabels(), getProperties())\", this.className, newSymbolicName);\n\t\t}\n\t\treturn builder.build();\n\t}\n\n\tprivate MethodSpec buildWithPropertiesMethod() {\n\n\t\tParameterSpec newProperties = ParameterSpec.builder(TYPE_NAME_MAP_EXPRESSION, \"newProperties\").build();\n\t\tMethodSpec.Builder builder = MethodSpec.methodBuilder(\"withProperties\")\n\t\t\t.addAnnotation(Override.class)\n\t\t\t.addModifiers(Modifier.PUBLIC)\n\t\t\t.addParameter(newProperties);\n\t\tif (this.extensible) {\n\t\t\tbuilder.returns(this.self)\n\t\t\t\t.addStatement(\"return create(getSymbolicName().orElse(null), getLabels(), Properties.create($N))\",\n\t\t\t\t\t\tnewProperties);\n\t\t}\n\t\telse {\n\t\t\tbuilder.returns(this.className)\n\t\t\t\t.addStatement(\"return new $T(getSymbolicName().orElse(null), getLabels(), Properties.create($N))\",\n\t\t\t\t\t\tthis.className, newProperties);\n\t\t}\n\t\treturn builder.build();\n\t}\n\n\tprivate List<FieldSpec> buildFields(FieldSpec primaryLabelField) {\n\n\t\tFieldSpec defaultInstance;\n\t\tif (this.extensible) {\n\t\t\tvar type = ParameterizedTypeName.get(this.className,\n\t\t\t\t\tParameterizedTypeName.get(this.className, WildcardTypeName.subtypeOf(Object.class)));\n\t\t\tdefaultInstance = FieldSpec.builder(type, getFieldName(), Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)\n\t\t\t\t.initializer(\"new $T<>()\", this.className)\n\t\t\t\t.build();\n\n\t\t}\n\t\telse {\n\t\t\tdefaultInstance = FieldSpec\n\t\t\t\t.builder(this.className, getFieldName(), Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)\n\t\t\t\t.initializer(\"new $T()\", this.className)\n\t\t\t\t.build();\n\n\t\t}\n\n\t\tStream<FieldSpec> properties = generateFieldSpecsFromProperties();\n\n\t\tStream<FieldSpec> relationships = this.relationshipDefinitions.stream()\n\t\t\t.filter(NodeImplBuilder::isNotSelfReferential)\n\t\t\t.map(p -> {\n\n\t\t\t\tString fieldName = this.fieldNameGenerator\n\t\t\t\t\t.generate((p.getNameInDomain() != null) ? p.getNameInDomain() : p.getType());\n\t\t\t\tClassName startClass = extractClassName(p.getStart());\n\t\t\t\tClassName endClass = extractClassName(p.getEnd());\n\n\t\t\t\tvar relationshipClassName = getRelationTypeWithParameters(p.getRelationshipBuilder(), startClass,\n\t\t\t\t\t\tendClass);\n\t\t\t\tFieldSpec.Builder builder = FieldSpec.builder(relationshipClassName, fieldName, Modifier.PUBLIC,\n\t\t\t\t\t\tModifier.FINAL);\n\t\t\t\tif (this == p.getStart()) {\n\t\t\t\t\tbuilder.initializer(\"new $T(this, $T.$N)\", relationshipClassName, endClass,\n\t\t\t\t\t\t\tp.getEnd().getFieldName());\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbuilder.initializer(\"new $T($T.$N, this)\", relationshipClassName, startClass,\n\t\t\t\t\t\t\tp.getStart().getFieldName());\n\t\t\t\t}\n\t\t\t\treturn builder.build();\n\t\t\t});\n\n\t\treturn Stream.concat(Stream.of(primaryLabelField, defaultInstance), Stream.concat(properties, relationships))\n\t\t\t.toList();\n\t}\n\n\t@Override\n\tprotected JavaFile buildJavaFile() {\n\n\t\tif (this.labels.isEmpty()) {\n\t\t\tthrow new IllegalStateException(\"Cannot build NodeImpl without labels!\");\n\t\t}\n\t\tvar baseNode = (this.baseModel != null) ? extractClassName(this.baseModel) : TYPE_NAME_NODE_BASE;\n\t\tif (this.baseModel != null && (!(this.baseModel instanceof NodeImplBuilder nmb) || !nmb.extensible)) {\n\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\"Cannot extend non-extensible node \" + this.baseModel.getCanonicalClassName());\n\t\t}\n\n\t\tvar primaryLabelField = FieldSpec\n\t\t\t.builder(String.class, this.fieldNameGenerator.generate(\"$PRIMARY_LABEL\"), Modifier.PUBLIC, Modifier.FINAL,\n\t\t\t\t\tModifier.STATIC)\n\t\t\t.initializer(\"$S\", this.labels.stream().findFirst().orElseThrow())\n\t\t\t.build();\n\n\t\tTypeSpec.Builder builder = addGenerated(TypeSpec.classBuilder(this.className));\n\t\tbuilder.addModifiers(Modifier.PUBLIC);\n\t\tif (this.extensible) {\n\t\t\tbuilder.addTypeVariable(this.self).superclass(ParameterizedTypeName.get(baseNode, this.self));\n\t\t}\n\t\telse {\n\t\t\tbuilder.addModifiers(Modifier.FINAL).superclass(ParameterizedTypeName.get(baseNode, this.className));\n\t\t}\n\t\tbuilder.addFields(buildFields(primaryLabelField)).addMethod(buildDefaultConstructor(primaryLabelField));\n\t\tif (this.extensible) {\n\t\t\tbuilder.addMethod(buildConstructorForInheritance(primaryLabelField));\n\t\t}\n\t\tif (this.extensible || baseNode != TYPE_NAME_NODE_BASE) {\n\t\t\tbuilder.addMethod(buildCreateMethod());\n\t\t}\n\t\tbuilder.addMethod(buildCopyConstructor());\n\t\tif (baseNode == TYPE_NAME_NODE_BASE) {\n\t\t\tbuilder.addMethod(buildNamedMethod()).addMethod(buildWithPropertiesMethod());\n\t\t}\n\n\t\tthis.relationshipDefinitions.stream()\n\t\t\t.filter(NodeImplBuilder::isSelfReferential)\n\t\t\t.map(buildSelfReferentialAccessor())\n\t\t\t.forEach(builder::addMethod);\n\n\t\tthis.relationshipMethodDefinitions.stream().map(buildRelationshipFactoryMethod()).forEach(builder::addMethod);\n\n\t\tTypeSpec newType = builder.build();\n\n\t\treturn prepareFileBuilder(newType).build();\n\t}\n\n\tprivate TypeName getRelationTypeWithParameters(RelationshipModelBuilder relationshipBuilder, TypeName startClass,\n\t\t\tClassName endClass) {\n\t\tTypeName relationshipClassName;\n\t\tif (relationshipBuilder instanceof RelationshipImplBuilder impl) {\n\t\t\trelationshipClassName = impl.getTypeName(startClass, endClass);\n\t\t}\n\t\telse {\n\t\t\trelationshipClassName = extractClassName(relationshipBuilder);\n\t\t}\n\t\treturn relationshipClassName;\n\t}\n\n\tprivate Function<RelationshipPropertyDefinition, MethodSpec> buildSelfReferentialAccessor() {\n\t\treturn p -> {\n\t\t\tClassName relationshipClassName = extractClassName(p.getRelationshipBuilder());\n\t\t\tParameterSpec end = ParameterSpec.builder(this.className, p.getNameInDomain()).build();\n\t\t\treturn MethodSpec.methodBuilder(\"with\" + capitalize(p.getNameInDomain()))\n\t\t\t\t.addModifiers(Modifier.PUBLIC)\n\t\t\t\t.returns(relationshipClassName)\n\t\t\t\t.addParameter(end)\n\t\t\t\t.addStatement(\"return new $T(this, $N)\", relationshipClassName, end)\n\t\t\t\t.build();\n\t\t};\n\t}\n\n\tprivate Function<RelationshipFactoryDefinition, MethodSpec> buildRelationshipFactoryMethod() {\n\t\treturn p -> {\n\t\t\tClassName startClass = extractClassName(p.getStart());\n\t\t\tClassName endClass = extractClassName(p.getEnd());\n\n\t\t\tTypeName relationshipClassName = getRelationTypeWithParameters(p.getRelationshipBuilder(), startClass,\n\t\t\t\t\tendClass);\n\t\t\tvar b = MethodSpec.methodBuilder(p.getNameInDomain())\n\t\t\t\t.addModifiers(Modifier.PUBLIC)\n\t\t\t\t.returns(relationshipClassName);\n\t\t\tif (this == p.getStart()) {\n\t\t\t\tParameterSpec param = ParameterSpec.builder(endClass, \"end\").build();\n\t\t\t\tb.addParameter(param).addStatement(\"return new $T(this, $N)\", relationshipClassName, param);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tParameterSpec param = ParameterSpec.builder(startClass, \"start\").build();\n\t\t\t\tb.addParameter(param).addStatement(\"return new $T($N, this)\", relationshipClassName, param);\n\t\t\t}\n\t\t\treturn b.build();\n\t\t};\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/NodeModelBuilder.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport java.util.Collection;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.EXPERIMENTAL;\n\n/**\n * Helper class to create static code describing labels and properties of a\n * {@code org.neo4j.cypherdsl.core.Node} object.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = EXPERIMENTAL, since = \"2021.1.0\")\npublic interface NodeModelBuilder extends ModelBuilder<NodeModelBuilder> {\n\n\t/**\n\t * Get a new instance of a node model builder. The instance can be modified as long as\n\t * no {@code writeToXXX} method has been called.\n\t * @param configuration the generators configuration\n\t * @param packageName a package name, which can be null. In that case, the default\n\t * package name from the configuration is taken\n\t * @param suggestedTypeName a suggested type name\n\t * @return a new instance without any labels or properties registered.\n\t */\n\tstatic NodeModelBuilder create(Configuration configuration, String packageName, String suggestedTypeName) {\n\n\t\treturn NodeImplBuilder.create(configuration, packageName, suggestedTypeName);\n\t}\n\n\t/**\n\t * Adds a new label to this builder.\n\t * @param newLabel the new label\n\t * @return this builder\n\t * @throws IllegalStateException when this builder has already been used to create\n\t * Java class.\n\t */\n\tNodeModelBuilder addLabel(String newLabel);\n\n\t/**\n\t * Adds several new labels to this builder.\n\t * @param newLabels the list of new labels\n\t * @return this builder\n\t * @throws IllegalStateException when this builder has already been used to create\n\t * Java class.\n\t */\n\tNodeModelBuilder addLabels(Collection<String> newLabels);\n\n\t/**\n\t * Adds a relationship definition to this builder.\n\t * @param definition the definition of a relationship\n\t * @return this builder\n\t * @throws IllegalStateException when this builder has already been used to create\n\t * Java class.\n\t */\n\tNodeModelBuilder addRelationshipDefinition(RelationshipPropertyDefinition definition);\n\n\t/**\n\t * Adds a factory method for a relationship to this builder.\n\t * @param definition the definition of the relationship\n\t * @return this builder\n\t * @throws IllegalStateException when this builder has already been used to create\n\t * Java class.\n\t * @since 2023.9.0\n\t */\n\tNodeModelBuilder addRelationshipFactory(RelationshipFactoryDefinition definition);\n\n\t/**\n\t * Adds a model this model should extend.\n\t * @param baseModel the model to extend\n\t * @return this builder\n\t * @throws IllegalStateException when this builder has already been used to create\n\t * Java class.\n\t * @since 2023.9.2\n\t */\n\tNodeModelBuilder setBaseNodeModel(NodeModelBuilder baseModel);\n\n\t/**\n\t * Returns {@literal true} when this builder produces extensible modules.\n\t * @return {@literal true} when this builder produces extensible modules\n\t */\n\tboolean isExtensible();\n\n\t/**\n\t * If true, this model will be extensible.\n\t * @param extensible true if this model should be extensible\n\t * @return this builder\n\t * @throws IllegalStateException when this builder has already been used to create\n\t * Java class.\n\t * @since 2023.9.2\n\t */\n\tNodeModelBuilder setExtensible(boolean extensible);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/NodeNameGenerator.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Default generator for creating names of node classes. Just creates a valid java\n * identifier from a suggested name. No further optimization is done. Suggested name can\n * be a list of labels etc.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\nfinal class NodeNameGenerator extends AbstractClassNameGenerator implements ClassNameGenerator {\n\n\t@Override\n\tpublic String generate(String suggestedName) {\n\n\t\treturn generateTypeName(suggestedName).toString();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/PropertyDefinition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport java.util.Objects;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.EXPERIMENTAL;\n\n/**\n * Represents a property name: With a name in the graph and an optional name in the domain\n * model.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = EXPERIMENTAL, since = \"2021.1.0\")\npublic final class PropertyDefinition {\n\n\t/**\n\t * Name of the property inside the graph.\n\t */\n\tprivate final String nameInGraph;\n\n\t/**\n\t * Optional name of the property inside the domain.\n\t */\n\tprivate final String nameInDomain;\n\n\tprivate PropertyDefinition(String nameInGraph, String nameInDomain) {\n\t\tthis.nameInGraph = nameInGraph;\n\t\tthis.nameInDomain = nameInDomain;\n\t}\n\n\t/**\n\t * Creates a new property definition.\n\t * @param nameInGraph required name in graph.\n\t * @param optionalNameInDomain optional in domain\n\t * @return a working definition\n\t */\n\tpublic static PropertyDefinition create(String nameInGraph, String optionalNameInDomain) {\n\n\t\tif (nameInGraph == null || nameInGraph.isBlank()) {\n\t\t\tthrow new IllegalArgumentException(\"The name of the property in the graph must not be null or empty.\");\n\t\t}\n\t\treturn new PropertyDefinition(nameInGraph, optionalNameInDomain);\n\t}\n\n\t/**\n\t * {@return the name as defined in the future graph}\n\t */\n\tpublic String getNameInGraph() {\n\t\treturn this.nameInGraph;\n\t}\n\n\t/**\n\t * {@return the name as defined in the domain object (most likely the field name)}\n\t */\n\tpublic String getNameInDomain() {\n\t\treturn this.nameInDomain;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (this == o) {\n\t\t\treturn true;\n\t\t}\n\t\tif (o == null || getClass() != o.getClass()) {\n\t\t\treturn false;\n\t\t}\n\t\tPropertyDefinition that = (PropertyDefinition) o;\n\t\treturn this.nameInGraph.equals(that.nameInGraph) && Objects.equals(this.nameInDomain, that.nameInDomain);\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn Objects.hash(this.nameInGraph, this.nameInDomain);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/RelationshipFactoryDefinition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.EXPERIMENTAL;\n\n/**\n * This represents a method in the static metamodel that creates a relationship.\n *\n * @author Andreas Berger\n * @since 2023.9.0\n */\n@API(status = EXPERIMENTAL, since = \"2023.9.0\")\npublic final class RelationshipFactoryDefinition {\n\n\t/**\n\t * Optional name in the domain, for example a field name.\n\t */\n\tprivate final String nameInDomain;\n\n\t/**\n\t * start of the relationship.\n\t */\n\tprivate final NodeModelBuilder start;\n\n\t/**\n\t * end of the relationship.\n\t */\n\tprivate final NodeModelBuilder end;\n\n\t/**\n\t * The actual builder that defines this relationship.\n\t */\n\tprivate final RelationshipModelBuilder relationshipBuilder;\n\n\tprivate RelationshipFactoryDefinition(String nameInDomain, RelationshipModelBuilder relationshipBuilder,\n\t\t\tNodeModelBuilder start, NodeModelBuilder end) {\n\t\tthis.nameInDomain = nameInDomain;\n\t\tthis.start = start;\n\t\tthis.end = end;\n\t\tthis.relationshipBuilder = relationshipBuilder;\n\t}\n\n\t/**\n\t * Creates a new definition.\n\t * @param nameInDomain the name of the relationship in the domain class\n\t * @param start builder for the start node in the domain\n\t * @param end builder for the end node in the domain\n\t * @return a valid definition\n\t */\n\tpublic static RelationshipFactoryDefinition create(String nameInDomain, NodeModelBuilder start,\n\t\t\tNodeModelBuilder end) {\n\t\treturn new RelationshipFactoryDefinition(nameInDomain, null, start, end);\n\t}\n\n\t/**\n\t * Creates a new relationship definition with a new builder for it.\n\t * @param newBuilder the new builder to use\n\t * @return a new instance, {@literal this} won't change\n\t */\n\tpublic RelationshipFactoryDefinition withBuilder(RelationshipModelBuilder newBuilder) {\n\t\treturn new RelationshipFactoryDefinition(this.nameInDomain, newBuilder, this.start, this.end);\n\t}\n\n\t/**\n\t * Returns the name in the domain model (most likely the field name).\n\t * @return the name in the domain model\n\t */\n\tpublic String getNameInDomain() {\n\t\treturn this.nameInDomain;\n\t}\n\n\t/**\n\t * {@return a builder for the start node}\n\t */\n\tpublic NodeModelBuilder getStart() {\n\t\treturn this.start;\n\t}\n\n\t/**\n\t * {@return a builder for the end node}\n\t */\n\tpublic NodeModelBuilder getEnd() {\n\t\treturn this.end;\n\t}\n\n\tRelationshipModelBuilder getRelationshipBuilder() {\n\t\treturn this.relationshipBuilder;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/RelationshipImplBuilder.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport java.util.ArrayDeque;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Deque;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport javax.lang.model.element.Modifier;\n\nimport com.squareup.javapoet.ClassName;\nimport com.squareup.javapoet.FieldSpec;\nimport com.squareup.javapoet.JavaFile;\nimport com.squareup.javapoet.MethodSpec;\nimport com.squareup.javapoet.ParameterSpec;\nimport com.squareup.javapoet.ParameterizedTypeName;\nimport com.squareup.javapoet.TypeName;\nimport com.squareup.javapoet.TypeSpec;\nimport com.squareup.javapoet.TypeVariableName;\nimport com.squareup.javapoet.WildcardTypeName;\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * This is a builder. It builds classes extending {@link RelationshipImplBuilder}.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\nfinal class RelationshipImplBuilder extends AbstractModelBuilder<RelationshipModelBuilder>\n\t\timplements RelationshipModelBuilder {\n\n\tprivate static final ClassName TYPE_NAME_RELATIONSHIP_BASE = ClassName.get(RelationshipBase.class);\n\n\tprivate static final TypeVariableName S = TypeVariableName.get(\"S\",\n\t\t\tParameterizedTypeName.get(TYPE_NAME_NODE_BASE, WildcardTypeName.subtypeOf(Object.class)));\n\n\tprivate static final TypeVariableName E = TypeVariableName.get(\"E\",\n\t\t\tParameterizedTypeName.get(TYPE_NAME_NODE_BASE, WildcardTypeName.subtypeOf(Object.class)));\n\n\t/**\n\t * The required relationship type.\n\t */\n\tprivate final FieldSpec relationshipTypeField;\n\n\t/**\n\t * The possible start- and end-node connections.\n\t */\n\tprivate final Deque<Edge> edges = new ArrayDeque<>();\n\n\tprivate RelationshipImplBuilder(Configuration configuration, String relationshipType, ClassName className,\n\t\t\tString fieldName) {\n\t\tsuper(configuration.getConstantFieldNameGenerator(), className, fieldName, configuration.getTarget(),\n\t\t\t\tconfiguration.getIndent());\n\n\t\tif (relationshipType == null) {\n\t\t\tthrow new IllegalStateException(\"Cannot build a RelationshipImpl without a single relationship type!\");\n\t\t}\n\n\t\tthis.relationshipTypeField = FieldSpec\n\t\t\t.builder(String.class, configuration.getConstantFieldNameGenerator().generate(\"$TYPE\"), Modifier.PUBLIC,\n\t\t\t\t\tModifier.FINAL, Modifier.STATIC)\n\t\t\t.initializer(\"$S\", relationshipType)\n\t\t\t.build();\n\t}\n\n\tstatic RelationshipModelBuilder create(Configuration configuration, String packageName, String relationshipType,\n\t\t\tString alternateClassNameSuggestion) {\n\n\t\tString className = configuration.getRelationshipNameGenerator()\n\t\t\t.generate((alternateClassNameSuggestion != null) ? alternateClassNameSuggestion : relationshipType);\n\t\tString usedPackageName = (packageName != null) ? packageName : configuration.getDefaultPackage();\n\t\tRelationshipImplBuilder builder = new RelationshipImplBuilder(configuration, relationshipType,\n\t\t\t\tClassName.get(usedPackageName, configuration.getTypeNameDecorator().apply(className)), className);\n\t\treturn builder.apply(configuration);\n\t}\n\n\tstatic Edge pickDefault(Collection<Edge> relations) {\n\t\tvar startNodes = relations.stream().map(edge -> edge.start).collect(Collectors.toSet());\n\t\tvar endNodes = relations.stream().map(edge -> edge.end).collect(Collectors.toSet());\n\n\t\tvar expectedStartNode = (startNodes.size() == 1) ? startNodes.iterator().next() : S;\n\t\tvar expectedEndNode = (endNodes.size() == 1) ? endNodes.iterator().next() : E;\n\t\treturn new Edge(expectedStartNode, expectedEndNode);\n\t}\n\n\t@Override\n\tpublic RelationshipModelBuilder setStartNode(NodeModelBuilder newStartNode) {\n\t\tif (newStartNode == null) {\n\t\t\treturn this;\n\t\t}\n\t\treturn callOnlyWithoutJavaFilePresent(() -> {\n\t\t\tvar lastRelation = getOrCreateLastDefinedRelationType();\n\t\t\tlastRelation.start = extractClassName(newStartNode);\n\t\t\treturn this;\n\t\t});\n\t}\n\n\t@Override\n\tpublic RelationshipModelBuilder setEndNode(NodeModelBuilder newEndNode) {\n\t\tif (newEndNode == null) {\n\t\t\treturn this;\n\t\t}\n\t\treturn callOnlyWithoutJavaFilePresent(() -> {\n\t\t\tvar lastRelation = getOrCreateLastDefinedRelationType();\n\t\t\tlastRelation.end = extractClassName(newEndNode);\n\t\t\treturn this;\n\t\t});\n\t}\n\n\tprivate Edge getOrCreateLastDefinedRelationType() {\n\t\tvar lastRelation = this.edges.peek();\n\t\tif (lastRelation == null) {\n\t\t\tlastRelation = new Edge(S, E);\n\t\t\tthis.edges.push(lastRelation);\n\t\t}\n\t\treturn lastRelation;\n\t}\n\n\tprivate MethodSpec buildConstructor(Edge relation, Edge expectedTypes) {\n\t\tParameterSpec startNodeParam = ParameterSpec.builder(relation.start, \"start\").build();\n\t\tParameterSpec endNodeParam = ParameterSpec.builder(relation.end, \"end\").build();\n\t\tMethodSpec.Builder builder = MethodSpec.constructorBuilder()\n\t\t\t.addModifiers(Modifier.PUBLIC)\n\t\t\t.addParameter(startNodeParam)\n\t\t\t.addParameter(endNodeParam);\n\t\tif (relation.start != expectedTypes.start) {\n\t\t\tif (relation.end != expectedTypes.end) {\n\t\t\t\tbuilder.addStatement(\"super(($T) $N, $N, ($T) $N)\", expectedTypes.start, startNodeParam,\n\t\t\t\t\t\tthis.relationshipTypeField, expectedTypes.end, endNodeParam);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbuilder.addStatement(\"super(($T) $N, $N, $N)\", expectedTypes.start, startNodeParam,\n\t\t\t\t\t\tthis.relationshipTypeField, endNodeParam);\n\t\t\t}\n\t\t}\n\t\telse if (relation.end != expectedTypes.end) {\n\t\t\tbuilder.addStatement(\"super($N, $N, ($T) $N)\", startNodeParam, this.relationshipTypeField,\n\t\t\t\t\texpectedTypes.end, endNodeParam);\n\t\t}\n\t\telse {\n\t\t\tbuilder.addStatement(\"super($N, $N, $N)\", startNodeParam, this.relationshipTypeField, endNodeParam);\n\t\t}\n\t\treturn builder.build();\n\t}\n\n\t@Override\n\tpublic RelationshipModelBuilder addRelationship(NodeModelBuilder newStartNode, NodeModelBuilder newEndNode) {\n\t\treturn callOnlyWithoutJavaFilePresent(() -> {\n\t\t\tTypeName startNode = S;\n\t\t\tif (newStartNode != null) {\n\t\t\t\tstartNode = newStartNode.isExtensible() ? ParameterizedTypeName.get(extractClassName(newStartNode),\n\t\t\t\t\t\tWildcardTypeName.subtypeOf(Object.class)) : extractClassName(newStartNode);\n\t\t\t}\n\n\t\t\tTypeName endNode = E;\n\t\t\tif (newEndNode != null) {\n\t\t\t\tendNode = newEndNode.isExtensible() ? ParameterizedTypeName.get(extractClassName(newEndNode),\n\t\t\t\t\t\tWildcardTypeName.subtypeOf(Object.class)) : extractClassName(newEndNode);\n\t\t\t}\n\n\t\t\tthis.edges.add(new Edge(startNode, endNode));\n\t\t\treturn this;\n\t\t});\n\t}\n\n\tprivate MethodSpec buildCopyConstructor() {\n\n\t\tParameterSpec symbolicName = ParameterSpec.builder(TYPE_NAME_SYMBOLIC_NAME, \"symbolicName\").build();\n\t\tParameterSpec start = ParameterSpec.builder(TYPE_NAME_NODE, \"start\").build();\n\t\tParameterSpec properties = ParameterSpec.builder(ClassName.get(Properties.class), \"properties\").build();\n\t\tParameterSpec end = ParameterSpec.builder(TYPE_NAME_NODE, \"end\").build();\n\t\treturn MethodSpec.constructorBuilder()\n\t\t\t.addModifiers(Modifier.PRIVATE)\n\t\t\t.addParameters(Arrays.asList(symbolicName, start, properties, end))\n\t\t\t.addStatement(\"super($N, $N, $N, $N, $N)\", symbolicName, start, this.relationshipTypeField, properties, end)\n\t\t\t.build();\n\n\t}\n\n\tprivate MethodSpec buildNamedMethod(TypeName typeName) {\n\n\t\tParameterSpec newSymbolicName = ParameterSpec.builder(TYPE_NAME_SYMBOLIC_NAME, \"newSymbolicName\").build();\n\t\treturn MethodSpec.methodBuilder(\"named\")\n\t\t\t.addAnnotation(Override.class)\n\t\t\t.addModifiers(Modifier.PUBLIC)\n\t\t\t.returns(typeName)\n\t\t\t.addParameter(newSymbolicName)\n\t\t\t.addStatement(\"return new $T$L($N, getLeft(), getDetails().getProperties(), getRight())\", super.className,\n\t\t\t\t\t(typeName == super.className) ? \"\" : \"<>\", newSymbolicName)\n\t\t\t.build();\n\t}\n\n\tprivate MethodSpec buildWithPropertiesMethod(TypeName typeName) {\n\n\t\tParameterSpec newProperties = ParameterSpec.builder(TYPE_NAME_MAP_EXPRESSION, \"newProperties\").build();\n\t\treturn MethodSpec.methodBuilder(\"withProperties\")\n\t\t\t.addAnnotation(Override.class)\n\t\t\t.addModifiers(Modifier.PUBLIC)\n\t\t\t.returns(typeName)\n\t\t\t.addParameter(newProperties)\n\t\t\t.addStatement(\n\t\t\t\t\t\"return new $T$L(getSymbolicName().orElse(null), getLeft(), Properties.create($N), getRight())\",\n\t\t\t\t\tsuper.className, (typeName == super.className) ? \"\" : \"<>\", newProperties)\n\t\t\t.build();\n\t}\n\n\tprivate List<FieldSpec> buildFields() {\n\t\treturn Stream.concat(Stream.of(this.relationshipTypeField), generateFieldSpecsFromProperties()).toList();\n\t}\n\n\t@Override\n\tprotected JavaFile buildJavaFile() {\n\n\t\tvar expectedTypes = pickDefault(this.edges);\n\t\tvar builder = TypeSpec.classBuilder(super.className);\n\t\tvar typeName = getTypeName(expectedTypes);\n\t\tif (typeName instanceof ParameterizedTypeName pt) {\n\t\t\tfor (TypeName t : pt.typeArguments) {\n\t\t\t\tif (t instanceof TypeVariableName tn) {\n\t\t\t\t\tbuilder.addTypeVariable(tn);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\taddGenerated(builder)\n\t\t\t.superclass(ParameterizedTypeName.get(TYPE_NAME_RELATIONSHIP_BASE, expectedTypes.start, expectedTypes.end,\n\t\t\t\t\ttypeName))\n\t\t\t.addModifiers(Modifier.PUBLIC, Modifier.FINAL)\n\t\t\t.addFields(buildFields());\n\n\t\t(this.edges.isEmpty() ? Stream.of(new Edge(S, E)) : this.edges.stream())\n\t\t\t.map(relation -> buildConstructor(relation, expectedTypes))\n\t\t\t.forEach(builder::addMethod);\n\n\t\tvar newType = builder.addMethod(buildCopyConstructor())\n\t\t\t.addMethod(buildNamedMethod(typeName))\n\t\t\t.addMethod(buildWithPropertiesMethod(typeName))\n\t\t\t.build();\n\n\t\treturn prepareFileBuilder(newType).build();\n\t}\n\n\tprivate TypeName getTypeName(Edge expectedTypes) {\n\t\treturn getTypeName(expectedTypes, null, null);\n\t}\n\n\tTypeName getTypeName(TypeName concreteStartType, TypeName concreteEndType) {\n\t\treturn getTypeName(pickDefault(this.edges), concreteStartType, concreteEndType);\n\t}\n\n\tprivate TypeName getTypeName(Edge expectedEdge, TypeName concreteStartType, TypeName concreteEndType) {\n\n\t\tvar concreteOrDefaultStart = (concreteStartType != null) ? concreteStartType : S;\n\t\tvar concreteOrDefaultEnd = (concreteEndType != null) ? concreteEndType : E;\n\t\tif (expectedEdge.start == S && expectedEdge.end == E) {\n\t\t\treturn ParameterizedTypeName.get(super.className, concreteOrDefaultStart, concreteOrDefaultEnd);\n\t\t}\n\t\telse if (expectedEdge.start == S) {\n\t\t\treturn ParameterizedTypeName.get(super.className, concreteOrDefaultStart);\n\t\t}\n\t\telse if (expectedEdge.end == E) {\n\t\t\treturn ParameterizedTypeName.get(super.className, concreteOrDefaultEnd);\n\t\t}\n\t\telse {\n\t\t\treturn super.className;\n\t\t}\n\t}\n\n\tprivate static final class Edge {\n\n\t\tTypeName start;\n\n\t\tTypeName end;\n\n\t\tprivate Edge(TypeName start, TypeName end) {\n\t\t\tthis.start = start;\n\t\t\tthis.end = end;\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/RelationshipModelBuilder.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\n\nimport static org.apiguardian.api.API.Status.EXPERIMENTAL;\n\n/**\n * A variant of a {@link ModelBuilder} responsible for creating classes extending from\n * {@link RelationshipBase} that will in the end represent a static model of relationships\n * and their properties.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = EXPERIMENTAL, since = \"2021.1.0\")\npublic interface RelationshipModelBuilder extends ModelBuilder<RelationshipModelBuilder> {\n\n\t/**\n\t * Start building a new {@link RelationshipModelBuilder}.\n\t * @param configuration configuration of the generator\n\t * @param packageName the package name into the model should be generated\n\t * @param relationshipType the type of the relationship\n\t * @return the new builder\n\t */\n\tstatic RelationshipModelBuilder create(Configuration configuration, String packageName, String relationshipType) {\n\n\t\treturn create(configuration, packageName, relationshipType, null);\n\t}\n\n\t/**\n\t * Start building a new {@link RelationshipModelBuilder}, including alternate name\n\t * suggestions.\n\t * @param configuration configuration of the generator\n\t * @param packageName the package name into the model should be generated\n\t * @param relationshipType the type of the relationship\n\t * @param alternateClassNameSuggestion an alternative suggestion for the class name\n\t * @return the new builder\n\t */\n\tstatic RelationshipModelBuilder create(Configuration configuration, String packageName, String relationshipType,\n\t\t\tString alternateClassNameSuggestion) {\n\n\t\treturn RelationshipImplBuilder.create(configuration, packageName, relationshipType,\n\t\t\t\talternateClassNameSuggestion);\n\t}\n\n\t/**\n\t * Registers the start node of a relationship with this builder. Will add a new\n\t * relationship to this builder if none is present, will modify the last one if this\n\t * method or {@link #setEndNode(NodeModelBuilder)} or\n\t * {@link #addRelationship(NodeModelBuilder, NodeModelBuilder)} has already been used.\n\t * <p>\n\t * A wild card will be emitted for the generated class instead of a concrete class so\n\t * that this relationship model suites several different relationships with the same\n\t * type.\n\t * @param startNode the new start node, may be null\n\t * @return this builder\n\t * @throws IllegalStateException when this builder has already been used to create\n\t * Java class.\n\t */\n\tRelationshipModelBuilder setStartNode(NodeModelBuilder startNode);\n\n\t/**\n\t * Registers the end node of the relationship with this builder. Will add a new\n\t * relationship to this builder if none is present, will modify the last one if this\n\t * method or {@link #setStartNode(NodeModelBuilder)} or\n\t * {@link #addRelationship(NodeModelBuilder, NodeModelBuilder)} has already been used.\n\t * <p>\n\t * A wild card will be emitted for the generated class instead of a concrete class so\n\t * that this relationship model suites several different relationships with the same\n\t * type.\n\t * @param endNode the new start node, may be null\n\t * @return this builder\n\t * @throws IllegalStateException when this builder has already been used to create\n\t * Java class.\n\t */\n\tRelationshipModelBuilder setEndNode(NodeModelBuilder endNode);\n\n\t/**\n\t * Registers a relationship between start and end node with this builder.\n\t * @param startNode the new start node, may be null\n\t * @param endNode the new start node, may be null\n\t * @return this builder\n\t * @throws IllegalStateException when this builder has already been used to create\n\t * Java class.\n\t * @since 2023.9.0\n\t */\n\tRelationshipModelBuilder addRelationship(NodeModelBuilder startNode, NodeModelBuilder endNode);\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/RelationshipNameGenerator.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Default generator for creating names of relationship classes. It uses the given type as\n * class name, generates a valid type from it and then tries to derive a camel cased name.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = INTERNAL, since = \"2021.1.0\")\nfinal class RelationshipNameGenerator extends AbstractClassNameGenerator implements ClassNameGenerator {\n\n\t@Override\n\tpublic String generate(String suggestedName) {\n\n\t\tfinal StringBuilder sb = generateTypeName(suggestedName);\n\t\tint i = 0;\n\t\tint last = 0;\n\t\twhile (i <= sb.length()) {\n\t\t\tif (i == sb.length() || sb.charAt(i) == '_') {\n\t\t\t\tchar copy = sb.charAt(last);\n\t\t\t\tsb.setCharAt(last, Character.toUpperCase(sb.charAt(last)));\n\t\t\t\twhile (++last < i) {\n\t\t\t\t\tboolean flip = last + 1 == i && Character.isUpperCase(copy)\n\t\t\t\t\t\t\t|| last + 1 < i && Character.isUpperCase(sb.charAt(last + 1));\n\t\t\t\t\tcopy = sb.charAt(last);\n\t\t\t\t\tif (flip) {\n\t\t\t\t\t\tsb.setCharAt(last, Character.toLowerCase(sb.charAt(last)));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlast = i;\n\t\t\t}\n\t\t\tif (i != sb.length() && sb.charAt(i) == '_') {\n\t\t\t\tsb.deleteCharAt(i);\n\t\t\t}\n\t\t\t++i;\n\t\t}\n\n\t\treturn sb.toString();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/RelationshipPropertyDefinition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.EXPERIMENTAL;\n\n/**\n * This represents a property in the static metamodel for a relationship. Such a property\n * can refer to several other {@link PropertyDefinition property definitions} on its own\n * when we detect properties stored on the relationship.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = EXPERIMENTAL, since = \"2021.1.0\")\npublic final class RelationshipPropertyDefinition {\n\n\t/**\n\t * A set of properties to generate.\n\t */\n\tprivate final Set<PropertyDefinition> properties;\n\n\t/**\n\t * Relationship type as stored in the database.\n\t */\n\tprivate final String type;\n\n\tprivate final String optionalPropertyHolder;\n\n\t/**\n\t * Optional name in the domain, for example a field name.\n\t */\n\tprivate final String nameInDomain;\n\n\t/**\n\t * Start of the relationship. Generated, static relationships are always left to right\n\t * (start to end).\n\t */\n\tprivate final NodeModelBuilder start;\n\n\t/**\n\t * end of the relationship. Generated, static relationships are always left to right\n\t * (start to end).\n\t */\n\tprivate final NodeModelBuilder end;\n\n\t/**\n\t * The actual builder that defines this relationship.\n\t */\n\tprivate RelationshipModelBuilder relationshipBuilder;\n\n\tprivate RelationshipPropertyDefinition(String type, String optionalPropertyHolder, String nameInDomain,\n\t\t\tNodeModelBuilder start, RelationshipModelBuilder relationshipBuilder, NodeModelBuilder end,\n\t\t\tSet<PropertyDefinition> properties) {\n\t\tthis.type = type;\n\t\tthis.optionalPropertyHolder = optionalPropertyHolder;\n\t\tthis.nameInDomain = nameInDomain;\n\t\tthis.start = start;\n\t\tthis.end = end;\n\t\tthis.relationshipBuilder = relationshipBuilder;\n\t\tthis.properties = properties;\n\t}\n\n\t/**\n\t * Creates a new definition.\n\t * @param type the type of the relationship as stored in the database\n\t * @param optionalPropertyHolder the class name of the holder of the relationships\n\t * properties\n\t * @param nameInDomain the name of the relationship in the domain class\n\t * @param start builder for the start node in the domain\n\t * @param end builder for the end node in the domain\n\t * @param optionalProperties a collection of properties, maybe null or empty\n\t * @return a valid definition\n\t */\n\tpublic static RelationshipPropertyDefinition create(String type, String optionalPropertyHolder, String nameInDomain,\n\t\t\tNodeModelBuilder start, NodeModelBuilder end, Collection<PropertyDefinition> optionalProperties) {\n\n\t\treturn new RelationshipPropertyDefinition(type, optionalPropertyHolder, nameInDomain, start, null, end,\n\t\t\t\t(optionalProperties != null) ? new HashSet<>(optionalProperties) : Collections.emptySet());\n\t}\n\n\t/**\n\t * Creates a new relationship definition with a new builder for it.\n\t * @param newBuilder the new builder to use\n\t * @return a new instance, {@literal this} won't change\n\t */\n\tpublic RelationshipPropertyDefinition withBuilder(RelationshipModelBuilder newBuilder) {\n\t\treturn new RelationshipPropertyDefinition(this.type, this.optionalPropertyHolder, this.nameInDomain, this.start,\n\t\t\t\tnewBuilder, this.end, this.properties);\n\t}\n\n\t/**\n\t * {@return the type of the relationship}\n\t */\n\tpublic String getType() {\n\t\treturn this.type;\n\t}\n\n\t/**\n\t * Returns the name in the domain model (most likely the field name).\n\t * @return the name in the domain model\n\t */\n\tpublic String getNameInDomain() {\n\t\treturn this.nameInDomain;\n\t}\n\n\t/**\n\t * {@return a builder for the start node}\n\t */\n\tpublic NodeModelBuilder getStart() {\n\t\treturn this.start;\n\t}\n\n\t/**\n\t * {@return a builder for the end node}\n\t */\n\tpublic NodeModelBuilder getEnd() {\n\t\treturn this.end;\n\t}\n\n\tRelationshipModelBuilder getRelationshipBuilder() {\n\t\treturn this.relationshipBuilder;\n\t}\n\n\t/**\n\t * {@return a set of properties on this relationship}\n\t */\n\tpublic Set<PropertyDefinition> getProperties() {\n\t\treturn Collections.unmodifiableSet(this.properties);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/main/java/org/neo4j/cypherdsl/codegen/core/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Basic infrastructure for creating static metamodels based on the Cypher-DSL.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/test/java/org/neo4j/cypherdsl/codegen/core/ConfigurationTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport java.util.function.UnaryOperator;\n\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass ConfigurationTests {\n\n\t@Test // GH-829\n\tvoid fieldNameGeneratorShouldBeConfigurable() {\n\t\tConfiguration configuration = Configuration.newConfig().withFieldNameGenerator(name -> \"Wurst\" + name).build();\n\t\tassertThat(configuration.getConstantFieldNameGenerator().generate(\"salat\")).isEqualTo(\"Wurstsalat\");\n\t}\n\n\t@Nested\n\tclass TypeNameDecoratorTest {\n\n\t\t@Test\n\t\tvoid typeNameDecoratorShouldDefaultToIdentity() {\n\t\t\tConfiguration configuration = Configuration.newConfig().withSuffix(null).build();\n\t\t\tassertThat(configuration.getTypeNameDecorator()).isSameAs(UnaryOperator.identity());\n\t\t}\n\n\t\t@Test\n\t\tvoid prefixShouldBeApplied() {\n\t\t\tConfiguration configuration = Configuration.newConfig().withPrefix(\"p\").build();\n\t\t\tassertThat(configuration.getTypeNameDecorator().apply(\"v\")).isEqualTo(\"pv_\");\n\t\t}\n\n\t\t@Test\n\t\tvoid suffixShouldBeNullable() {\n\t\t\tConfiguration configuration = Configuration.newConfig().withPrefix(\"p\").withSuffix(null).build();\n\t\t\tassertThat(configuration.getTypeNameDecorator().apply(\"v\")).isEqualTo(\"pv\");\n\t\t}\n\n\t\t@Test\n\t\tvoid suffixShouldBeApplied() {\n\t\t\tConfiguration configuration = Configuration.newConfig().withSuffix(\"s\").build();\n\t\t\tassertThat(configuration.getTypeNameDecorator().apply(\"v\")).isEqualTo(\"vs\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/test/java/org/neo4j/cypherdsl/codegen/core/ConstantFieldNamingStrategyTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.CsvSource;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass ConstantFieldNamingStrategyTests {\n\n\t@ParameterizedTest\n\t@CsvSource({ \"aName, A_NAME\", \"AName, A_NAME\", \"BAZ_BAR, BAZ_BAR\", \"aName, A_NAME\",\n\t\t\t\"ANumberedNam3, A_NUMBERED_NAM_3\", \"Foo3Bar, FOO_3_BAR\", \"Foo3BaR, FOO_3_BA_R\", \"foo3BaR, FOO_3_BA_R\",\n\t\t\t\"🖖someThing, SOME_THING\", \"$someThing, $_SOME_THING\", \"$$some33Thing, $_$_SOME_3_3_THING\",\n\t\t\t\"🧐someThing✋x, SOME_THING_X\", \"🧐someThing✋✋X, SOME_THING_X\" })\n\tvoid toConstantFieldNameShouldWork(String name, String expectedEscapedName) {\n\n\t\tassertThat(FieldNameGenerator.Default.INSTANCE.generate(name)).isEqualTo(expectedEscapedName);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/test/java/org/neo4j/cypherdsl/codegen/core/ModelBuilderTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport java.io.File;\nimport java.net.URISyntaxException;\nimport java.util.List;\nimport java.util.Locale;\n\nimport com.google.testing.compile.CompilationSubject;\nimport com.google.testing.compile.Compiler;\nimport com.google.testing.compile.JavaFileObjects;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatThrownBy;\n\n/**\n * @author Andreas Berger\n */\nclass ModelBuilderTests {\n\n\t@Test\n\tvoid testGeneratingRelationWithMultipleStartAndEndNodes() {\n\t\tvar configuration = Configuration.newConfig().build();\n\t\tvar a = NodeModelBuilder.create(configuration, null, \"A\").addLabel(\"A\");\n\t\tvar b = NodeModelBuilder.create(configuration, null, \"B\").addLabel(\"B\").addLabel(\"X\");\n\t\tvar c = NodeModelBuilder.create(configuration, null, \"C\").addLabel(\"C\");\n\t\tvar rel = RelationshipModelBuilder.create(configuration, null, \"BELONGS_TO\")\n\t\t\t.addRelationship(a, b)\n\t\t\t.addRelationship(a, c)\n\t\t\t.addRelationship(c, b);\n\n\t\ta.addRelationshipDefinition(\n\t\t\t\tRelationshipPropertyDefinition.create(\"BELONGS_TO\", null, \"belongsTo\", a, b, null).withBuilder(rel))\n\t\t\t.addRelationshipFactory(RelationshipFactoryDefinition.create(\"belongsTo\", a, b).withBuilder(rel))\n\t\t\t.addRelationshipFactory(RelationshipFactoryDefinition.create(\"belongsTo\", a, c).withBuilder(rel));\n\n\t\tb.addRelationshipDefinition(\n\t\t\t\tRelationshipPropertyDefinition.create(\"BELONGS_TO\", null, \"belongsTo\", a, b, null).withBuilder(rel))\n\t\t\t.addRelationshipFactory(RelationshipFactoryDefinition.create(\"belongsTo\", a, b).withBuilder(rel));\n\n\t\tassertThat(a.writeToString()).isEqualTo(\"\"\"\n\t\t\t\timport java.util.List;\n\t\t\t\timport org.neo4j.cypherdsl.core.MapExpression;\n\t\t\t\timport org.neo4j.cypherdsl.core.NodeBase;\n\t\t\t\timport org.neo4j.cypherdsl.core.NodeLabel;\n\t\t\t\timport org.neo4j.cypherdsl.core.Properties;\n\t\t\t\timport org.neo4j.cypherdsl.core.SymbolicName;\n\n\t\t\t\t/**\n\t\t\t\t * This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\n\t\t\t\t */\n\t\t\t\tpublic final class A_ extends NodeBase<A_> {\n\t\t\t\t\tpublic static final String $PRIMARY_LABEL = \"A\";\n\n\t\t\t\t\tpublic static final A_ A = new A_();\n\n\t\t\t\t\tpublic final BelongsTo_<A_, B_> BELONGS_TO = new BelongsTo_<A_, B_>(this, B_.B);\n\n\t\t\t\t\tpublic A_() {\n\t\t\t\t\t\tsuper($PRIMARY_LABEL);\n\t\t\t\t\t}\n\n\t\t\t\t\tprivate A_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\t\t\t\t\tsuper(symbolicName, labels, properties);\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic A_ named(SymbolicName newSymbolicName) {\n\t\t\t\t\t\treturn new A_(newSymbolicName, getLabels(), getProperties());\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic A_ withProperties(MapExpression newProperties) {\n\t\t\t\t\t\treturn new A_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t\t\t\t\t}\n\n\t\t\t\t\tpublic BelongsTo_<A_, B_> belongsTo(B_ end) {\n\t\t\t\t\t\treturn new BelongsTo_<A_, B_>(this, end);\n\t\t\t\t\t}\n\n\t\t\t\t\tpublic BelongsTo_<A_, C_> belongsTo(C_ end) {\n\t\t\t\t\t\treturn new BelongsTo_<A_, C_>(this, end);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\"\"\");\n\n\t\tassertThat(b.writeToString()).isEqualTo(\"\"\"\n\t\t\t\timport java.util.List;\n\t\t\t\timport org.neo4j.cypherdsl.core.MapExpression;\n\t\t\t\timport org.neo4j.cypherdsl.core.NodeBase;\n\t\t\t\timport org.neo4j.cypherdsl.core.NodeLabel;\n\t\t\t\timport org.neo4j.cypherdsl.core.Properties;\n\t\t\t\timport org.neo4j.cypherdsl.core.SymbolicName;\n\n\t\t\t\t/**\n\t\t\t\t * This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\n\t\t\t\t */\n\t\t\t\tpublic final class B_ extends NodeBase<B_> {\n\t\t\t\t\tpublic static final String $PRIMARY_LABEL = \"B\";\n\n\t\t\t\t\tpublic static final B_ B = new B_();\n\n\t\t\t\t\tpublic final BelongsTo_<A_, B_> BELONGS_TO = new BelongsTo_<A_, B_>(A_.A, this);\n\n\t\t\t\t\tpublic B_() {\n\t\t\t\t\t\tsuper($PRIMARY_LABEL, \"X\");\n\t\t\t\t\t}\n\n\t\t\t\t\tprivate B_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\t\t\t\t\tsuper(symbolicName, labels, properties);\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic B_ named(SymbolicName newSymbolicName) {\n\t\t\t\t\t\treturn new B_(newSymbolicName, getLabels(), getProperties());\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic B_ withProperties(MapExpression newProperties) {\n\t\t\t\t\t\treturn new B_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t\t\t\t\t}\n\n\t\t\t\t\tpublic BelongsTo_<A_, B_> belongsTo(A_ start) {\n\t\t\t\t\t\treturn new BelongsTo_<A_, B_>(start, this);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\"\"\");\n\n\t\tassertThat(rel.writeToString()).isEqualTo(\n\t\t\t\t\"\"\"\n\t\t\t\t\t\timport org.neo4j.cypherdsl.core.MapExpression;\n\t\t\t\t\t\timport org.neo4j.cypherdsl.core.Node;\n\t\t\t\t\t\timport org.neo4j.cypherdsl.core.NodeBase;\n\t\t\t\t\t\timport org.neo4j.cypherdsl.core.Properties;\n\t\t\t\t\t\timport org.neo4j.cypherdsl.core.RelationshipBase;\n\t\t\t\t\t\timport org.neo4j.cypherdsl.core.SymbolicName;\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tpublic final class BelongsTo_<S extends NodeBase<?>, E extends NodeBase<?>> extends RelationshipBase<S, E, BelongsTo_<S, E>> {\n\t\t\t\t\t\t\tpublic static final String $TYPE = \"BELONGS_TO\";\n\n\t\t\t\t\t\t\tpublic BelongsTo_(A_ start, B_ end) {\n\t\t\t\t\t\t\t\tsuper((S) start, $TYPE, (E) end);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tpublic BelongsTo_(A_ start, C_ end) {\n\t\t\t\t\t\t\t\tsuper((S) start, $TYPE, (E) end);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tpublic BelongsTo_(C_ start, B_ end) {\n\t\t\t\t\t\t\t\tsuper((S) start, $TYPE, (E) end);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tprivate BelongsTo_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\t\t\t\t\t\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\tpublic BelongsTo_<S, E> named(SymbolicName newSymbolicName) {\n\t\t\t\t\t\t\t\treturn new BelongsTo_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\tpublic BelongsTo_<S, E> withProperties(MapExpression newProperties) {\n\t\t\t\t\t\t\t\treturn new BelongsTo_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\"\"\");\n\t}\n\n\t@Test\n\tvoid testConstructorsOfRelationsWithoutGeneric() {\n\t\tvar configuration = Configuration.newConfig().build();\n\t\tvar a = NodeModelBuilder.create(configuration, null, \"A\").addLabel(\"A\");\n\t\tvar b = NodeModelBuilder.create(configuration, null, \"B\").addLabel(\"B\");\n\n\t\tassertThat(RelationshipModelBuilder.create(configuration, null, \"BELONGS_TO\")\n\t\t\t.addRelationship(a, b)\n\t\t\t.writeToString()).isEqualTo(\n\t\t\t\t\t\"\"\"\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.MapExpression;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.Node;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.Properties;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.RelationshipBase;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.SymbolicName;\n\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tpublic final class BelongsTo_ extends RelationshipBase<A_, B_, BelongsTo_> {\n\t\t\t\t\t\t\t\tpublic static final String $TYPE = \"BELONGS_TO\";\n\n\t\t\t\t\t\t\t\tpublic BelongsTo_(A_ start, B_ end) {\n\t\t\t\t\t\t\t\t\tsuper(start, $TYPE, end);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tprivate BelongsTo_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\t\t\t\t\t\t\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\t\tpublic BelongsTo_ named(SymbolicName newSymbolicName) {\n\t\t\t\t\t\t\t\t\treturn new BelongsTo_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\t\tpublic BelongsTo_ withProperties(MapExpression newProperties) {\n\t\t\t\t\t\t\t\t\treturn new BelongsTo_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\"\"\");\n\t}\n\n\t@Test\n\tvoid testConstructorsOfRelationsWithEndNodeGeneric() {\n\t\tvar configuration = Configuration.newConfig().build();\n\t\tvar a = NodeModelBuilder.create(configuration, null, \"A\").addLabel(\"A\");\n\t\tvar b = NodeModelBuilder.create(configuration, null, \"B\").addLabel(\"B\");\n\t\tvar c = NodeModelBuilder.create(configuration, null, \"C\").addLabel(\"C\");\n\n\t\tassertThat(RelationshipModelBuilder.create(configuration, null, \"BELONGS_TO\")\n\t\t\t.addRelationship(a, b)\n\t\t\t.addRelationship(a, c)\n\t\t\t.writeToString()).isEqualTo(\n\t\t\t\t\t\"\"\"\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.MapExpression;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.Node;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.NodeBase;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.Properties;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.RelationshipBase;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.SymbolicName;\n\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tpublic final class BelongsTo_<E extends NodeBase<?>> extends RelationshipBase<A_, E, BelongsTo_<E>> {\n\t\t\t\t\t\t\t\tpublic static final String $TYPE = \"BELONGS_TO\";\n\n\t\t\t\t\t\t\t\tpublic BelongsTo_(A_ start, B_ end) {\n\t\t\t\t\t\t\t\t\tsuper(start, $TYPE, (E) end);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tpublic BelongsTo_(A_ start, C_ end) {\n\t\t\t\t\t\t\t\t\tsuper(start, $TYPE, (E) end);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tprivate BelongsTo_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\t\t\t\t\t\t\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\t\tpublic BelongsTo_<E> named(SymbolicName newSymbolicName) {\n\t\t\t\t\t\t\t\t\treturn new BelongsTo_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\t\tpublic BelongsTo_<E> withProperties(MapExpression newProperties) {\n\t\t\t\t\t\t\t\t\treturn new BelongsTo_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\"\"\");\n\t}\n\n\t@Test\n\tvoid testConstructorsOfRelationsWithStartNodeGeneric() {\n\t\tvar configuration = Configuration.newConfig().build();\n\t\tvar a = NodeModelBuilder.create(configuration, null, \"A\").addLabel(\"A\");\n\t\tvar b = NodeModelBuilder.create(configuration, null, \"B\").addLabel(\"B\");\n\t\tvar c = NodeModelBuilder.create(configuration, null, \"C\").addLabel(\"C\");\n\n\t\tassertThat(RelationshipModelBuilder.create(configuration, null, \"BELONGS_TO\")\n\t\t\t.addRelationship(a, b)\n\t\t\t.addRelationship(c, b)\n\t\t\t.writeToString()).isEqualTo(\n\t\t\t\t\t\"\"\"\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.MapExpression;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.Node;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.NodeBase;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.Properties;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.RelationshipBase;\n\t\t\t\t\t\t\timport org.neo4j.cypherdsl.core.SymbolicName;\n\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tpublic final class BelongsTo_<S extends NodeBase<?>> extends RelationshipBase<S, B_, BelongsTo_<S>> {\n\t\t\t\t\t\t\t\tpublic static final String $TYPE = \"BELONGS_TO\";\n\n\t\t\t\t\t\t\t\tpublic BelongsTo_(A_ start, B_ end) {\n\t\t\t\t\t\t\t\t\tsuper((S) start, $TYPE, end);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tpublic BelongsTo_(C_ start, B_ end) {\n\t\t\t\t\t\t\t\t\tsuper((S) start, $TYPE, end);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tprivate BelongsTo_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\t\t\t\t\t\t\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\t\tpublic BelongsTo_<S> named(SymbolicName newSymbolicName) {\n\t\t\t\t\t\t\t\t\treturn new BelongsTo_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\t\tpublic BelongsTo_<S> withProperties(MapExpression newProperties) {\n\t\t\t\t\t\t\t\t\treturn new BelongsTo_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\"\"\");\n\t}\n\n\t@Test\n\tvoid testGeneratingWithInheritance() {\n\t\tvar configuration = Configuration.newConfig().build();\n\t\tvar a = NodeModelBuilder.create(configuration, null, \"A\")\n\t\t\t.addLabel(\"A\")\n\t\t\t.addLabel(\"B\")\n\t\t\t.addProperty(\"foo\")\n\t\t\t.setExtensible(true);\n\n\t\tvar c = NodeModelBuilder.create(configuration, null, \"C\")\n\t\t\t.addLabel(\"C\")\n\t\t\t.addLabel(\"D\")\n\t\t\t.setBaseNodeModel(a)\n\t\t\t.addProperty(\"bar\");\n\n\t\tassertThat(a.writeToString()).isEqualTo(\n\t\t\t\t\"\"\"\n\t\t\t\t\t\timport java.util.Arrays;\n\t\t\t\t\t\timport java.util.List;\n\t\t\t\t\t\timport java.util.stream.Stream;\n\t\t\t\t\t\timport org.neo4j.cypherdsl.core.MapExpression;\n\t\t\t\t\t\timport org.neo4j.cypherdsl.core.NodeBase;\n\t\t\t\t\t\timport org.neo4j.cypherdsl.core.NodeLabel;\n\t\t\t\t\t\timport org.neo4j.cypherdsl.core.Properties;\n\t\t\t\t\t\timport org.neo4j.cypherdsl.core.Property;\n\t\t\t\t\t\timport org.neo4j.cypherdsl.core.SymbolicName;\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tpublic class A_<SELF extends A_<?>> extends NodeBase<SELF> {\n\t\t\t\t\t\t\tpublic static final String $PRIMARY_LABEL = \"A\";\n\n\t\t\t\t\t\t\tpublic static final A_<A_<?>> A = new A_<>();\n\n\t\t\t\t\t\t\tpublic final Property FOO = this.property(\"foo\").referencedAs(\"foo\");\n\n\t\t\t\t\t\t\tpublic A_() {\n\t\t\t\t\t\t\t\tsuper($PRIMARY_LABEL, \"B\");\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tprotected A_(String primaryLabel, String... additionalLabels) {\n\t\t\t\t\t\t\t\tsuper(primaryLabel, Stream.concat(Arrays.stream(additionalLabels), Stream.of($PRIMARY_LABEL, \"B\")).toArray(String[]::new));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tprotected A_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\t\t\t\t\t\t\tsuper(symbolicName, labels, properties);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t@SuppressWarnings(\"unchecked\")\n\t\t\t\t\t\t\tprotected SELF create(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\t\t\t\t\t\t\treturn (SELF) new A_<>(symbolicName, labels, properties);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\tpublic SELF named(SymbolicName newSymbolicName) {\n\t\t\t\t\t\t\t\treturn create(newSymbolicName, getLabels(), getProperties());\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\tpublic SELF withProperties(MapExpression newProperties) {\n\t\t\t\t\t\t\t\treturn create(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\"\"\");\n\n\t\tassertThat(c.writeToString()).isEqualTo(\"\"\"\n\t\t\t\timport java.util.List;\n\t\t\t\timport org.neo4j.cypherdsl.core.NodeLabel;\n\t\t\t\timport org.neo4j.cypherdsl.core.Properties;\n\t\t\t\timport org.neo4j.cypherdsl.core.Property;\n\t\t\t\timport org.neo4j.cypherdsl.core.SymbolicName;\n\n\t\t\t\t/**\n\t\t\t\t * This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\n\t\t\t\t */\n\t\t\t\tpublic final class C_ extends A_<C_> {\n\t\t\t\t\tpublic static final String $PRIMARY_LABEL = \"C\";\n\n\t\t\t\t\tpublic static final C_ C = new C_();\n\n\t\t\t\t\tpublic final Property BAR = this.property(\"bar\").referencedAs(\"bar\");\n\n\t\t\t\t\tpublic C_() {\n\t\t\t\t\t\tsuper($PRIMARY_LABEL, \"D\");\n\t\t\t\t\t}\n\n\t\t\t\t\tprivate C_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\t\t\t\t\tsuper(symbolicName, labels, properties);\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tprotected C_ create(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\t\t\t\t\treturn new C_(symbolicName, labels, properties);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\"\"\");\n\t}\n\n\t@Test\n\tvoid testThrowingErrorWhenExtendingNonExtensibleNode() {\n\t\tvar configuration = Configuration.newConfig().build();\n\t\tvar a = NodeModelBuilder.create(configuration, null, \"A\").addLabel(\"A\");\n\n\t\tvar c = NodeModelBuilder.create(configuration, null, \"C\").addLabel(\"C\").setBaseNodeModel(a);\n\n\t\t// test that exception is thrown\n\t\tassertThatThrownBy(c::writeToString).isInstanceOf(IllegalStateException.class)\n\t\t\t.hasMessage(\"Cannot extend non-extensible node A_\");\n\n\t}\n\n\t@Test // GH-970\n\tvoid modelBuilderMustProduceValidGenerics() throws URISyntaxException {\n\n\t\tvar configuration = Configuration.newConfig().withDefaultPackage(\"org.example\").build();\n\t\tvar foo = NodeModelBuilder.create(configuration, null, \"Foo\")\n\t\t\t.setExtensible(true)\n\t\t\t.addLabel(\"Foo\")\n\t\t\t.addProperty(\"prop1\");\n\t\tvar bar = NodeModelBuilder.create(configuration, null, \"Bar\").addLabel(\"Bar\").addProperty(\"prop2\");\n\t\tvar related = RelationshipModelBuilder.create(configuration, null, \"Related\").addRelationship(foo, bar);\n\n\t\tvar cp = new File(new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI())\n\t\t\t\t+ \"/../../../../neo4j-cypher-dsl/target/classes\");\n\t\tvar compilation = Compiler.javac()\n\t\t\t.withClasspath(List.of(cp))\n\t\t\t.compile(JavaFileObjects.forSourceLines(\"org.example.Foo_\", foo.writeToString()),\n\t\t\t\t\tJavaFileObjects.forSourceLines(\"org.example.Bar_\", bar.writeToString()),\n\t\t\t\t\tJavaFileObjects.forSourceLines(\"org.example.Related_\", related.writeToString()));\n\n\t\tCompilationSubject.assertThat(compilation).succeeded();\n\t\tvar warningsOtherThanApiGuardian = compilation.warnings()\n\t\t\t.stream()\n\t\t\t.filter(d -> !d.getMessage(Locale.ROOT).startsWith(\"unknown enum constant org.apiguardian.api.API.\"))\n\t\t\t.toList();\n\t\tassertThat(warningsOtherThanApiGuardian).isEmpty();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/test/java/org/neo4j/cypherdsl/codegen/core/NodeImplBuilderTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.CsvSource;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n *\n */\nclass NodeImplBuilderTests {\n\n\t@ParameterizedTest\n\t@CsvSource(nullValues = \"n/a\", value = { \"n/a,n/a\", \"foo, Foo\", \"fOo, FOo\", \"Foo, n/a\" })\n\tvoid capitalizeShouldWork(String in, String expected) {\n\n\t\tString result = NodeImplBuilder.capitalize(in);\n\t\tif (in == null) {\n\t\t\tassertThat(result).isNull();\n\t\t}\n\t\telse if (expected == null) {\n\t\t\tassertThat(result).isSameAs(in);\n\t\t}\n\t\telse {\n\t\t\tassertThat(result).isEqualTo(expected);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/test/java/org/neo4j/cypherdsl/codegen/core/NodeNameGeneratorTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass NodeNameGeneratorTests {\n\n\tprivate final NodeNameGenerator defaultStrategy = new NodeNameGenerator();\n\n\tstatic Stream<Arguments> suggestedAndEscapedNames() {\n\t\tStream.Builder<Arguments> arguments = Stream.builder();\n\t\tfor (String pair : new String[] { \"BAZ_BAR, BAZ_BAR\", \"aName, AName\", \"ANumberedNam3, ANumberedNam3\",\n\t\t\t\t\"Foo3Bar, Foo3Bar\", \"Foo3BaR, Foo3BaR\", \"foo3BaR, Foo3BaR\", \"🖖someThing, SomeThing\",\n\t\t\t\t\"$someThing, $someThing\", \"$$some33Thing, $$some33Thing\", \"🧐someThing✋x, SomeThingx\",\n\t\t\t\t\"🧐someThing✋✋X, SomeThingX\" }) {\n\t\t\tString[] suggestedAndExpectedName = pair.split(\",\");\n\t\t\targuments.add(Arguments.of(suggestedAndExpectedName[0].trim(), suggestedAndExpectedName[1].trim()));\n\t\t}\n\t\treturn arguments.build();\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource(\"suggestedAndEscapedNames\")\n\tvoid createTypeNameShouldWork(String name, String expectedEscapedName) {\n\n\t\tassertThat(this.defaultStrategy.generate(name)).isEqualTo(expectedEscapedName);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-core/src/test/java/org/neo4j/cypherdsl/codegen/core/RelationshipNameGeneratorTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.core;\n\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass RelationshipNameGeneratorTests {\n\n\tprivate final RelationshipNameGenerator defaultStrategy = new RelationshipNameGenerator();\n\n\tstatic Stream<Arguments> suggestedAndEscapedNames() {\n\t\tStream.Builder<Arguments> arguments = Stream.builder();\n\t\tfor (String pair : new String[] { \"BOR_BOR_B, BorBorB\", \"BAZ_BOR, BazBor\", \"aName, AName\",\n\t\t\t\t\"ANumberedNam3, ANumberedNam3\", \"Foo3Bar, Foo3Bar\", \"Foo3BaR, Foo3BaR\", \"foo3BaR, Foo3BaR\",\n\t\t\t\t\"🖖someThing, SomeThing\", \"$someThing, $someThing\", \"$$some33Thing, $$some33Thing\",\n\t\t\t\t\"🧐someThing✋x, SomeThingx\", \"🧐someThing✋✋X, SomeThingX\" }) {\n\t\t\tString[] suggestedAndExpectedName = pair.split(\",\");\n\t\t\targuments.add(Arguments.of(suggestedAndExpectedName[0].trim(), suggestedAndExpectedName[1].trim()));\n\t\t}\n\t\treturn arguments.build();\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource(\"suggestedAndEscapedNames\")\n\tvoid createTypeNameShouldWork(String name, String expectedEscapedName) {\n\n\t\tassertThat(this.defaultStrategy.generate(name)).isEqualTo(expectedEscapedName);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-codegen</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-codegen-ogm</artifactId>\n\t<name>Code Generator (Neo4j-OGM)</name>\n\t<description>Annotation processor reading Neo4j-OGM annotations and creating a static model of them.</description>\n\n\t<properties>\n\t\t<java-module-name>org.neo4j.cypherdsl.codegen.ogm</java-module-name>\n\t\t<sonar.coverage.jacoco.xmlReportPaths>${basedir}/../../${aggregate.report.dir}</sonar.coverage.jacoco.xmlReportPaths>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl-codegen-core</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-ogm-core</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.google.testing.compile</groupId>\n\t\t\t<artifactId>compile-testing</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.assertj</groupId>\n\t\t\t<artifactId>assertj-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.junit.vintage</groupId>\n\t\t\t<artifactId>junit-vintage-engine</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<testResources>\n\t\t\t<testResource>\n\t\t\t\t<!-- We add the classes as resources. We could have them directly in resources, but than we would miss compile time safety on them -->\n\t\t\t\t<directory>src/test/java</directory>\n\t\t\t\t<includes>\n\t\t\t\t\t<include>org/neo4j/cypherdsl/codegen/ogm/models/**/*.java</include>\n\t\t\t\t</includes>\n\t\t\t</testResource>\n\t\t\t<testResource>\n\t\t\t\t<directory>src/test/resources</directory>\n\t\t\t</testResource>\n\t\t</testResources>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<!-- Massage the Java compiler so that it trusts us what we are doing with jdk modules -->\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<argLine>@{argLine}\n\t\t\t\t\t\t--add-opens jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED\n\t\t\t\t\t\t--add-opens jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED\n\t\t\t\t\t\t--add-opens jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED\n\t\t\t\t\t\t--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED\n\t\t\t\t\t\t--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED\n\t\t\t\t\t\t--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</argLine>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<!--\n\t\t\t\t| Disable processors, otherwise Javac would already find our processors while compiling them and end up with\n\t\t\t\t| \"Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing.Processor: Provider org.neo4j.cypherdsl.codegen.neo4j.SDN6AnnotationProcessor not found\"\n\t\t\t\t-->\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<compilerArgument>-proc:none</compilerArgument>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-jar-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<archive>\n\t\t\t\t\t\t<manifestEntries>\n\t\t\t\t\t\t\t<Automatic-Module-Name>${java-module-name}</Automatic-Module-Name>\n\t\t\t\t\t\t</manifestEntries>\n\t\t\t\t\t</archive>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/main/java/org/neo4j/cypherdsl/codegen/ogm/OGMAnnotationProcessor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm;\n\nimport java.io.IOException;\nimport java.util.AbstractMap;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.EnumMap;\nimport java.util.HashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.function.Consumer;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\nimport javax.annotation.processing.ProcessingEnvironment;\nimport javax.annotation.processing.RoundEnvironment;\nimport javax.annotation.processing.SupportedAnnotationTypes;\nimport javax.annotation.processing.SupportedOptions;\nimport javax.lang.model.element.AnnotationMirror;\nimport javax.lang.model.element.AnnotationValue;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.RecordComponentElement;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.element.VariableElement;\nimport javax.lang.model.type.DeclaredType;\nimport javax.lang.model.type.TypeMirror;\nimport javax.lang.model.util.ElementKindVisitor8;\nimport javax.lang.model.util.Elements;\nimport javax.lang.model.util.SimpleTypeVisitor8;\nimport javax.lang.model.util.TypeKindVisitor8;\nimport javax.tools.Diagnostic;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.codegen.core.AbstractMappingAnnotationProcessor;\nimport org.neo4j.cypherdsl.codegen.core.Configuration;\nimport org.neo4j.cypherdsl.codegen.core.ModelBuilder;\nimport org.neo4j.cypherdsl.codegen.core.NodeModelBuilder;\nimport org.neo4j.cypherdsl.codegen.core.PropertyDefinition;\nimport org.neo4j.cypherdsl.codegen.core.RelationshipModelBuilder;\nimport org.neo4j.cypherdsl.codegen.core.RelationshipPropertyDefinition;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Property;\nimport org.neo4j.ogm.annotation.Relationship;\nimport org.neo4j.ogm.annotation.RelationshipEntity;\n\nimport static org.apiguardian.api.API.Status.EXPERIMENTAL;\n\n/**\n * This processor works on Neo4j-OGM annotations and creates a static metamodel based on\n * CypherDSL for those classes.\n *\n * @author Shinigami92 (Christopher Quadflieg)\n * @author Michael J. Simons\n * @since 2025.0.0\n */\n@API(status = EXPERIMENTAL, since = \"2025.0.0\")\n@SupportedAnnotationTypes({ OGMAnnotationProcessor.NODE_ENTITY_ANNOTATION,\n\t\tOGMAnnotationProcessor.RELATIONSHIP_ENTITY_ANNOTATION })\n@SupportedOptions({ Configuration.PROPERTY_PREFIX, Configuration.PROPERTY_SUFFIX, Configuration.PROPERTY_INDENT_STYLE,\n\t\tConfiguration.PROPERTY_INDENT_SIZE, Configuration.PROPERTY_TIMESTAMP, Configuration.PROPERTY_ADD_AT_GENERATED,\n\t\tConfiguration.PROPERTY_EXCLUDES })\npublic final class OGMAnnotationProcessor extends AbstractMappingAnnotationProcessor {\n\n\tstatic final String NODE_ENTITY_ANNOTATION = \"org.neo4j.ogm.annotation.NodeEntity\";\n\tstatic final String RELATIONSHIP_ENTITY_ANNOTATION = \"org.neo4j.ogm.annotation.RelationshipEntity\";\n\tstatic final Set<String> VALID_GENERATED_ID_TYPES = Set.of(Long.class.getName(), long.class.getName());\n\n\tprivate final List<TypeElement> convertAnnotationTypes = new ArrayList<>();\n\n\tprivate TypeElement propertyAnnotationType;\n\n\tprivate TypeElement nodeEntityAnnotationType;\n\n\tprivate TypeElement relationshipEntityAnnotationType;\n\n\tprivate TypeElement relationshipAnnotationType;\n\n\tprivate TypeElement startNodeAnnotationType;\n\n\tprivate TypeElement endNodeAnnotationType;\n\n\tprivate TypeElement ogmIdAnnotationType;\n\n\tprivate TypeElement generatedValueAnnotationType;\n\n\tprivate static boolean declaredTypeContains(DeclaredType dt, Element annotatedEntity) {\n\t\t// Single field\n\t\tif (dt.equals(annotatedEntity.asType())) {\n\t\t\treturn true;\n\t\t}\n\t\telse {\n\t\t\t// Treating anything that has a generic type argument for a collection shaped\n\t\t\t// thing\n\t\t\t// Most other mappings with OGM won't work anyhow, so this is good enough for\n\t\t\t// now\n\t\t\tfor (var typeArgument : dt.getTypeArguments()) {\n\t\t\t\tif (typeArgument.equals(annotatedEntity.asType())) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void initFrameworkSpecific(ProcessingEnvironment processingEnv) {\n\n\t\tElements elementUtils = processingEnv.getElementUtils();\n\t\tthis.nodeEntityAnnotationType = elementUtils.getTypeElement(NODE_ENTITY_ANNOTATION);\n\t\tthis.relationshipEntityAnnotationType = elementUtils.getTypeElement(RELATIONSHIP_ENTITY_ANNOTATION);\n\n\t\tthis.relationshipAnnotationType = elementUtils.getTypeElement(\"org.neo4j.ogm.annotation.Relationship\");\n\t\tthis.startNodeAnnotationType = elementUtils.getTypeElement(\"org.neo4j.ogm.annotation.StartNode\");\n\t\tthis.endNodeAnnotationType = elementUtils.getTypeElement(\"org.neo4j.ogm.annotation.EndNode\");\n\t\tfor (var name : List.of(\"Convert\", \"DateLong\", \"DateString\", \"EnumString\", \"NumberString\")) {\n\t\t\tthis.convertAnnotationTypes\n\t\t\t\t.add(elementUtils.getTypeElement(\"org.neo4j.ogm.annotation.typeconversion.%s\".formatted(name)));\n\t\t}\n\t\tthis.propertyAnnotationType = elementUtils.getTypeElement(\"org.neo4j.ogm.annotation.Property\");\n\n\t\tthis.ogmIdAnnotationType = elementUtils.getTypeElement(\"org.neo4j.ogm.annotation.Id\");\n\t\tthis.generatedValueAnnotationType = elementUtils.getTypeElement(\"org.neo4j.ogm.annotation.GeneratedValue\");\n\t}\n\n\t@Override\n\tprotected Collection<String> getLabel(TypeElement annotatedClass) {\n\t\tNodeEntity nodeAnnotation = annotatedClass.getAnnotation(NodeEntity.class);\n\t\tSet<String> labels = new LinkedHashSet<>();\n\t\tConsumer<String> addLabel = label -> {\n\t\t\tif (!label.isEmpty()) {\n\t\t\t\tlabels.add(label);\n\t\t\t}\n\t\t};\n\t\taddLabel.accept(nodeAnnotation.label());\n\t\taddLabel.accept(nodeAnnotation.value());\n\n\t\tif (labels.isEmpty()) {\n\t\t\taddLabel.accept(annotatedClass.getSimpleName().toString());\n\t\t}\n\t\treturn Collections.unmodifiableCollection(labels);\n\t}\n\n\t@Override\n\tpublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {\n\t\tif (annotations.isEmpty()) {\n\t\t\treturn false;\n\t\t}\n\n\t\tMap<TypeElement, NodeModelBuilder> nodeBuilders = populateListOfNodes(\n\t\t\t\tgetTypesAnnotatedWith(this.nodeEntityAnnotationType, roundEnv));\n\t\tMap<NodeModelBuilder, List<Element>> relationshipFields = populateNodePropertiesAndCollectRelationshipFields(\n\t\t\t\tnodeBuilders);\n\t\tMap<TypeElement, Map.Entry<TypeElement, List<PropertyDefinition>>> relationshipProperties = collectRelationshipProperties(\n\t\t\t\trelationshipFields, roundEnv);\n\t\tMap<String, List<RelationshipModelBuilder>> relationshipBuilders = populateListOfRelationships(\n\t\t\t\tcomputeRelationshipDefinitions(relationshipFields, relationshipProperties, nodeBuilders));\n\n\t\tList<ModelBuilder<?>> allBuilders = new ArrayList<>(nodeBuilders.values());\n\t\trelationshipBuilders.values().forEach(allBuilders::addAll);\n\t\ttry {\n\t\t\twriteSourceFiles(allBuilders);\n\t\t}\n\t\tcatch (IOException ex) {\n\t\t\tthis.messager.printMessage(Diagnostic.Kind.ERROR, \"Could not write source files: \" + ex.getMessage());\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate String getRelationshipEntityType(Element annotatedEntity) {\n\n\t\tvar relationshipEntity = annotatedEntity.getAnnotation(RelationshipEntity.class);\n\t\tif (relationshipEntity == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tString typeValue = relationshipEntity.type();\n\t\tString valueValue = relationshipEntity.value();\n\t\tString relationshipType = null;\n\n\t\tif (!typeValue.isEmpty() && !valueValue.isEmpty()) {\n\t\t\tif (!typeValue.equals(valueValue)) {\n\t\t\t\tthis.messager.printMessage(Diagnostic.Kind.ERROR,\n\t\t\t\t\t\t\"Different @AliasFor mirror values for annotation [org.neo4j.ogm.annotation.RelationshipEntity]!\",\n\t\t\t\t\t\tannotatedEntity);\n\t\t\t}\n\t\t\trelationshipType = typeValue;\n\t\t}\n\t\telse if (!typeValue.isEmpty()) {\n\t\t\trelationshipType = typeValue;\n\t\t}\n\t\telse if (!valueValue.isEmpty()) {\n\t\t\trelationshipType = valueValue;\n\t\t}\n\t\treturn relationshipType;\n\t}\n\n\t// Tries to figure out the direction of this relationship, so that we can decide on\n\t// how to treat start/end nodes\n\tprivate Optional<Relationship.Direction> findDirection(Element annotatedEntity, Element startElement,\n\t\t\tSet<Element> allRelationshipFields) {\n\n\t\treturn allRelationshipFields.stream().filter(element -> {\n\n\t\t\t// The enclosing field must be of the same type as the startElement\n\t\t\tif (!element.getEnclosingElement().asType().equals(startElement.asType())) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Get the type\n\t\t\tif (element.asType() instanceof DeclaredType dt) {\n\t\t\t\treturn declaredTypeContains(dt, annotatedEntity);\n\t\t\t}\n\t\t\treturn false;\n\t\t}).map(element -> {\n\t\t\tvar relationship = element.getAnnotation(Relationship.class);\n\t\t\treturn (relationship != null) ? relationship.direction() : Relationship.Direction.OUTGOING;\n\t\t}).findFirst();\n\n\t}\n\n\tprivate Map<TypeElement, Map.Entry<TypeElement, List<PropertyDefinition>>> collectRelationshipProperties(\n\t\t\tMap<NodeModelBuilder, List<Element>> relationshipFields, RoundEnvironment roundEnvironment) {\n\n\t\tvar allRelationshipFields = relationshipFields.values()\n\t\t\t.stream()\n\t\t\t.flatMap(List::stream)\n\t\t\t.collect(Collectors.toSet());\n\n\t\tMap<TypeElement, Map.Entry<TypeElement, List<PropertyDefinition>>> result = new HashMap<>();\n\t\tSet<TypeElement> annotatedEntities = getTypesAnnotatedWith(this.relationshipEntityAnnotationType,\n\t\t\t\troundEnvironment);\n\t\tannotatedEntities.forEach(annotatedEntity -> {\n\n\t\t\tList<PropertyDefinition> properties = new ArrayList<>();\n\t\t\tElement startElement = null;\n\t\t\tElement endElement = null;\n\t\t\tfor (Element enclosedElement : annotatedEntity.getEnclosedElements()) {\n\n\t\t\t\tif (!enclosedElement.getKind().isField()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tSet<Element> declaredAnnotations = enclosedElement.getAnnotationMirrors()\n\t\t\t\t\t.stream()\n\t\t\t\t\t.map(AnnotationMirror::getAnnotationType)\n\t\t\t\t\t.map(DeclaredType::asElement)\n\t\t\t\t\t.collect(Collectors.toSet());\n\n\t\t\t\tif (declaredAnnotations.contains(this.startNodeAnnotationType)) {\n\t\t\t\t\tstartElement = enclosedElement;\n\t\t\t\t}\n\t\t\t\telse if (declaredAnnotations.contains(this.endNodeAnnotationType)) {\n\t\t\t\t\tendElement = enclosedElement;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tproperties.add(asPropertyDefinition(enclosedElement));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tTypeElement actualTargetType = null;\n\t\t\tElement relationshipDefiningElement = null;\n\t\t\tif (startElement != null && endElement != null) {\n\t\t\t\tvar finalEndElement = endElement;\n\t\t\t\tvar direction = findDirection(annotatedEntity, startElement, allRelationshipFields)\n\t\t\t\t\t.or(() -> findDirection(annotatedEntity, finalEndElement, allRelationshipFields))\n\t\t\t\t\t.orElse(Relationship.Direction.OUTGOING);\n\n\t\t\t\trelationshipDefiningElement = (direction != Relationship.Direction.OUTGOING) ? startElement\n\t\t\t\t\t\t: endElement;\n\t\t\t}\n\t\t\telse if (startElement != null) {\n\t\t\t\trelationshipDefiningElement = startElement;\n\t\t\t}\n\t\t\telse if (endElement != null) {\n\t\t\t\trelationshipDefiningElement = endElement;\n\t\t\t}\n\n\t\t\tif (relationshipDefiningElement != null) {\n\t\t\t\tactualTargetType = this.typeUtils.asElement(relationshipDefiningElement.asType())\n\t\t\t\t\t.accept(new TypeElementVisitor<>(Function.identity()), null);\n\t\t\t\tif (actualTargetType == null) {\n\t\t\t\t\tthis.messager.printMessage(Diagnostic.Kind.WARNING,\n\t\t\t\t\t\t\t\"Cannot resolve generic type, not generating a property for relationships referring to \"\n\t\t\t\t\t\t\t\t\t+ annotatedEntity.getQualifiedName(),\n\t\t\t\t\t\t\trelationshipDefiningElement);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (actualTargetType != null) {\n\t\t\t\tresult.put(annotatedEntity,\n\t\t\t\t\t\tnew AbstractMap.SimpleEntry<>(actualTargetType, Collections.unmodifiableList(properties)));\n\t\t\t}\n\t\t});\n\t\treturn Collections.unmodifiableMap(result);\n\t}\n\n\t@Override\n\tprotected PropertyDefinition asPropertyDefinition(Element e) {\n\t\tOptional<Property> optionalPropertyAnnotation = Optional.ofNullable(e.getAnnotation(Property.class));\n\n\t\tPropertyDefinition propertyDefinition;\n\t\tString fieldName = e.getSimpleName().toString();\n\n\t\tif (optionalPropertyAnnotation.isPresent()) {\n\t\t\tProperty propertyAnnotation = optionalPropertyAnnotation.get();\n\n\t\t\tString nameValue = propertyAnnotation.name();\n\t\t\tString valueValue = propertyAnnotation.value();\n\n\t\t\tif (!nameValue.isEmpty() && !valueValue.isEmpty()) {\n\t\t\t\tif (!nameValue.equals(valueValue)) {\n\t\t\t\t\tthis.messager.printMessage(Diagnostic.Kind.ERROR,\n\t\t\t\t\t\t\t\"Different @AliasFor mirror values for annotation [org.neo4j.ogm.annotation.Property]!\", e);\n\t\t\t\t}\n\t\t\t\tpropertyDefinition = PropertyDefinition.create(nameValue, fieldName);\n\t\t\t}\n\t\t\telse if (!nameValue.isEmpty()) {\n\t\t\t\tpropertyDefinition = PropertyDefinition.create(nameValue, fieldName);\n\t\t\t}\n\t\t\telse if (!valueValue.isEmpty()) {\n\t\t\t\tpropertyDefinition = PropertyDefinition.create(valueValue, fieldName);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpropertyDefinition = PropertyDefinition.create(fieldName, null);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tpropertyDefinition = PropertyDefinition.create(fieldName, null);\n\t\t}\n\n\t\treturn propertyDefinition;\n\t}\n\n\t@Override\n\tprotected RelationshipPropertyDefinition asRelationshipDefinition(NodeModelBuilder owner, Element e,\n\t\t\tMap<TypeElement, Map.Entry<TypeElement, List<PropertyDefinition>>> relationshipProperties,\n\t\t\tMap<TypeElement, NodeModelBuilder> nodeBuilders) {\n\t\tOptional<Relationship> optionalRelationshipAnnotation = Optional\n\t\t\t.ofNullable(e.getAnnotation(Relationship.class));\n\n\t\tString fieldName = e.getSimpleName().toString();\n\n\t\t// Default Relationship#direction is outgoing.\n\t\tboolean isIncoming = false;\n\n\t\tString relationshipType;\n\t\tif (optionalRelationshipAnnotation.isPresent()) {\n\t\t\tRelationship relationshipAnnotation = optionalRelationshipAnnotation.get();\n\n\t\t\tString typeValue = relationshipAnnotation.type();\n\t\t\tString valueValue = relationshipAnnotation.value();\n\n\t\t\tisIncoming = relationshipAnnotation.direction() == Relationship.Direction.INCOMING;\n\n\t\t\tif (!typeValue.isEmpty() && !valueValue.isEmpty()) {\n\t\t\t\tif (!typeValue.equals(valueValue)) {\n\t\t\t\t\tthis.messager.printMessage(Diagnostic.Kind.ERROR,\n\t\t\t\t\t\t\t\"Different @AliasFor mirror values for annotation [org.neo4j.ogm.annotation.Relationship]!\",\n\t\t\t\t\t\t\te);\n\t\t\t\t}\n\t\t\t\trelationshipType = typeValue;\n\t\t\t}\n\t\t\telse if (!typeValue.isEmpty()) {\n\t\t\t\trelationshipType = typeValue;\n\t\t\t}\n\t\t\telse if (!valueValue.isEmpty()) {\n\t\t\t\trelationshipType = valueValue;\n\t\t\t}\n\t\t\telse {\n\t\t\t\trelationshipType = fieldName;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\trelationshipType = fieldName;\n\t\t}\n\n\t\tDeclaredType declaredType = e.asType().accept(new SimpleTypeVisitor8<DeclaredType, Void>() {\n\t\t\t@Override\n\t\t\tpublic DeclaredType visitDeclared(DeclaredType t, Void unused) {\n\t\t\t\treturn t;\n\t\t\t}\n\t\t}, null);\n\n\t\tif (declaredType == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tTypeMirror relatedType = null;\n\t\tif (declaredType.getTypeArguments().size() == 1) {\n\t\t\trelatedType = declaredType.getTypeArguments().get(0);\n\t\t}\n\t\telse if (declaredType.getTypeArguments().isEmpty()) {\n\t\t\trelatedType = declaredType;\n\t\t}\n\n\t\tElement key = this.typeUtils.asElement(relatedType);\n\t\tNodeModelBuilder end = (key != null) ? nodeBuilders.get(key) : null;\n\t\tList<PropertyDefinition> properties = null;\n\t\tString optionalPropertyHolder = null;\n\n\t\tif (key == null) {\n\t\t\treturn null;\n\t\t}\n\t\telse if (end == null) {\n\t\t\tMap.Entry<TypeElement, List<PropertyDefinition>> typeAndProperties = relationshipProperties.get(key);\n\t\t\tif (typeAndProperties != null) {\n\t\t\t\toptionalPropertyHolder = key.toString();\n\t\t\t\tend = nodeBuilders.get(typeAndProperties.getKey());\n\t\t\t\tproperties = typeAndProperties.getValue();\n\t\t\t}\n\t\t}\n\n\t\tif (end == null) {\n\t\t\treturn null;\n\t\t}\n\t\telse if (isIncoming) {\n\t\t\treturn RelationshipPropertyDefinition.create(relationshipType, optionalPropertyHolder, fieldName, end,\n\t\t\t\t\towner, properties);\n\t\t}\n\t\telse {\n\t\t\treturn RelationshipPropertyDefinition.create(relationshipType, optionalPropertyHolder, fieldName, owner,\n\t\t\t\t\tend, properties);\n\t\t}\n\t}\n\n\t@Override\n\tprotected PropertiesAndRelationshipGrouping newPropertiesAndRelationshipGrouping() {\n\t\treturn new GroupPropertiesAndRelationships();\n\t}\n\n\t/**\n\t * Pre-groups fields into properties and relationships to avoid running the\n\t * association check multiple times.\n\t */\n\t// Silence Sonar complaining about the class hierarchy, which is given through\n\t// the ElementKindVisitor8, which we need but cannot change\n\t@SuppressWarnings(\"squid:S110\")\n\tclass GroupPropertiesAndRelationships extends ElementKindVisitor8<Map<FieldType, List<Element>>, Void>\n\t\t\timplements PropertiesAndRelationshipGrouping {\n\n\t\tprivate final Map<FieldType, List<Element>> result;\n\n\t\tGroupPropertiesAndRelationships() {\n\n\t\t\tfinal Map<FieldType, List<Element>> hlp = new EnumMap<>(FieldType.class);\n\t\t\thlp.put(FieldType.R, new ArrayList<>());\n\t\t\thlp.put(FieldType.P, new ArrayList<>());\n\t\t\tthis.result = Collections.unmodifiableMap(hlp);\n\t\t}\n\n\t\t@Override\n\t\tpublic void apply(Element element) {\n\t\t\telement.accept(this, null);\n\t\t}\n\n\t\t@Override\n\t\tpublic Map<FieldType, List<Element>> getResult() {\n\t\t\treturn this.result;\n\t\t}\n\n\t\t@Override\n\t\tpublic Map<FieldType, List<Element>> visitTypeAsRecord(TypeElement e, Void unused) {\n\t\t\t// We must overwrite this or visitUnknown() in case we encounter a record\n\t\t\treturn this.result;\n\t\t}\n\n\t\t@Override\n\t\tpublic Map<FieldType, List<Element>> visitRecordComponent(RecordComponentElement e, Void unused) {\n\t\t\treturn visitFieldOrRecordComponent(e);\n\t\t}\n\n\t\t@Override\n\t\tpublic Map<FieldType, List<Element>> visitVariableAsField(VariableElement e, Void unused) {\n\t\t\treturn visitFieldOrRecordComponent(e);\n\t\t}\n\n\t\tprivate Map<FieldType, List<Element>> visitFieldOrRecordComponent(Element e) {\n\t\t\tSet<Element> declaredAnnotations = e.getAnnotationMirrors()\n\t\t\t\t.stream()\n\t\t\t\t.map(AnnotationMirror::getAnnotationType)\n\t\t\t\t.map(DeclaredType::asElement)\n\t\t\t\t.collect(Collectors.toSet());\n\n\t\t\t// Skip internal ids\n\t\t\tif (isInternalId(e, declaredAnnotations)) {\n\t\t\t\treturn this.result;\n\t\t\t}\n\n\t\t\tthis.result.get(isAssociation(declaredAnnotations, e) ? FieldType.R : FieldType.P).add(e);\n\t\t\treturn this.result;\n\t\t}\n\n\t\tprivate boolean isInternalId(Element e, Set<Element> declaredAnnotations) {\n\n\t\t\tboolean idAnnotationPresent = declaredAnnotations.contains(OGMAnnotationProcessor.this.ogmIdAnnotationType);\n\t\t\tif (!idAnnotationPresent) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn e.getAnnotationMirrors()\n\t\t\t\t.stream()\n\t\t\t\t.filter(m -> m.getAnnotationType()\n\t\t\t\t\t.asElement()\n\t\t\t\t\t.equals(OGMAnnotationProcessor.this.generatedValueAnnotationType))\n\t\t\t\t.findFirst()\n\t\t\t\t.map(generatedValue -> isUsingInternalIdGenerator(e, generatedValue))\n\t\t\t\t.orElse(false);\n\t\t}\n\n\t\tprivate boolean isUsingInternalIdGenerator(Element e, AnnotationMirror generatedValue) {\n\n\t\t\tMap<String, ? extends AnnotationValue> values = generatedValue.getElementValues()\n\t\t\t\t.entrySet()\n\t\t\t\t.stream()\n\t\t\t\t.collect(Collectors.toMap(entry -> entry.getKey().getSimpleName().toString(), Map.Entry::getValue));\n\n\t\t\tDeclaredType generatorClassValue = values.containsKey(\"strategy\")\n\t\t\t\t\t? (DeclaredType) values.get(\"strategy\").getValue() : null;\n\n\t\t\tString name = null;\n\t\t\tif (generatorClassValue != null) {\n\t\t\t\tname = generatorClassValue.toString();\n\t\t\t}\n\n\t\t\t// The defaults will not be materialized\n\t\t\treturn (name == null || \"org.neo4j.ogm.id.InternalIdStrategy\".equals(name))\n\t\t\t\t\t&& VALID_GENERATED_ID_TYPES.contains(e.asType().toString());\n\t\t}\n\n\t\t/**\n\t\t * Returns true if this field is an association.\n\t\t * @param declaredAnnotations the declared annotations on this field\n\t\t * @param field a variable element describing a field. No further checks done if\n\t\t * this is true or not\n\t\t * @return true if this field is an association\n\t\t */\n\t\tprivate boolean isAssociation(Set<Element> declaredAnnotations, Element field) {\n\t\t\tTypeMirror typeMirrorOfField = field.asType();\n\n\t\t\tif (declaredAnnotations.contains(OGMAnnotationProcessor.this.relationshipAnnotationType)) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (declaredAnnotations.contains(OGMAnnotationProcessor.this.propertyAnnotationType)) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// They will be converted anyway\n\t\t\tif (describesEnum(typeMirrorOfField)) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Strings, primitives and their boxed variants are never associations\n\t\t\tif (typeMirrorOfField.getKind().isPrimitive()) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tvar type = typeMirrorOfField.accept(new TypeKindVisitor8<>() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic String visitDeclared(DeclaredType t, Object o) {\n\t\t\t\t\t\treturn t.asElement().accept(new TypeElementVisitor<>(newTypeElementNameFunction()), null);\n\t\t\t\t\t}\n\t\t\t\t}, null);\n\t\t\t\tif (\"java.lang.String\".equals(type)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tOGMAnnotationProcessor.this.typeUtils.unboxedType(typeMirrorOfField);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tcatch (IllegalArgumentException ex) {\n\t\t\t\t\t// Exception driven development for the win, yeah\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Stuff that is explicitly converted can't be an association either\n\t\t\tfor (var converterAnnotation : OGMAnnotationProcessor.this.convertAnnotationTypes) {\n\t\t\t\tif (declaredAnnotations.contains(converterAnnotation)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Unless it is a start / end node, it is by a big chance an implicit\n\t\t\t// relationship and hence, an association\n\t\t\tboolean isStartNode = declaredAnnotations.contains(OGMAnnotationProcessor.this.startNodeAnnotationType);\n\t\t\tboolean isEndNode = declaredAnnotations.contains(OGMAnnotationProcessor.this.endNodeAnnotationType);\n\t\t\treturn !(isStartNode || isEndNode);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/main/java/org/neo4j/cypherdsl/codegen/ogm/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Contains the Neo4j-OGM annotation processor that creates a static metamodel for OGM\n * annotated classes.\n */\npackage org.neo4j.cypherdsl.codegen.ogm;\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/main/resources/META-INF/services/javax.annotation.processing.Processor",
    "content": "org.neo4j.cypherdsl.codegen.ogm.OGMAnnotationProcessor\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/OGMAnnotationProcessorTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm;\n\nimport java.util.Arrays;\n\nimport javax.tools.JavaFileObject;\nimport javax.tools.ToolProvider;\n\nimport com.google.testing.compile.Compilation;\nimport com.google.testing.compile.CompilationSubject;\nimport com.google.testing.compile.Compiler;\nimport com.google.testing.compile.JavaFileObjects;\nimport io.github.classgraph.ClassGraph;\nimport io.github.classgraph.ScanResult;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.converter.ArgumentConversionException;\nimport org.junit.jupiter.params.converter.ConvertWith;\nimport org.junit.jupiter.params.converter.SimpleArgumentConverter;\nimport org.junit.jupiter.params.provider.CsvSource;\n\n/**\n * @author Michael J. Simons\n * @author Shinigami92 (Christopher Quadflieg)\n */\nclass OGMAnnotationProcessorTests {\n\n\tstatic Compiler getCompiler(String release, Object... options) {\n\n\t\tString ts = \"-Aorg.neo4j.cypherdsl.codegen.timestamp=2025-09-21T21:21:00+01:00\";\n\t\tObject[] defaultOptions;\n\n\t\tif (ToolProvider.getSystemJavaCompiler().isSupportedOption(\"--release\") >= 0) {\n\t\t\t// release 8 deprecated since Java 21, surprised with -options\n\t\t\tdefaultOptions = new Object[] { \"-Xlint:-options\", ts, \"--release\", release };\n\t\t}\n\t\telse if (\"8\".equals(release)) {\n\t\t\tdefaultOptions = new Object[] { ts, \"-source\", \"8\", \"-target\", \"8\" };\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException(\"Release %s not supported for testing\".formatted(release));\n\t\t}\n\n\t\tObject[] finalOptions = new Object[options.length + defaultOptions.length];\n\t\tSystem.arraycopy(defaultOptions, 0, finalOptions, 0, defaultOptions.length);\n\t\tSystem.arraycopy(options, 0, finalOptions, defaultOptions.length, options.length);\n\n\t\treturn Compiler.javac().withOptions(finalOptions);\n\t}\n\n\tJavaFileObject[] getJavaResources(String base) {\n\t\ttry (ScanResult scanResult = new ClassGraph().acceptPaths(base).scan()) {\n\t\t\treturn scanResult.getResourcesWithExtension(\"java\")\n\t\t\t\t.stream()\n\t\t\t\t.map(resource -> JavaFileObjects.forResource(resource.getURL()))\n\t\t\t\t.toArray(JavaFileObject[]::new);\n\t\t}\n\t}\n\n\t@CsvSource({\n\t\t\t\"8, ids, 'InternalGeneratedId, ExternalGeneratedId, ExternalGeneratedIdImplicit, InternalGeneratedPrimitiveLongId',\",\n\t\t\t\"8, simple, 'Person, Movie, ActedIn, Follows, Directed, Produced',\",\n\t\t\t\"8, labels, 'LabelOnNode1, LabelOnNode2', nodeswithdifferentlabelannotations\",\n\t\t\t\"8, same_properties_for_rel_type, 'Person, Movie, Play, ActedIn', \",\n\t\t\t\"8, different_properties_for_rel_type, 'Person, Movie, Play, ActedInPlay, ActedInMovie', \",\n\t\t\t\"8, same_rel_different_target, 'Person, Movie, Book, Wrote', \",\n\t\t\t\"8, same_rel_different_source, 'Person, Movie, Book, Wrote', \",\n\t\t\t\"8, same_rel_mixed, 'Person, Movie, Book, Wrote', \",\n\t\t\t\"8, same_rel_mixed_different_directions, 'Person, Movie, Book, Wrote', \",\n\t\t\t\"8, abstract_rels, 'Person, Movie, Directed',\", \"8, primitives, 'Connector', \",\n\t\t\t\"8, enums_and_inner_classes, 'ConnectorTransport', \",\n\t\t\t\"8, related_classes_not_on_cp_like_in_reallife, 'Movie, Person', \", \"8, self_referential, 'Example', \",\n\t\t\t\"17, records, 'NodeWithRecordProperties, RecordAsRelationship, RecordTarget', \" })\n\t@ParameterizedTest\n\tvoid validSourceFiles(String release, String scenario, @ConvertWith(StringArrayConverter.class) String[] expected,\n\t\t\tString subpackage) {\n\n\t\tCompilation compilation = getCompiler(release).withProcessors(new OGMAnnotationProcessor())\n\t\t\t.compile(getJavaResources(\"/org/neo4j/cypherdsl/codegen/ogm/models/\" + scenario));\n\n\t\tCompilationSubject.assertThat(compilation).succeeded();\n\t\tif (\"abstract_rels\".equals(scenario)) {\n\t\t\tCompilationSubject.assertThat(compilation)\n\t\t\t\t.hadWarningContaining(\n\t\t\t\t\t\t\"Cannot resolve generic type, not generating a property for relationships referring to org.neo4j.cypherdsl.codegen.ogm.models.abstract_rels.Actor\");\n\t\t}\n\t\telse {\n\t\t\tCompilationSubject.assertThat(compilation).hadWarningCount(0);\n\t\t}\n\n\t\tfor (String expectedSourceFile : expected) {\n\t\t\tString finalName = scenario + \".\" + ((subpackage != null) ? subpackage + \".\" : \"\") + expectedSourceFile\n\t\t\t\t\t+ \"_\";\n\t\t\tCompilationSubject.assertThat(compilation)\n\t\t\t\t.generatedSourceFile(\"org.neo4j.cypherdsl.codegen.ogm.models.\" + finalName)\n\t\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(finalName.replaceAll(\"\\\\.\", \"/\") + \".java\"));\n\t\t}\n\t}\n\n\tstatic class StringArrayConverter extends SimpleArgumentConverter {\n\n\t\t@Override\n\t\tprotected Object convert(Object source, Class<?> targetType) throws ArgumentConversionException {\n\t\t\tif (source instanceof String && String[].class.isAssignableFrom(targetType)) {\n\t\t\t\treturn Arrays.stream(((String) source).split(\"\\\\s*,\\\\s*\")).map(String::trim).toArray(String[]::new);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"Conversion from \" + source.getClass() + \" to \" + targetType + \" not supported.\");\n\t\t\t}\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/abstract_rels/Actor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.abstract_rels;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.RelationshipEntity;\nimport org.neo4j.ogm.annotation.StartNode;\n\n/**\n * Example type.\n *\n * @param <T> a type\n * @author Michael J. Simons\n */\n@RelationshipEntity\npublic class Actor<T> {\n\n\t@StartNode\n\tprivate final T person;\n\n\tprivate List<String> roles = new ArrayList<>();\n\n\tpublic Actor(T person) {\n\t\tthis.person = person;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/abstract_rels/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.abstract_rels;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Property;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\t@Property(\"tagline\")\n\tprivate final String description;\n\n\t@Relationship(type = \"ACTED_IN\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Actor<Person>> actors = new ArrayList<>();\n\n\t@Relationship(type = \"DIRECTED\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Person> directors = new ArrayList<>();\n\n\tpublic Movie(String title, String description) {\n\t\tthis.title = title;\n\t\tthis.description = description;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/abstract_rels/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.abstract_rels;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Person {\n\n\t@Id\n\tprivate String name;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/different_properties_for_rel_type/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.different_properties_for_rel_type;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Movie {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n\tprivate String title;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/different_properties_for_rel_type/MovieAppearance.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.different_properties_for_rel_type;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.EndNode;\nimport org.neo4j.ogm.annotation.RelationshipEntity;\nimport org.neo4j.ogm.annotation.StartNode;\n\n/**\n * @author Michael J. Simons\n */\n@RelationshipEntity\npublic class MovieAppearance {\n\n\t@StartNode\n\tprivate Person person;\n\n\t@EndNode\n\tprivate Movie movie;\n\n\tprivate List<String> roles = new ArrayList<>();\n\n\tprivate String stuntDouble;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/different_properties_for_rel_type/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.different_properties_for_rel_type;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Person {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n\tprivate String name;\n\n\tprivate Integer born;\n\n\t@Relationship(type = \"ACTED_IN\")\n\tprivate MovieAppearance movies;\n\n\t@Relationship(type = \"ACTED_IN\")\n\tprivate List<TheaterAppearance> plays = new ArrayList<>();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/different_properties_for_rel_type/Play.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.different_properties_for_rel_type;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Play {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n\tprivate String title;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/different_properties_for_rel_type/TheaterAppearance.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.different_properties_for_rel_type;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.EndNode;\nimport org.neo4j.ogm.annotation.RelationshipEntity;\nimport org.neo4j.ogm.annotation.StartNode;\n\n/**\n * @author Michael J. Simons\n */\n@RelationshipEntity\npublic class TheaterAppearance {\n\n\t@StartNode\n\tprivate Person person;\n\n\t@EndNode\n\tprivate Play play;\n\n\tprivate List<String> roles = new ArrayList<>();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/different_properties_for_rel_type/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * The same relationship type ACTED_IN is used with different properties. Multiple types\n * needs to be generated.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.different_properties_for_rel_type;\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/enums_and_inner_classes/AnotherConverter.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.enums_and_inner_classes;\n\nimport org.neo4j.ogm.typeconversion.AttributeConverter;\n\n/**\n * @author Michael J. Simons\n */\npublic abstract class AnotherConverter\n\t\timplements AttributeConverter<ConnectorTransport.InnerClass.InnerInnerClass, String> {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/enums_and_inner_classes/ConnectorTransport.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.enums_and_inner_classes;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.typeconversion.Convert;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity(label = \"Transport\")\npublic class ConnectorTransport {\n\n\t@Id\n\tprivate final ConnectorTransportType value;\n\n\tprivate OtherEnum otherEnum;\n\n\t@SuppressWarnings(\"checkstyle:AnnotationUseStyle\")\n\t@Convert(value = AnotherConverter.class)\n\tprivate InnerClass.InnerInnerClass innerInnerClass;\n\n\t@SuppressWarnings(\"checkstyle:AnnotationUseStyle\")\n\t@Convert(value = InnerInnerClassConverter.class)\n\tprivate InnerClass.InnerInnerClass innerInnerClassButWithoutConverter;\n\n\tpublic ConnectorTransport(ConnectorTransportType value) {\n\t\tthis.value = value;\n\t}\n\n\t/**\n\t * Some enum\n\t */\n\tpublic enum ConnectorTransportType {\n\n\t\tHTTP, BOLT\n\n\t}\n\n\t/**\n\t * An inner class\n\t */\n\tpublic static class InnerClass {\n\n\t\t/**\n\t\t * With a nested inner class (used to check whether the recursive algorithm stops\n\t\t * at some point)\n\t\t */\n\t\tpublic static class InnerInnerClass {\n\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/enums_and_inner_classes/InnerInnerClassConverter.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.enums_and_inner_classes;\n\nimport org.neo4j.ogm.typeconversion.AttributeConverter;\n\n/**\n * @author Michael J. Simons\n */\npublic abstract class InnerInnerClassConverter\n\t\timplements AttributeConverter<ConnectorTransport.InnerClass.InnerInnerClass, String> {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/enums_and_inner_classes/OtherEnum.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.enums_and_inner_classes;\n\n/**\n * @author Michael J. Simons\n */\npublic enum OtherEnum {\n\n\tA, B\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/ids/ExternalGeneratedId.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.ids;\n\nimport java.util.UUID;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.typeconversion.Convert;\nimport org.neo4j.ogm.id.UuidStrategy;\nimport org.neo4j.ogm.typeconversion.UuidStringConverter;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class ExternalGeneratedId {\n\n\t@Id\n\t@GeneratedValue(strategy = UuidStrategy.class)\n\t@Convert(UuidStringConverter.class)\n\tprivate UUID id;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/ids/ExternalGeneratedIdImplicit.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.ids;\n\nimport java.util.UUID;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.typeconversion.Convert;\nimport org.neo4j.ogm.typeconversion.UuidStringConverter;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class ExternalGeneratedIdImplicit {\n\n\t@Id\n\t@GeneratedValue\n\t@Convert(UuidStringConverter.class)\n\tprivate UUID id;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/ids/InternalGeneratedId.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.ids;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class InternalGeneratedId {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/ids/InternalGeneratedPrimitiveLongId.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.ids;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class InternalGeneratedPrimitiveLongId {\n\n\t@Id\n\t@GeneratedValue\n\tprivate long id;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/labels/NodesWithDifferentLabelAnnotations.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.labels;\n\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * Tests various ways to define labels. The generated classes will end up in a subpackage\n * as they are static, inner classes.\n *\n * @author Michael J. Simons\n */\npublic class NodesWithDifferentLabelAnnotations {\n\n\t@NodeEntity(\"ALabel\")\n\tstatic class LabelOnNode1 {\n\n\t}\n\n\t@SuppressWarnings(\"checkstyle:AnnotationUseStyle\")\n\t@NodeEntity(value = \"ALabel\")\n\tstatic class LabelOnNode2 {\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/primitives/Connector.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.primitives;\n\nimport java.util.UUID;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Relationship;\nimport org.neo4j.ogm.annotation.typeconversion.Convert;\nimport org.neo4j.ogm.typeconversion.UuidStringConverter;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity(\"Connector\")\npublic class Connector {\n\n\t@Id\n\t@GeneratedValue\n\t@Convert(UuidStringConverter.class)\n\tprivate UUID id;\n\n\tprivate final String uri;\n\n\tprivate final boolean official;\n\n\tprivate int anInt;\n\n\tprivate float aFloat;\n\n\tprivate double aDouble;\n\n\t@Relationship\n\tprivate char aChar;\n\n\tpublic Connector(String uri, boolean official) {\n\t\tthis.uri = uri;\n\t\tthis.official = official;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/records/NodeWithRecordProperties.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.records;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Property;\nimport org.neo4j.ogm.annotation.Relationship;\nimport org.neo4j.ogm.annotation.typeconversion.Convert;\nimport org.neo4j.ogm.typeconversion.AttributeConverter;\n\n/**\n * Random test class.\n */\n@NodeEntity\npublic class NodeWithRecordProperties {\n\n\t@Id\n\tprivate String id;\n\n\t@Convert(RecordConverter.class)\n\tprivate RecordAsProperty recordAsPropertyWithConversion;\n\n\t@Property\n\tprivate RecordAsProperty yoloingNoConversion;\n\n\t// Inner types for relationships are not supported\n\t@Relationship\n\tprivate RecordTarget recordAsRelationship;\n\n\trecord RecordAsProperty(String value) {\n\t}\n\n\tabstract static class RecordConverter implements AttributeConverter<RecordAsProperty, String> {\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/records/RecordTarget.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.records;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * Random test class.\n *\n * @param value a value\n */\n@NodeEntity\npublic record RecordTarget(@Id String value) {\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_properties_for_rel_type/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_properties_for_rel_type;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Movie {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n\tprivate String title;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_properties_for_rel_type/MovieAppearance.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_properties_for_rel_type;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.EndNode;\nimport org.neo4j.ogm.annotation.RelationshipEntity;\n\n/**\n * @author Michael J. Simons\n */\n@RelationshipEntity\npublic class MovieAppearance {\n\n\t@EndNode\n\tprivate Movie movie;\n\n\tprivate List<String> roles = new ArrayList<>();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_properties_for_rel_type/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_properties_for_rel_type;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Person {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n\tprivate String name;\n\n\tprivate Integer born;\n\n\t@Relationship(type = \"ACTED_IN\")\n\tprivate List<MovieAppearance> movies = new ArrayList<>();\n\n\t@Relationship(type = \"ACTED_IN\")\n\tprivate List<TheaterAppearance> plays = new ArrayList<>();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_properties_for_rel_type/Play.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_properties_for_rel_type;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Play {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n\tprivate String title;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_properties_for_rel_type/TheaterAppearance.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_properties_for_rel_type;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.EndNode;\nimport org.neo4j.ogm.annotation.RelationshipEntity;\n\n/**\n * @author Michael J. Simons\n */\n@RelationshipEntity\npublic class TheaterAppearance {\n\n\t@EndNode\n\tprivate Play play;\n\n\tprivate List<String> roles = new ArrayList<>();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_properties_for_rel_type/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * The same relationship type ACTED_IN is used with same properties. Only one type needs\n * to be generated.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_properties_for_rel_type;\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_rel_different_source/Book.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_source;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Book {\n\n\t@Id\n\tprivate final String title;\n\n\t@Relationship(value = \"WROTE\", direction = Relationship.Direction.INCOMING)\n\tprivate Person writtenBy;\n\n\tBook(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_rel_different_source/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_source;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\t@Relationship(value = \"WROTE\", direction = Relationship.Direction.INCOMING)\n\tprivate Person writtenBy;\n\n\tMovie(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_rel_different_source/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_source;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Person {\n\n\t@Id\n\tprivate String name;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_rel_different_target/Book.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_target;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Book {\n\n\t@Id\n\tprivate final String title;\n\n\tBook(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_rel_different_target/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_target;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\tMovie(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_rel_different_target/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_target;\n\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Person {\n\n\t@Id\n\tprivate String name;\n\n\t@Relationship(\"WROTE\")\n\tprivate List<Movie> writtenMovies;\n\n\t@Relationship(\"WROTE\")\n\tprivate List<Book> writtenBooks;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_rel_different_target/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Here the WROTE relationship targets different entities. It should be generated with a\n * wild card.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_target;\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_rel_mixed/Book.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Book {\n\n\t@Id\n\tprivate final String title;\n\n\t@Relationship(value = \"WROTE\", direction = Relationship.Direction.INCOMING)\n\tprivate Person writtenBy;\n\n\tBook(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_rel_mixed/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\tMovie(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_rel_mixed/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed;\n\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Person {\n\n\t@Id\n\tprivate String name;\n\n\t@Relationship(\"WROTE\")\n\tprivate List<Movie> writtenMovies;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_rel_mixed_different_directions/Book.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed_different_directions;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Book {\n\n\t@Id\n\tprivate final String title;\n\n\t// Makes not much sense, but one never knows\n\t@Relationship(value = \"WROTE\", direction = Relationship.Direction.OUTGOING)\n\tprivate Person writtenBy;\n\n\tBook(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_rel_mixed_different_directions/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed_different_directions;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\t@Relationship(value = \"WROTE\", direction = Relationship.Direction.INCOMING)\n\tprivate Person writtenBy;\n\n\tMovie(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/same_rel_mixed_different_directions/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed_different_directions;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Person {\n\n\t@Id\n\tprivate String name;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/self_referential/Example.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.self_referential;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Example {\n\n\t@Id\n\tprivate final long id;\n\n\t@Relationship(type = \"BELONGS_TO\")\n\tprivate Example parent;\n\n\tpublic Example(long id) {\n\t\tthis.id = id;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/simple/Actor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.simple;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.EndNode;\nimport org.neo4j.ogm.annotation.RelationshipEntity;\nimport org.neo4j.ogm.annotation.StartNode;\n\n/**\n * @author Michael J. Simons\n */\n@RelationshipEntity(type = \"ACTED_IN\")\npublic class Actor {\n\n\t@StartNode\n\tprivate final Person person;\n\n\t@EndNode\n\tMovie movie;\n\n\tprivate List<String> roles = new ArrayList<>();\n\n\tpublic Actor(Person person) {\n\t\tthis.person = person;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/simple/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.simple;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Property;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\t@Property(\"tagline\")\n\tprivate final String description;\n\n\t@Relationship(type = \"ACTED_IN\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Actor> actors = new ArrayList<>();\n\n\t@Relationship(type = \"DIRECTED\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Person> directors = new ArrayList<>();\n\n\t// This will be ignored, not annotated and the other type is not a node\n\tprivate SomeType someProp;\n\n\tprivate Integer released;\n\n\tpublic Movie(String title, String description) {\n\t\tthis.title = title;\n\t\tthis.description = description;\n\t}\n\n\tstatic class SomeType {\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/simple/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.simple;\n\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Person {\n\n\t@Id\n\tprivate String name;\n\n\tprivate Integer born;\n\n\tprivate Person follows;\n\n\tprivate List<Movie> produced;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/java/org/neo4j/cypherdsl/codegen/ogm/models/simple/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * This is basically the \"happy path\" as demonstrated in several examples.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.simple;\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/abstract_rels/Directed_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.abstract_rels;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Directed_ extends RelationshipBase<Person_, Movie_, Directed_> {\n\n\tpublic static final String $TYPE = \"DIRECTED\";\n\n\tpublic Directed_(Person_ start, Movie_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Directed_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Directed_ named(SymbolicName newSymbolicName) {\n\t\treturn new Directed_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Directed_ withProperties(MapExpression newProperties) {\n\t\treturn new Directed_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/abstract_rels/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.abstract_rels;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Property DESCRIPTION = this.property(\"tagline\").referencedAs(\"description\");\n\n\tpublic final Directed_ DIRECTORS = new Directed_(Person_.PERSON, this);\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/abstract_rels/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.abstract_rels;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/different_properties_for_rel_type/ActedInMovie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.different_properties_for_rel_type;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ActedInMovie_ extends RelationshipBase<Person_, Movie_, ActedInMovie_> {\n\n\tpublic static final String $TYPE = \"ACTED_IN\";\n\n\tpublic final Property ROLES = this.property(\"roles\");\n\n\tpublic final Property STUNT_DOUBLE = this.property(\"stuntDouble\");\n\n\tpublic ActedInMovie_(Person_ start, Movie_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate ActedInMovie_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic ActedInMovie_ named(SymbolicName newSymbolicName) {\n\t\treturn new ActedInMovie_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic ActedInMovie_ withProperties(MapExpression newProperties) {\n\t\treturn new ActedInMovie_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties),\n\t\t\t\tgetRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/different_properties_for_rel_type/ActedInPlay_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.different_properties_for_rel_type;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ActedInPlay_ extends RelationshipBase<Person_, Play_, ActedInPlay_> {\n\n\tpublic static final String $TYPE = \"ACTED_IN\";\n\n\tpublic final Property ROLES = this.property(\"roles\");\n\n\tpublic ActedInPlay_(Person_ start, Play_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate ActedInPlay_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic ActedInPlay_ named(SymbolicName newSymbolicName) {\n\t\treturn new ActedInPlay_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic ActedInPlay_ withProperties(MapExpression newProperties) {\n\t\treturn new ActedInPlay_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties),\n\t\t\t\tgetRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/different_properties_for_rel_type/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.different_properties_for_rel_type;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/different_properties_for_rel_type/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.different_properties_for_rel_type;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Property BORN = this.property(\"born\");\n\n\tpublic final ActedInMovie_ MOVIES = new ActedInMovie_(this, Movie_.MOVIE);\n\n\tpublic final ActedInPlay_ PLAYS = new ActedInPlay_(this, Play_.PLAY);\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/different_properties_for_rel_type/Play_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.different_properties_for_rel_type;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Play_ extends NodeBase<Play_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Play\";\n\n\tpublic static final Play_ PLAY = new Play_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Play_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Play_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Play_ named(SymbolicName newSymbolicName) {\n\t\treturn new Play_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Play_ withProperties(MapExpression newProperties) {\n\t\treturn new Play_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/enums_and_inner_classes/ConnectorTransport_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.enums_and_inner_classes;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ConnectorTransport_ extends NodeBase<ConnectorTransport_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Transport\";\n\n\tpublic static final ConnectorTransport_ CONNECTOR_TRANSPORT = new ConnectorTransport_();\n\n\tpublic final Property VALUE = this.property(\"value\");\n\n\tpublic final Property OTHER_ENUM = this.property(\"otherEnum\");\n\n\tpublic final Property INNER_INNER_CLASS = this.property(\"innerInnerClass\");\n\n\tpublic final Property INNER_INNER_CLASS_BUT_WITHOUT_CONVERTER = this.property(\"innerInnerClassButWithoutConverter\");\n\n\tpublic ConnectorTransport_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate ConnectorTransport_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic ConnectorTransport_ named(SymbolicName newSymbolicName) {\n\t\treturn new ConnectorTransport_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic ConnectorTransport_ withProperties(MapExpression newProperties) {\n\t\treturn new ConnectorTransport_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/ids/ExternalGeneratedIdImplicit_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.ids;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ExternalGeneratedIdImplicit_ extends NodeBase<ExternalGeneratedIdImplicit_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"ExternalGeneratedIdImplicit\";\n\n\tpublic static final ExternalGeneratedIdImplicit_ EXTERNAL_GENERATED_ID_IMPLICIT = new ExternalGeneratedIdImplicit_();\n\n\tpublic final Property ID = this.property(\"id\");\n\n\tpublic ExternalGeneratedIdImplicit_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate ExternalGeneratedIdImplicit_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic ExternalGeneratedIdImplicit_ named(SymbolicName newSymbolicName) {\n\t\treturn new ExternalGeneratedIdImplicit_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic ExternalGeneratedIdImplicit_ withProperties(MapExpression newProperties) {\n\t\treturn new ExternalGeneratedIdImplicit_(getSymbolicName().orElse(null), getLabels(),\n\t\t\t\tProperties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/ids/ExternalGeneratedId_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.ids;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ExternalGeneratedId_ extends NodeBase<ExternalGeneratedId_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"ExternalGeneratedId\";\n\n\tpublic static final ExternalGeneratedId_ EXTERNAL_GENERATED_ID = new ExternalGeneratedId_();\n\n\tpublic final Property ID = this.property(\"id\");\n\n\tpublic ExternalGeneratedId_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate ExternalGeneratedId_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic ExternalGeneratedId_ named(SymbolicName newSymbolicName) {\n\t\treturn new ExternalGeneratedId_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic ExternalGeneratedId_ withProperties(MapExpression newProperties) {\n\t\treturn new ExternalGeneratedId_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/ids/InternalGeneratedId_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.ids;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class InternalGeneratedId_ extends NodeBase<InternalGeneratedId_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"InternalGeneratedId\";\n\n\tpublic static final InternalGeneratedId_ INTERNAL_GENERATED_ID = new InternalGeneratedId_();\n\n\tpublic InternalGeneratedId_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate InternalGeneratedId_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic InternalGeneratedId_ named(SymbolicName newSymbolicName) {\n\t\treturn new InternalGeneratedId_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic InternalGeneratedId_ withProperties(MapExpression newProperties) {\n\t\treturn new InternalGeneratedId_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/ids/InternalGeneratedPrimitiveLongId_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.ids;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class InternalGeneratedPrimitiveLongId_ extends NodeBase<InternalGeneratedPrimitiveLongId_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"InternalGeneratedPrimitiveLongId\";\n\n\tpublic static final InternalGeneratedPrimitiveLongId_ INTERNAL_GENERATED_PRIMITIVE_LONG_ID = new InternalGeneratedPrimitiveLongId_();\n\n\tpublic InternalGeneratedPrimitiveLongId_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate InternalGeneratedPrimitiveLongId_(SymbolicName symbolicName, List<NodeLabel> labels,\n\t\t\tProperties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic InternalGeneratedPrimitiveLongId_ named(SymbolicName newSymbolicName) {\n\t\treturn new InternalGeneratedPrimitiveLongId_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic InternalGeneratedPrimitiveLongId_ withProperties(MapExpression newProperties) {\n\t\treturn new InternalGeneratedPrimitiveLongId_(getSymbolicName().orElse(null), getLabels(),\n\t\t\t\tProperties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/labels/nodeswithdifferentlabelannotations/LabelOnNode1_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.labels.nodeswithdifferentlabelannotations;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class LabelOnNode1_ extends NodeBase<LabelOnNode1_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"ALabel\";\n\n\tpublic static final LabelOnNode1_ LABEL_ON_NODE_1 = new LabelOnNode1_();\n\n\tpublic LabelOnNode1_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate LabelOnNode1_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic LabelOnNode1_ named(SymbolicName newSymbolicName) {\n\t\treturn new LabelOnNode1_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic LabelOnNode1_ withProperties(MapExpression newProperties) {\n\t\treturn new LabelOnNode1_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/labels/nodeswithdifferentlabelannotations/LabelOnNode2_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.labels.nodeswithdifferentlabelannotations;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class LabelOnNode2_ extends NodeBase<LabelOnNode2_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"ALabel\";\n\n\tpublic static final LabelOnNode2_ LABEL_ON_NODE_2 = new LabelOnNode2_();\n\n\tpublic LabelOnNode2_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate LabelOnNode2_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic LabelOnNode2_ named(SymbolicName newSymbolicName) {\n\t\treturn new LabelOnNode2_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic LabelOnNode2_ withProperties(MapExpression newProperties) {\n\t\treturn new LabelOnNode2_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/org/neo4j/cypherdsl/codegen/ogm/models/related_classes_not_on_cp_like_in_reallife/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.related_classes_not_on_cp_like_in_reallife;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Property;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic final class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\t@Property(\"tagline\")\n\tprivate final String description;\n\n\t@Relationship(value = \"DIRECTED\", direction = Relationship.Direction.INCOMING)\n\tprivate final List<Person> directors;\n\tprivate Type type;\n\tprivate Integer released;\n\n\tpublic Movie(String title, String description) {\n\t\tthis.title = title;\n\t\tthis.description = description;\n\t\tthis.directors = new ArrayList<>();\n\t}\n\n\tpublic Movie(String title, String description, List<Person> directors) {\n\t\tthis.title = title;\n\t\tthis.description = description;\n\t\tthis.directors = directors == null ? Collections.emptyList() : new ArrayList<>(directors);\n\t}\n\n\tpublic String getTitle() {\n\t\treturn title;\n\t}\n\n\tpublic String getDescription() {\n\t\treturn description;\n\t}\n\n\tpublic List<Person> getDirectors() {\n\t\treturn Collections.unmodifiableList(this.directors);\n\t}\n\n\tpublic Integer getReleased() {\n\t\treturn released;\n\t}\n\n\tpublic void setReleased(Integer released) {\n\t\tthis.released = released;\n\t}\n\n\tpublic Type getType() {\n\t\treturn type;\n\t}\n\n\tpublic void setType(Type type) {\n\t\tthis.type = type;\n\t}\n\n\tpublic Movie addDirectors(Collection<Person> newDirectors) {\n\t\tthis.directors.addAll(newDirectors);\n\t\treturn this;\n\t}\n\n\tpublic enum Type {\n\n\t\tAKTION_FILM, KOMÖDIE, SCHNULZE\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/org/neo4j/cypherdsl/codegen/ogm/models/related_classes_not_on_cp_like_in_reallife/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.ogm.models.related_classes_not_on_cp_like_in_reallife;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * @author Michael J. Simons\n */\n@NodeEntity\npublic final class Person {\n\n\t@Id\n\t@GeneratedValue\n\tprivate final Long id;\n\n\tprivate final String name;\n\n\tprivate Integer born;\n\n\tprivate Person(Long id, String name, Integer born) {\n\t\tthis.id = id;\n\t\tthis.born = born;\n\t\tthis.name = name;\n\t}\n\n\tpublic Person(String name, Integer born) {\n\t\tthis(null, name, born);\n\t}\n\n\tpublic Long getId() {\n\t\treturn id;\n\t}\n\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\tpublic Integer getBorn() {\n\t\treturn born;\n\t}\n\n\tpublic void setBorn(Integer born) {\n\t\tthis.born = born;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/primitives/Connector_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.primitives;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Connector_ extends NodeBase<Connector_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Connector\";\n\n\tpublic static final Connector_ CONNECTOR = new Connector_();\n\n\tpublic final Property ID = this.property(\"id\");\n\n\tpublic final Property URI = this.property(\"uri\");\n\n\tpublic final Property OFFICIAL = this.property(\"official\");\n\n\tpublic final Property AN_INT = this.property(\"anInt\");\n\n\tpublic final Property A_FLOAT = this.property(\"aFloat\");\n\n\tpublic final Property A_DOUBLE = this.property(\"aDouble\");\n\n\tpublic Connector_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Connector_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Connector_ named(SymbolicName newSymbolicName) {\n\t\treturn new Connector_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Connector_ withProperties(MapExpression newProperties) {\n\t\treturn new Connector_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/records/NodeWithRecordProperties_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.records;\n\nimport java.util.List;\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class NodeWithRecordProperties_ extends NodeBase<NodeWithRecordProperties_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"NodeWithRecordProperties\";\n\n\tpublic static final NodeWithRecordProperties_ NODE_WITH_RECORD_PROPERTIES = new NodeWithRecordProperties_();\n\n\tpublic final Property ID = this.property(\"id\");\n\n\tpublic final Property RECORD_AS_PROPERTY_WITH_CONVERSION = this.property(\"recordAsPropertyWithConversion\");\n\n\tpublic final Property YOLOING_NO_CONVERSION = this.property(\"yoloingNoConversion\");\n\n\tpublic final RecordAsRelationship_ RECORD_AS_RELATIONSHIP = new RecordAsRelationship_(this,\n\t\t\tRecordTarget_.RECORD_TARGET);\n\n\tpublic NodeWithRecordProperties_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate NodeWithRecordProperties_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic NodeWithRecordProperties_ named(SymbolicName newSymbolicName) {\n\t\treturn new NodeWithRecordProperties_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic NodeWithRecordProperties_ withProperties(MapExpression newProperties) {\n\t\treturn new NodeWithRecordProperties_(getSymbolicName().orElse(null), getLabels(),\n\t\t\t\tProperties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/records/RecordAsRelationship_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.records;\n\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class RecordAsRelationship_\n\t\textends RelationshipBase<NodeWithRecordProperties_, RecordTarget_, RecordAsRelationship_> {\n\n\tpublic static final String $TYPE = \"recordAsRelationship\";\n\n\tpublic RecordAsRelationship_(NodeWithRecordProperties_ start, RecordTarget_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate RecordAsRelationship_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic RecordAsRelationship_ named(SymbolicName newSymbolicName) {\n\t\treturn new RecordAsRelationship_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic RecordAsRelationship_ withProperties(MapExpression newProperties) {\n\t\treturn new RecordAsRelationship_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties),\n\t\t\t\tgetRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/records/RecordTarget_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.records;\n\nimport java.util.List;\n\nimport javax.annotation.processing.Generated;\n\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class RecordTarget_ extends NodeBase<RecordTarget_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"RecordTarget\";\n\n\tpublic static final RecordTarget_ RECORD_TARGET = new RecordTarget_();\n\n\tpublic final Property VALUE = this.property(\"value\");\n\n\tpublic RecordTarget_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate RecordTarget_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic RecordTarget_ named(SymbolicName newSymbolicName) {\n\t\treturn new RecordTarget_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic RecordTarget_ withProperties(MapExpression newProperties) {\n\t\treturn new RecordTarget_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/related_classes_not_on_cp_like_in_reallife/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.related_classes_not_on_cp_like_in_reallife;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Property DESCRIPTION = this.property(\"tagline\").referencedAs(\"description\");\n\n\tpublic final Property TYPE = this.property(\"type\");\n\n\tpublic final Property RELEASED = this.property(\"released\");\n\n\tpublic final Directed_ DIRECTORS = new Directed_(Person_.PERSON, this);\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/related_classes_not_on_cp_like_in_reallife/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.related_classes_not_on_cp_like_in_reallife;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Property BORN = this.property(\"born\");\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_properties_for_rel_type/ActedIn_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_properties_for_rel_type;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ActedIn_<E extends NodeBase<?>> extends RelationshipBase<Person_, E, ActedIn_<E>> {\n\n\tpublic static final String $TYPE = \"ACTED_IN\";\n\n\tpublic final Property ROLES = this.property(\"roles\");\n\n\tpublic ActedIn_(Person_ start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate ActedIn_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic ActedIn_<E> named(SymbolicName newSymbolicName) {\n\t\treturn new ActedIn_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic ActedIn_<E> withProperties(MapExpression newProperties) {\n\t\treturn new ActedIn_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_properties_for_rel_type/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_properties_for_rel_type;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_properties_for_rel_type/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_properties_for_rel_type;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Property BORN = this.property(\"born\");\n\n\tpublic final ActedIn_<Movie_> MOVIES = new ActedIn_<Movie_>(this, Movie_.MOVIE);\n\n\tpublic final ActedIn_<Play_> PLAYS = new ActedIn_<Play_>(this, Play_.PLAY);\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_properties_for_rel_type/Play_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_properties_for_rel_type;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Play_ extends NodeBase<Play_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Play\";\n\n\tpublic static final Play_ PLAY = new Play_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Play_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Play_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Play_ named(SymbolicName newSymbolicName) {\n\t\treturn new Play_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Play_ withProperties(MapExpression newProperties) {\n\t\treturn new Play_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_different_source/Book_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_source;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Book_ extends NodeBase<Book_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Book\";\n\n\tpublic static final Book_ BOOK = new Book_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Wrote_<Book_> WRITTEN_BY = new Wrote_<Book_>(Person_.PERSON, this);\n\n\tpublic Book_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Book_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Book_ named(SymbolicName newSymbolicName) {\n\t\treturn new Book_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Book_ withProperties(MapExpression newProperties) {\n\t\treturn new Book_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_different_source/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_source;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Wrote_<Movie_> WRITTEN_BY = new Wrote_<Movie_>(Person_.PERSON, this);\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_different_source/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_source;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_different_source/Wrote_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_source;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Wrote_<E extends NodeBase<?>> extends RelationshipBase<Person_, E, Wrote_<E>> {\n\n\tpublic static final String $TYPE = \"WROTE\";\n\n\tpublic Wrote_(Person_ start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Wrote_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Wrote_<E> named(SymbolicName newSymbolicName) {\n\t\treturn new Wrote_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Wrote_<E> withProperties(MapExpression newProperties) {\n\t\treturn new Wrote_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_different_target/Book_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_target;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Book_ extends NodeBase<Book_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Book\";\n\n\tpublic static final Book_ BOOK = new Book_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Book_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Book_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Book_ named(SymbolicName newSymbolicName) {\n\t\treturn new Book_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Book_ withProperties(MapExpression newProperties) {\n\t\treturn new Book_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_different_target/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_target;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_different_target/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_target;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Wrote_<Movie_> WRITTEN_MOVIES = new Wrote_<Movie_>(this, Movie_.MOVIE);\n\n\tpublic final Wrote_<Book_> WRITTEN_BOOKS = new Wrote_<Book_>(this, Book_.BOOK);\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_different_target/Wrote_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_different_target;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Wrote_<E extends NodeBase<?>> extends RelationshipBase<Person_, E, Wrote_<E>> {\n\n\tpublic static final String $TYPE = \"WROTE\";\n\n\tpublic Wrote_(Person_ start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Wrote_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Wrote_<E> named(SymbolicName newSymbolicName) {\n\t\treturn new Wrote_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Wrote_<E> withProperties(MapExpression newProperties) {\n\t\treturn new Wrote_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_mixed/Book_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Book_ extends NodeBase<Book_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Book\";\n\n\tpublic static final Book_ BOOK = new Book_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Wrote_<Book_> WRITTEN_BY = new Wrote_<Book_>(Person_.PERSON, this);\n\n\tpublic Book_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Book_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Book_ named(SymbolicName newSymbolicName) {\n\t\treturn new Book_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Book_ withProperties(MapExpression newProperties) {\n\t\treturn new Book_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_mixed/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_mixed/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Wrote_<Movie_> WRITTEN_MOVIES = new Wrote_<Movie_>(this, Movie_.MOVIE);\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_mixed/Wrote_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Wrote_<E extends NodeBase<?>> extends RelationshipBase<Person_, E, Wrote_<E>> {\n\n\tpublic static final String $TYPE = \"WROTE\";\n\n\tpublic Wrote_(Person_ start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Wrote_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Wrote_<E> named(SymbolicName newSymbolicName) {\n\t\treturn new Wrote_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Wrote_<E> withProperties(MapExpression newProperties) {\n\t\treturn new Wrote_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_mixed_different_directions/Book_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed_different_directions;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Book_ extends NodeBase<Book_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Book\";\n\n\tpublic static final Book_ BOOK = new Book_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Wrote_<Book_, Person_> WRITTEN_BY = new Wrote_<Book_, Person_>(this, Person_.PERSON);\n\n\tpublic Book_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Book_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Book_ named(SymbolicName newSymbolicName) {\n\t\treturn new Book_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Book_ withProperties(MapExpression newProperties) {\n\t\treturn new Book_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_mixed_different_directions/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed_different_directions;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Wrote_<Person_, Movie_> WRITTEN_BY = new Wrote_<Person_, Movie_>(Person_.PERSON, this);\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_mixed_different_directions/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed_different_directions;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/same_rel_mixed_different_directions/Wrote_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.same_rel_mixed_different_directions;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Wrote_<S extends NodeBase<?>, E extends NodeBase<?>> extends RelationshipBase<S, E, Wrote_<S, E>> {\n\n\tpublic static final String $TYPE = \"WROTE\";\n\n\tpublic Wrote_(S start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Wrote_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Wrote_<S, E> named(SymbolicName newSymbolicName) {\n\t\treturn new Wrote_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Wrote_<S, E> withProperties(MapExpression newProperties) {\n\t\treturn new Wrote_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/self_referential/Example_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.self_referential;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Example_ extends NodeBase<Example_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Example\";\n\n\tpublic static final Example_ EXAMPLE = new Example_();\n\n\tpublic final Property ID = this.property(\"id\");\n\n\tpublic Example_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Example_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Example_ named(SymbolicName newSymbolicName) {\n\t\treturn new Example_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Example_ withProperties(MapExpression newProperties) {\n\t\treturn new Example_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n\tpublic BelongsTo_ withParent(Example_ parent) {\n\t\treturn new BelongsTo_(this, parent);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/simple/ActedIn_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.simple;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ActedIn_ extends RelationshipBase<Person_, Movie_, ActedIn_> {\n\n\tpublic static final String $TYPE = \"ACTED_IN\";\n\n\tpublic final Property ROLES = this.property(\"roles\");\n\n\tpublic ActedIn_(Person_ start, Movie_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate ActedIn_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic ActedIn_ named(SymbolicName newSymbolicName) {\n\t\treturn new ActedIn_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic ActedIn_ withProperties(MapExpression newProperties) {\n\t\treturn new ActedIn_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/simple/Directed_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.simple;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Directed_ extends RelationshipBase<Person_, Movie_, Directed_> {\n\n\tpublic static final String $TYPE = \"DIRECTED\";\n\n\tpublic Directed_(Person_ start, Movie_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Directed_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Directed_ named(SymbolicName newSymbolicName) {\n\t\treturn new Directed_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Directed_ withProperties(MapExpression newProperties) {\n\t\treturn new Directed_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/simple/Follows_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.simple;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Follows_ extends RelationshipBase<Person_, Person_, Follows_> {\n\n\tpublic static final String $TYPE = \"follows\";\n\n\tpublic Follows_(Person_ start, Person_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Follows_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Follows_ named(SymbolicName newSymbolicName) {\n\t\treturn new Follows_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Follows_ withProperties(MapExpression newProperties) {\n\t\treturn new Follows_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/simple/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.simple;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Property DESCRIPTION = this.property(\"tagline\").referencedAs(\"description\");\n\n\tpublic final Property RELEASED = this.property(\"released\");\n\n\tpublic final ActedIn_ ACTORS = new ActedIn_(Person_.PERSON, this);\n\n\tpublic final Directed_ DIRECTORS = new Directed_(Person_.PERSON, this);\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/simple/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.simple;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Property BORN = this.property(\"born\");\n\n\tpublic final Produced_ PRODUCED = new Produced_(this, Movie_.MOVIE);\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n\tpublic Follows_ withFollows(Person_ follows) {\n\t\treturn new Follows_(this, follows);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-ogm/src/test/resources/simple/Produced_.java",
    "content": "package org.neo4j.cypherdsl.codegen.ogm.models.simple;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2025-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Produced_ extends RelationshipBase<Person_, Movie_, Produced_> {\n\n\tpublic static final String $TYPE = \"produced\";\n\n\tpublic Produced_(Person_ start, Movie_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Produced_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Produced_ named(SymbolicName newSymbolicName) {\n\t\treturn new Produced_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Produced_ withProperties(MapExpression newProperties) {\n\t\treturn new Produced_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-codegen</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-codegen-sdn6</artifactId>\n\t<name>Code Generator (SDN 6)</name>\n\t<description>Annotation processor reading SDN 6 annotations and creating a static model of them.</description>\n\n\t<properties>\n\t\t<covered-ratio-complexity>0.7</covered-ratio-complexity>\n\t\t<covered-ratio-instructions>0.7</covered-ratio-instructions>\n\t\t<java-module-name>org.neo4j.cypherdsl.codegen.sdn6</java-module-name>\n\t\t<sonar.coverage.jacoco.xmlReportPaths>${basedir}/../../${aggregate.report.dir}</sonar.coverage.jacoco.xmlReportPaths>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl-codegen-core</artifactId>\n\t\t</dependency>\n\n\t\t<!-- SDN 6 annotation proc -->\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-simple</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.data</groupId>\n\t\t\t<artifactId>spring-data-neo4j</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.google.testing.compile</groupId>\n\t\t\t<artifactId>compile-testing</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.assertj</groupId>\n\t\t\t<artifactId>assertj-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.junit.vintage</groupId>\n\t\t\t<artifactId>junit-vintage-engine</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<testResources>\n\t\t\t<testResource>\n\t\t\t\t<directory>src/test/java</directory>\n\t\t\t\t<includes>\n\t\t\t\t\t<include>org/neo4j/cypherdsl/codegen/sdn6/models/**/*.java</include>\n\t\t\t\t</includes>\n\t\t\t</testResource>\n\t\t\t<testResource>\n\t\t\t\t<directory>src/test/resources</directory>\n\t\t\t</testResource>\n\t\t</testResources>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<argLine>@{argLine}\n\t\t\t\t\t\t--add-opens jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED\n\t\t\t\t\t\t--add-opens jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED\n\t\t\t\t\t\t--add-opens jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED\n\t\t\t\t\t\t--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED\n\t\t\t\t\t\t--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED\n\t\t\t\t\t\t--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</argLine>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<!--\n\t\t\t\t| Disable processors, otherwise Javac would already find our processors while compiling them and end up with\n\t\t\t\t| \"Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing.Processor: Provider org.neo4j.cypherdsl.codegen.neo4j.SDN6AnnotationProcessor not found\"\n\t\t\t\t-->\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<compilerArgument>-proc:none</compilerArgument>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-jar-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<archive>\n\t\t\t\t\t\t<manifestEntries>\n\t\t\t\t\t\t\t<Automatic-Module-Name>${java-module-name}</Automatic-Module-Name>\n\t\t\t\t\t\t</manifestEntries>\n\t\t\t\t\t</archive>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/main/java/org/neo4j/cypherdsl/codegen/sdn6/SDN6AnnotationProcessor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6;\n\nimport java.io.IOException;\nimport java.util.AbstractMap;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.EnumMap;\nimport java.util.HashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.function.BooleanSupplier;\nimport java.util.function.Consumer;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\nimport javax.annotation.processing.ProcessingEnvironment;\nimport javax.annotation.processing.RoundEnvironment;\nimport javax.annotation.processing.SupportedAnnotationTypes;\nimport javax.annotation.processing.SupportedOptions;\nimport javax.lang.model.element.AnnotationMirror;\nimport javax.lang.model.element.AnnotationValue;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.RecordComponentElement;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.element.VariableElement;\nimport javax.lang.model.type.DeclaredType;\nimport javax.lang.model.type.PrimitiveType;\nimport javax.lang.model.type.TypeMirror;\nimport javax.lang.model.util.ElementKindVisitor8;\nimport javax.lang.model.util.Elements;\nimport javax.lang.model.util.SimpleTypeVisitor8;\nimport javax.tools.Diagnostic;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.codegen.core.AbstractMappingAnnotationProcessor;\nimport org.neo4j.cypherdsl.codegen.core.Configuration;\nimport org.neo4j.cypherdsl.codegen.core.ModelBuilder;\nimport org.neo4j.cypherdsl.codegen.core.NodeModelBuilder;\nimport org.neo4j.cypherdsl.codegen.core.PropertyDefinition;\nimport org.neo4j.cypherdsl.codegen.core.RelationshipModelBuilder;\nimport org.neo4j.cypherdsl.codegen.core.RelationshipPropertyDefinition;\n\nimport org.springframework.data.neo4j.core.convert.Neo4jConversions;\nimport org.springframework.data.neo4j.core.convert.Neo4jPersistentPropertyConverter;\nimport org.springframework.data.neo4j.core.convert.Neo4jSimpleTypes;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Property;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\nimport static org.apiguardian.api.API.Status.EXPERIMENTAL;\n\n/**\n * Annotation processor supporting the annotations provided by\n * <a href=\"https://github.com/spring-projects/spring-data-neo4j\">Spring Data Neo4j\n * 6+</a>.\n *\n * @author Michael J. Simons\n * @since 2021.1.0\n */\n@API(status = EXPERIMENTAL, since = \"2021.1.0\")\n@SupportedAnnotationTypes({ SDN6AnnotationProcessor.NODE_ANNOTATION,\n\t\tSDN6AnnotationProcessor.RELATIONSHIP_PROPERTIES_ANNOTATION })\n@SupportedOptions({ Configuration.PROPERTY_PREFIX, Configuration.PROPERTY_SUFFIX, Configuration.PROPERTY_INDENT_STYLE,\n\t\tConfiguration.PROPERTY_INDENT_SIZE, Configuration.PROPERTY_TIMESTAMP, Configuration.PROPERTY_ADD_AT_GENERATED,\n\t\tSDN6AnnotationProcessor.PROPERTY_CUSTOM_CONVERTER_CLASSES, Configuration.PROPERTY_EXCLUDES })\npublic final class SDN6AnnotationProcessor extends AbstractMappingAnnotationProcessor {\n\n\tstatic final String NODE_ANNOTATION = \"org.springframework.data.neo4j.core.schema.Node\";\n\tstatic final String RELATIONSHIP_PROPERTIES_ANNOTATION = \"org.springframework.data.neo4j.core.schema.RelationshipProperties\";\n\tstatic final String PROPERTY_CUSTOM_CONVERTER_CLASSES = \"org.neo4j.cypherdsl.codegen.sdn.custom_converter_classes\";\n\tstatic final Set<String> VALID_GENERATED_ID_TYPES = Set.of(Long.class.getName(), long.class.getName());\n\n\t// Resources\n\t// * http://hannesdorfmann.com/annotation-processing/annotationprocessing101/\n\t// *\n\t// https://speakerdeck.com/gunnarmorling/das-annotation-processing-api-use-cases-und-best-practices\n\n\tstatic {\n\t\tdisableSpringConverterDebugLog();\n\t}\n\n\tprivate TypeElement nodeAnnotationType;\n\n\tprivate TypeElement relationshipAnnotationType;\n\n\tprivate TypeElement compositePropertyAnnotationType;\n\n\tprivate TypeElement convertWithAnnotationType;\n\n\tprivate TypeElement propertyAnnotationType;\n\n\tprivate TypeElement targetNodeAnnotationType;\n\n\tprivate TypeElement relationshipPropertiesAnnotationType;\n\n\tprivate TypeElement sdnIdAnnotationType;\n\n\tprivate TypeElement sdcIdAnnotationType;\n\n\tprivate TypeElement generatedValueAnnotationType;\n\n\tprivate Neo4jConversions conversions;\n\n\t@SuppressWarnings(\"PMD\")\n\tprivate static void disableSpringConverterDebugLog() {\n\t\ttry {\n\t\t\tClass<?> logback = Class.forName(\"ch.qos.logback.classic.Logger\");\n\t\t\t// Don't replace the qualified names, Checkstyle will yell at you.\n\t\t\tlogback.getMethod(\"setLevel\")\n\t\t\t\t.invoke(org.slf4j.LoggerFactory.getLogger(\"org.springframework.data.convert.CustomConversions\"),\n\t\t\t\t\t\torg.slf4j.event.Level.DEBUG);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\t// There's nothing we can do or should do in case there is no logback.\n\t\t}\n\t}\n\n\t@Override\n\tprotected void initFrameworkSpecific(ProcessingEnvironment processingEnv) {\n\t\tthis.conversions = createConversions(processingEnv);\n\n\t\tElements elementUtils = processingEnv.getElementUtils();\n\t\tthis.nodeAnnotationType = elementUtils.getTypeElement(NODE_ANNOTATION);\n\t\tthis.relationshipPropertiesAnnotationType = elementUtils.getTypeElement(RELATIONSHIP_PROPERTIES_ANNOTATION);\n\n\t\tthis.relationshipAnnotationType = elementUtils\n\t\t\t.getTypeElement(\"org.springframework.data.neo4j.core.schema.Relationship\");\n\t\tthis.propertyAnnotationType = elementUtils\n\t\t\t.getTypeElement(\"org.springframework.data.neo4j.core.schema.Property\");\n\t\tthis.compositePropertyAnnotationType = elementUtils\n\t\t\t.getTypeElement(\"org.springframework.data.neo4j.core.schema.CompositeProperty\");\n\t\tthis.convertWithAnnotationType = elementUtils\n\t\t\t.getTypeElement(\"org.springframework.data.neo4j.core.convert.ConvertWith\");\n\t\tthis.targetNodeAnnotationType = elementUtils\n\t\t\t.getTypeElement(\"org.springframework.data.neo4j.core.schema.TargetNode\");\n\n\t\tthis.sdnIdAnnotationType = elementUtils.getTypeElement(\"org.springframework.data.neo4j.core.schema.Id\");\n\t\tthis.sdcIdAnnotationType = elementUtils.getTypeElement(\"org.springframework.data.annotation.Id\");\n\t\tthis.generatedValueAnnotationType = elementUtils\n\t\t\t.getTypeElement(\"org.springframework.data.neo4j.core.schema.GeneratedValue\");\n\t}\n\n\t/**\n\t * Create an instance of {@link Neo4jConversions} and registers optional additional\n\t * converters with it. The converters must have a default-non-args constructor.\n\t * @param processingEnv the processing environment\n\t * @return a conversions instance\n\t */\n\tprivate Neo4jConversions createConversions(ProcessingEnvironment processingEnv) {\n\n\t\tMap<String, String> options = processingEnv.getOptions();\n\t\tif (!options.containsKey(PROPERTY_CUSTOM_CONVERTER_CLASSES)) {\n\t\t\treturn new Neo4jConversions();\n\t\t}\n\t\tString classNames = options.get(PROPERTY_CUSTOM_CONVERTER_CLASSES);\n\t\tList<Object> converters = new ArrayList<>();\n\t\tArrays.stream(classNames.split(\",\")).map(String::trim).filter(cn -> !cn.isEmpty()).forEach(cn -> {\n\t\t\ttry {\n\t\t\t\tClass<?> clazz = Class.forName(cn);\n\t\t\t\tif (Neo4jPersistentPropertyConverter.class.isAssignableFrom(clazz)) {\n\t\t\t\t\tthis.messager.printMessage(Diagnostic.Kind.MANDATORY_WARNING,\n\t\t\t\t\t\t\t\"Cannot use dedicated Neo4j persistent property converter of type `\" + cn\n\t\t\t\t\t\t\t\t\t+ \"` as Spring converter, it will be ignored.\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconverters.add(clazz.getDeclaredConstructor().newInstance());\n\t\t\t}\n\t\t\tcatch (Exception ex) {\n\t\t\t\tString message = ex.getMessage();\n\t\t\t\tif (ex instanceof ClassNotFoundException) {\n\t\t\t\t\tmessage = \"Class `\" + cn + \"` not found\";\n\t\t\t\t}\n\t\t\t\tthis.messager.printMessage(Diagnostic.Kind.MANDATORY_WARNING,\n\t\t\t\t\t\t\"Cannot load converter of type `\" + cn + \"`, it will be ignored: \" + message + \".\");\n\t\t\t}\n\t\t});\n\t\treturn new Neo4jConversions(converters);\n\t}\n\n\t@Override\n\tpublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {\n\t\tif (annotations.isEmpty()) {\n\t\t\treturn false;\n\t\t}\n\n\t\tMap<TypeElement, NodeModelBuilder> nodeBuilders = populateListOfNodes(\n\t\t\t\tgetTypesAnnotatedWith(this.nodeAnnotationType, roundEnv));\n\t\tMap<TypeElement, Map.Entry<TypeElement, List<PropertyDefinition>>> relationshipProperties = collectRelationshipProperties(\n\t\t\t\troundEnv);\n\t\tMap<NodeModelBuilder, List<Element>> relationshipFields = populateNodePropertiesAndCollectRelationshipFields(\n\t\t\t\tnodeBuilders);\n\t\tMap<String, List<RelationshipModelBuilder>> relationshipBuilders = populateListOfRelationships(\n\t\t\t\tcomputeRelationshipDefinitions(relationshipFields, relationshipProperties, nodeBuilders));\n\n\t\tList<ModelBuilder<?>> allBuilders = new ArrayList<>(nodeBuilders.values());\n\t\trelationshipBuilders.values().forEach(allBuilders::addAll);\n\t\ttry {\n\t\t\twriteSourceFiles(allBuilders);\n\t\t}\n\t\tcatch (IOException ex) {\n\t\t\tthis.messager.printMessage(Diagnostic.Kind.ERROR, \"Could not write source files: \" + ex.getMessage());\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t@Override\n\tprotected Collection<String> getLabel(TypeElement annotatedClass) {\n\n\t\tNode nodeAnnotation = annotatedClass.getAnnotation(Node.class);\n\t\tSet<String> labels = new LinkedHashSet<>();\n\t\tConsumer<String> addLabel = label -> {\n\t\t\tif (!label.isEmpty()) {\n\t\t\t\tlabels.add(label);\n\t\t\t}\n\t\t};\n\n\t\taddLabel.accept(nodeAnnotation.primaryLabel());\n\t\tArrays.stream(nodeAnnotation.value()).forEach(addLabel);\n\t\tArrays.stream(nodeAnnotation.labels()).forEach(addLabel);\n\n\t\tif (labels.isEmpty()) {\n\t\t\taddLabel.accept(annotatedClass.getSimpleName().toString());\n\t\t}\n\t\treturn Collections.unmodifiableCollection(labels);\n\t}\n\n\t/**\n\t * Collects classes annotated with {@code @RelationshipProperties}.\n\t * @param roundEnvironment the current environment\n\t * @return a map from the other end of the relationship (target node) to the\n\t * properties of the relationship\n\t */\n\tprivate Map<TypeElement, Map.Entry<TypeElement, List<PropertyDefinition>>> collectRelationshipProperties(\n\t\t\tRoundEnvironment roundEnvironment) {\n\n\t\tMap<TypeElement, Map.Entry<TypeElement, List<PropertyDefinition>>> result = new HashMap<>();\n\t\tSet<TypeElement> relationshipProperties = getTypesAnnotatedWith(this.relationshipPropertiesAnnotationType,\n\t\t\t\troundEnvironment);\n\t\trelationshipProperties.forEach(e -> {\n\t\t\tList<PropertyDefinition> properties = new ArrayList<>();\n\t\t\tTypeElement actualTargetType = null;\n\t\t\tfor (Element enclosedElement : e.getEnclosedElements()) {\n\t\t\t\tif (!enclosedElement.getKind().isField()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tSet<Element> declaredAnnotations = enclosedElement.getAnnotationMirrors()\n\t\t\t\t\t.stream()\n\t\t\t\t\t.map(AnnotationMirror::getAnnotationType)\n\t\t\t\t\t.map(DeclaredType::asElement)\n\t\t\t\t\t.collect(Collectors.toSet());\n\t\t\t\tif (declaredAnnotations.contains(this.targetNodeAnnotationType)) {\n\n\t\t\t\t\tElement element = this.typeUtils.asElement(enclosedElement.asType());\n\t\t\t\t\tactualTargetType = element.accept(new TypeElementVisitor<>(Function.identity()), null);\n\t\t\t\t\tif (actualTargetType == null) {\n\t\t\t\t\t\tthis.messager.printMessage(Diagnostic.Kind.WARNING,\n\t\t\t\t\t\t\t\t\"Cannot resolve generic type, not generating a property for relationships referring to \"\n\t\t\t\t\t\t\t\t\t\t+ e.getQualifiedName(),\n\t\t\t\t\t\t\t\telement);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tproperties.add(asPropertyDefinition(enclosedElement));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (actualTargetType != null) {\n\t\t\t\tresult.put(e,\n\t\t\t\t\t\tnew AbstractMap.SimpleEntry<>(actualTargetType, Collections.unmodifiableList(properties)));\n\t\t\t}\n\t\t});\n\t\treturn Collections.unmodifiableMap(result);\n\t}\n\n\t@Override\n\tprotected PropertyDefinition asPropertyDefinition(Element e) {\n\n\t\tOptional<Property> optionalPropertyAnnotation = Optional.ofNullable(e.getAnnotation(Property.class));\n\n\t\tPropertyDefinition propertyDefinition;\n\t\tString fieldName = e.getSimpleName().toString();\n\n\t\tif (optionalPropertyAnnotation.isPresent()) {\n\t\t\tProperty propertyAnnotation = optionalPropertyAnnotation.get();\n\n\t\t\tString nameValue = propertyAnnotation.name();\n\t\t\tString valueValue = propertyAnnotation.value();\n\n\t\t\tif (!nameValue.isEmpty() && !valueValue.isEmpty()) {\n\t\t\t\tif (!nameValue.equals(valueValue)) {\n\t\t\t\t\tthis.messager.printMessage(Diagnostic.Kind.ERROR,\n\t\t\t\t\t\t\t\"Different @AliasFor mirror values for annotation [org.springframework.data.neo4j.core.schema.Property]!\",\n\t\t\t\t\t\t\te);\n\t\t\t\t}\n\t\t\t\tpropertyDefinition = PropertyDefinition.create(nameValue, fieldName);\n\t\t\t}\n\t\t\telse if (!nameValue.isEmpty()) {\n\t\t\t\tpropertyDefinition = PropertyDefinition.create(nameValue, fieldName);\n\t\t\t}\n\t\t\telse if (!valueValue.isEmpty()) {\n\t\t\t\tpropertyDefinition = PropertyDefinition.create(valueValue, fieldName);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpropertyDefinition = PropertyDefinition.create(fieldName, null);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tpropertyDefinition = PropertyDefinition.create(fieldName, null);\n\t\t}\n\n\t\treturn propertyDefinition;\n\t}\n\n\t@Override\n\tprotected RelationshipPropertyDefinition asRelationshipDefinition(NodeModelBuilder owner, Element e,\n\t\t\tMap<TypeElement, Map.Entry<TypeElement, List<PropertyDefinition>>> relationshipProperties,\n\t\t\tMap<TypeElement, NodeModelBuilder> nodeBuilders) {\n\n\t\tOptional<Relationship> optionalRelationshipAnnotation = Optional\n\t\t\t.ofNullable(e.getAnnotation(Relationship.class));\n\n\t\tString fieldName = e.getSimpleName().toString();\n\n\t\t// Default SDN 6 is outgoing. SDN 6 does not support undirected.\n\t\tboolean isIncoming = false;\n\n\t\tString relationshipType;\n\t\tif (optionalRelationshipAnnotation.isPresent()) {\n\t\t\tRelationship relationshipAnnotation = optionalRelationshipAnnotation.get();\n\n\t\t\tString typeValue = relationshipAnnotation.type();\n\t\t\tString valueValue = relationshipAnnotation.value();\n\n\t\t\tisIncoming = relationshipAnnotation.direction() == Relationship.Direction.INCOMING;\n\n\t\t\tif (!typeValue.isEmpty() && !valueValue.isEmpty()) {\n\t\t\t\tif (!typeValue.equals(valueValue)) {\n\t\t\t\t\tthis.messager.printMessage(Diagnostic.Kind.ERROR,\n\t\t\t\t\t\t\t\"Different @AliasFor mirror values for annotation [org.springframework.data.neo4j.core.schema.Relationship]!\",\n\t\t\t\t\t\t\te);\n\t\t\t\t}\n\t\t\t\trelationshipType = typeValue;\n\t\t\t}\n\t\t\telse if (!typeValue.isEmpty()) {\n\t\t\t\trelationshipType = typeValue;\n\t\t\t}\n\t\t\telse if (!valueValue.isEmpty()) {\n\t\t\t\trelationshipType = valueValue;\n\t\t\t}\n\t\t\telse {\n\t\t\t\trelationshipType = fieldName;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\trelationshipType = fieldName;\n\t\t}\n\n\t\tDeclaredType declaredType = e.asType().accept(new SimpleTypeVisitor8<DeclaredType, Void>() {\n\t\t\t@Override\n\t\t\tpublic DeclaredType visitDeclared(DeclaredType t, Void unused) {\n\t\t\t\treturn t;\n\t\t\t}\n\t\t}, null);\n\n\t\tif (declaredType == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tTypeMirror relatedType = null;\n\t\tif (declaredType.getTypeArguments().size() == 1) {\n\t\t\trelatedType = declaredType.getTypeArguments().get(0);\n\t\t}\n\t\telse if (declaredType.getTypeArguments().isEmpty()) {\n\t\t\trelatedType = declaredType;\n\t\t}\n\n\t\tElement key = this.typeUtils.asElement(relatedType);\n\t\tNodeModelBuilder end = (key != null) ? nodeBuilders.get(key) : null;\n\t\tList<PropertyDefinition> properties = null;\n\t\tString optionalPropertyHolder = null;\n\n\t\tif (key == null) {\n\t\t\treturn null;\n\t\t}\n\t\telse if (end == null) {\n\t\t\tMap.Entry<TypeElement, List<PropertyDefinition>> typeAndProperties = relationshipProperties.get(key);\n\t\t\tif (typeAndProperties != null) {\n\t\t\t\toptionalPropertyHolder = key.toString();\n\t\t\t\tend = nodeBuilders.get(typeAndProperties.getKey());\n\t\t\t\tproperties = typeAndProperties.getValue();\n\t\t\t}\n\t\t}\n\n\t\tif (end == null) {\n\t\t\treturn null;\n\t\t}\n\t\telse if (isIncoming) {\n\t\t\treturn RelationshipPropertyDefinition.create(relationshipType, optionalPropertyHolder, fieldName, end,\n\t\t\t\t\towner, properties);\n\t\t}\n\t\telse {\n\t\t\treturn RelationshipPropertyDefinition.create(relationshipType, optionalPropertyHolder, fieldName, owner,\n\t\t\t\t\tend, properties);\n\t\t}\n\t}\n\n\t@Override\n\tprotected PropertiesAndRelationshipGrouping newPropertiesAndRelationshipGrouping() {\n\t\treturn new GroupPropertiesAndRelationships();\n\t}\n\n\t/**\n\t * Pre-groups fields into properties and relationships to avoid running the\n\t * association check multiple times.\n\t */\n\t@SuppressWarnings(\"squid:S110\") // Not something we need or can do anything about.\n\tclass GroupPropertiesAndRelationships extends ElementKindVisitor8<Map<FieldType, List<Element>>, Void>\n\t\t\timplements PropertiesAndRelationshipGrouping {\n\n\t\tprivate final Map<FieldType, List<Element>> result;\n\n\t\tGroupPropertiesAndRelationships() {\n\n\t\t\tfinal Map<FieldType, List<Element>> hlp = new EnumMap<>(FieldType.class);\n\t\t\thlp.put(FieldType.R, new ArrayList<>());\n\t\t\thlp.put(FieldType.P, new ArrayList<>());\n\t\t\tthis.result = Collections.unmodifiableMap(hlp);\n\t\t}\n\n\t\t@Override\n\t\tpublic void apply(Element element) {\n\t\t\telement.accept(this, null);\n\t\t}\n\n\t\t@Override\n\t\tpublic Map<FieldType, List<Element>> getResult() {\n\t\t\treturn this.result;\n\t\t}\n\n\t\t@Override\n\t\tpublic Map<FieldType, List<Element>> visitTypeAsRecord(TypeElement e, Void unused) {\n\t\t\t// We must overwrite this or visitUnknown() in case we encounter a record\n\t\t\treturn this.result;\n\t\t}\n\n\t\t@Override\n\t\tpublic Map<FieldType, List<Element>> visitRecordComponent(RecordComponentElement e, Void unused) {\n\t\t\treturn visitFieldOrRecordComponent(e);\n\t\t}\n\n\t\t@Override\n\t\tpublic Map<FieldType, List<Element>> visitVariableAsField(VariableElement e, Void unused) {\n\t\t\treturn visitFieldOrRecordComponent(e);\n\t\t}\n\n\t\tprivate Map<FieldType, List<Element>> visitFieldOrRecordComponent(Element e) {\n\t\t\tSet<Element> declaredAnnotations = e.getAnnotationMirrors()\n\t\t\t\t.stream()\n\t\t\t\t.map(AnnotationMirror::getAnnotationType)\n\t\t\t\t.map(DeclaredType::asElement)\n\t\t\t\t.collect(Collectors.toSet());\n\n\t\t\t// Skip internal ids\n\t\t\tif (isInternalId(e, declaredAnnotations)) {\n\t\t\t\treturn this.result;\n\t\t\t}\n\n\t\t\tthis.result.get(isAssociation(declaredAnnotations, e) ? FieldType.R : FieldType.P).add(e);\n\t\t\treturn this.result;\n\t\t}\n\n\t\tprivate boolean isInternalId(Element e, Set<Element> declaredAnnotations) {\n\n\t\t\tboolean idAnnotationPresent = declaredAnnotations.contains(SDN6AnnotationProcessor.this.sdcIdAnnotationType)\n\t\t\t\t\t|| declaredAnnotations.contains(SDN6AnnotationProcessor.this.sdnIdAnnotationType);\n\t\t\tif (!idAnnotationPresent) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn e.getAnnotationMirrors()\n\t\t\t\t.stream()\n\t\t\t\t.filter(m -> m.getAnnotationType()\n\t\t\t\t\t.asElement()\n\t\t\t\t\t.equals(SDN6AnnotationProcessor.this.generatedValueAnnotationType))\n\t\t\t\t.findFirst()\n\t\t\t\t.map(generatedValue -> isUsingInternalIdGenerator(e, generatedValue))\n\t\t\t\t.orElse(false);\n\t\t}\n\n\t\tprivate boolean isUsingInternalIdGenerator(Element e, AnnotationMirror generatedValue) {\n\n\t\t\tMap<String, ? extends AnnotationValue> values = generatedValue.getElementValues()\n\t\t\t\t.entrySet()\n\t\t\t\t.stream()\n\t\t\t\t.collect(Collectors.toMap(entry -> entry.getKey().getSimpleName().toString(), Map.Entry::getValue));\n\n\t\t\tDeclaredType generatorClassValue = values.containsKey(\"generatorClass\")\n\t\t\t\t\t? (DeclaredType) values.get(\"generatorClass\").getValue() : null;\n\t\t\tDeclaredType valueValue = values.containsKey(\"value\") ? (DeclaredType) values.get(\"value\").getValue()\n\t\t\t\t\t: null;\n\n\t\t\tString name = null;\n\t\t\tif (generatorClassValue != null && valueValue != null && !generatorClassValue.equals(valueValue)) {\n\t\t\t\tSDN6AnnotationProcessor.this.messager.printMessage(Diagnostic.Kind.ERROR,\n\t\t\t\t\t\t\"Different @AliasFor mirror values for annotation [org.springframework.data.neo4j.core.schema.GeneratedValue]!\",\n\t\t\t\t\t\te);\n\t\t\t}\n\t\t\telse if (generatorClassValue != null) {\n\t\t\t\tname = generatorClassValue.toString();\n\t\t\t}\n\t\t\telse if (valueValue != null) {\n\t\t\t\tname = valueValue.toString();\n\t\t\t}\n\n\t\t\t// The defaults will not be materialized\n\t\t\treturn (name == null\n\t\t\t\t\t|| \"org.springframework.data.neo4j.core.schema.GeneratedValue.InternalIdGenerator\".equals(name))\n\t\t\t\t\t&& VALID_GENERATED_ID_TYPES.contains(e.asType().toString());\n\t\t}\n\n\t\t/**\n\t\t * Reassembles\n\t\t * org.springframework.data.neo4j.core.mapping.DefaultNeo4jPersistentProperty#isAssociation.\n\t\t * @param declaredAnnotations the set of annotations declared on the given field\n\t\t * @param field a variable element describing a field. No further checks done if\n\t\t * this is true or not\n\t\t * @return true if this field is an association\n\t\t */\n\t\tprivate boolean isAssociation(Set<Element> declaredAnnotations, Element field) {\n\t\t\tTypeMirror typeMirrorOfField = field.asType();\n\n\t\t\tif (declaredAnnotations.contains(SDN6AnnotationProcessor.this.relationshipAnnotationType)) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (declaredAnnotations.contains(SDN6AnnotationProcessor.this.propertyAnnotationType)) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tboolean isTargetNodeOrComposite = declaredAnnotations\n\t\t\t\t.contains(SDN6AnnotationProcessor.this.targetNodeAnnotationType)\n\t\t\t\t\t|| declaredAnnotations.contains(SDN6AnnotationProcessor.this.compositePropertyAnnotationType);\n\n\t\t\tBooleanSupplier simpleTypeOrCustomWriteTarget = () -> {\n\t\t\t\ttry {\n\t\t\t\t\tString className = typeMirrorOfField.accept(new SimpleTypeVisitor8<String, Void>() {\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic String visitPrimitive(PrimitiveType t, Void unused) {\n\t\t\t\t\t\t\t// While I could use the fact that this is a primitive\n\t\t\t\t\t\t\t// directly, I'd rather stick with the\n\t\t\t\t\t\t\t// wrapper class so that in turn this can be passed on to the\n\t\t\t\t\t\t\t// Spring infrastructure.\n\t\t\t\t\t\t\treturn SDN6AnnotationProcessor.this.typeUtils.boxedClass(t).getQualifiedName().toString();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic String visitDeclared(DeclaredType t, Void unused) {\n\t\t\t\t\t\t\treturn t.asElement().accept(new TypeElementVisitor<>(newTypeElementNameFunction()), null);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, null);\n\t\t\t\t\t// This is likely to fail for everything but primitives as the\n\t\t\t\t\t// associated thing is currently compiled\n\t\t\t\t\tClass<?> fieldType = Class.forName(className);\n\t\t\t\t\treturn Neo4jSimpleTypes.HOLDER.isSimpleType(fieldType)\n\t\t\t\t\t\t\t|| SDN6AnnotationProcessor.this.conversions.hasCustomWriteTarget(fieldType);\n\t\t\t\t}\n\t\t\t\tcatch (ClassNotFoundException ex) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// They will be converted anyway\n\t\t\tif (describesEnum(typeMirrorOfField)) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn !(isTargetNodeOrComposite\n\t\t\t\t\t|| declaredAnnotations.contains(SDN6AnnotationProcessor.this.convertWithAnnotationType)\n\t\t\t\t\t|| simpleTypeOrCustomWriteTarget.getAsBoolean());\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/main/java/org/neo4j/cypherdsl/codegen/sdn6/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Contains the SDN6+ annotation processor that creates a static metamodel for SDN\n * annotated classes.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6;\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/main/resources/META-INF/services/javax.annotation.processing.Processor",
    "content": "org.neo4j.cypherdsl.codegen.sdn6.SDN6AnnotationProcessor\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/SDN6AnnotationProcessorTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6;\n\nimport java.io.IOException;\nimport java.io.UncheckedIOException;\nimport java.util.Arrays;\nimport java.util.HashSet;\n\nimport javax.tools.JavaFileObject;\nimport javax.tools.ToolProvider;\n\nimport com.google.testing.compile.Compilation;\nimport com.google.testing.compile.CompilationSubject;\nimport com.google.testing.compile.Compiler;\nimport com.google.testing.compile.JavaFileObjects;\nimport org.jspecify.annotations.NonNull;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.converter.ArgumentConversionException;\nimport org.junit.jupiter.params.converter.ConvertWith;\nimport org.junit.jupiter.params.converter.SimpleArgumentConverter;\nimport org.junit.jupiter.params.provider.CsvSource;\nimport org.junit.jupiter.params.provider.ValueSource;\n\nimport org.springframework.core.convert.converter.Converter;\nimport org.springframework.core.io.Resource;\nimport org.springframework.core.io.support.PathMatchingResourcePatternResolver;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n *\n */\nclass SDN6AnnotationProcessorTests {\n\n\t/**\n\t * We have Spring on the Classpath anyway... So not reinvent the wheel for finding the\n\t * resources.\n\t */\n\tprivate static final PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();\n\n\tstatic Compiler getCompiler(String release, Object... options) {\n\n\t\tString ts = \"-Aorg.neo4j.cypherdsl.codegen.timestamp=2019-09-21T21:21:00+01:00\";\n\t\tObject[] defaultOptions;\n\n\t\tif (ToolProvider.getSystemJavaCompiler().isSupportedOption(\"--release\") >= 0) {\n\t\t\t// release 8 deprecated since Java 21, surprised with -options\n\t\t\tdefaultOptions = new Object[] { \"-Xlint:-options\", ts, \"--release\", release };\n\t\t}\n\t\telse if (\"8\".equals(release)) {\n\t\t\tdefaultOptions = new Object[] { ts, \"-source\", \"8\", \"-target\", \"8\" };\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException(\"Release %s not supported for testing\".formatted(release));\n\t\t}\n\n\t\tObject[] finalOptions = new Object[options.length + defaultOptions.length];\n\t\tSystem.arraycopy(defaultOptions, 0, finalOptions, 0, defaultOptions.length);\n\t\tSystem.arraycopy(options, 0, finalOptions, defaultOptions.length, options.length);\n\n\t\treturn Compiler.javac().withOptions(finalOptions);\n\t}\n\n\tJavaFileObject[] getJavaResources(String base) {\n\n\t\ttry {\n\t\t\tResource[] resources = resourceResolver.getResources(base + \"/**/*.java\");\n\t\t\tJavaFileObject[] result = new JavaFileObject[resources.length];\n\t\t\tfor (int i = 0; i < resources.length; i++) {\n\t\t\t\tresult[i] = JavaFileObjects.forResource(resources[i].getURL());\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t\tcatch (IOException ex) {\n\t\t\tthrow new UncheckedIOException(ex);\n\t\t}\n\t}\n\n\t@ValueSource(strings = { \"foo\", \"org.neo4j.cypherdsl.codegen.sdn6.SDN6AnnotationProcessorTest$SomeConverter\",\n\t\t\t\"org.neo4j.cypherdsl.codegen.sdn6.models.enums_and_inner_classes.InnerInnerClassConverter\" })\n\t@ParameterizedTest\n\tvoid shouldNotFailWithInvalidConverters(String converter) {\n\t\tCompilation compilation = getCompiler(\"8\",\n\t\t\t\t\"-Aorg.neo4j.cypherdsl.codegen.sdn.custom_converter_classes=\" + converter)\n\t\t\t.withProcessors(new SDN6AnnotationProcessor())\n\t\t\t.compile(getJavaResources(\"org/neo4j/cypherdsl/codegen/sdn6/models/simple\"));\n\n\t\tCompilationSubject.assertThat(compilation).succeeded();\n\t\tString expectedMessage;\n\t\tif (converter.endsWith(\"InnerInnerClassConverter\")) {\n\t\t\texpectedMessage = \"Cannot use dedicated Neo4j persistent property converter of type `\" + converter\n\t\t\t\t\t+ \"` as Spring converter, it will be ignored.\";\n\t\t}\n\t\telse {\n\t\t\texpectedMessage = \"Cannot load converter of type `\" + converter + \"`, it will be ignored: \";\n\t\t}\n\t\tCompilationSubject.assertThat(compilation).hadWarningContaining(expectedMessage);\n\t}\n\n\t@Test\n\tvoid shouldRecognizeGlobalConvertersOnInnerClasses() {\n\t\tCompilation compilation = getCompiler(\"8\",\n\t\t\t\t\"-Aorg.neo4j.cypherdsl.codegen.sdn.custom_converter_classes=org.neo4j.cypherdsl.codegen.sdn6.models.enums_and_inner_classes.SpringBasedConverter\")\n\t\t\t.withProcessors(new SDN6AnnotationProcessor())\n\t\t\t.compile(getJavaResources(\"org/neo4j/cypherdsl/codegen/sdn6/models/enums_and_inner_classes\"));\n\n\t\tCompilationSubject.assertThat(compilation).succeeded();\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(\"org.neo4j.cypherdsl.codegen.sdn6.models.enums_and_inner_classes.ConnectorTransport_\")\n\t\t\t.hasSourceEquivalentTo(\n\t\t\t\t\tJavaFileObjects.forResource(\"enums_and_inner_classes/ConnectorTransportWithGlobalConverter_.java\"));\n\t}\n\n\t@CsvSource({\n\t\t\t\"8, ids, 'InternalGeneratedId, InternalGeneratedIdWithSpringId, ExternalGeneratedId, ExternalGeneratedIdImplicit, InternalGeneratedPrimitiveLongId',\",\n\t\t\t\"8, simple, 'Person, Movie, ActedIn, Follows, Directed, Produced, Src, Target2, Rel21, Rel22',\",\n\t\t\t\"8, labels, 'LabelOnNode1, LabelOnNode2, LabelOnNode3, MultipleLabels1, MultipleLabels2, MultipleLabels3', nodeswithdifferentlabelannotations\",\n\t\t\t\"8, same_properties_for_rel_type, 'Person, Movie, Play, ActedIn', \",\n\t\t\t\"8, different_properties_for_rel_type, 'Person, Movie, Play, ActedInPlay, ActedInMovie', \",\n\t\t\t\"8, same_rel_different_target, 'Person, Movie, Book, Wrote', \",\n\t\t\t\"8, same_rel_different_source, 'Person, Movie, Book, Wrote', \",\n\t\t\t\"8, same_rel_mixed, 'Person, Movie, Book, Wrote', \",\n\t\t\t\"8, same_rel_mixed_different_directions, 'Person, Movie, Book, Wrote', \",\n\t\t\t\"8, abstract_rels, 'Person, Movie, Directed',\", \"8, primitives, 'Connector', \",\n\t\t\t\"8, enums_and_inner_classes, 'ConnectorTransport', \",\n\t\t\t\"8, related_classes_not_on_cp_like_in_reallife, 'Movie, Person, Directed', \",\n\t\t\t\"8, self_referential, 'Example, BelongsTo', \",\n\t\t\t\"17, records, 'NodeWithRecordProperties, RecordAsRelationship, RecordTarget', \" })\n\t@ParameterizedTest\n\tvoid validSourceFiles(String release, String scenario, @ConvertWith(StringArrayConverter.class) String[] expected,\n\t\t\tString subpackage) {\n\n\t\tvar options = \"\"\"\n\t\t\t\t-Aorg.neo4j.cypherdsl.codegen.excludes=\n\t\t\t\t  org.neo4j.cypherdsl.codegen.sdn6.models.simple.TotallyIgnored,\n\t\t\t\t  org.neo4j.cypherdsl.codegen.sdn6.models.simple.Target,\n\t\t\t\t  org.neo4j.cypherdsl.codegen.sdn6.models.simple.Edge,\n\t\t\t\t  org.neo4j.cypherdsl.codegen.sdn6.models.simple.Target3,\n\t\t\t\t\"\"\";\n\t\tCompilation compilation = getCompiler(release, options).withProcessors(new SDN6AnnotationProcessor())\n\t\t\t.compile(getJavaResources(\"org/neo4j/cypherdsl/codegen/sdn6/models/\" + scenario));\n\n\t\tCompilationSubject.assertThat(compilation).succeeded();\n\t\tif (\"abstract_rels\".equals(scenario)) {\n\t\t\tCompilationSubject.assertThat(compilation)\n\t\t\t\t.hadWarningContaining(\n\t\t\t\t\t\t\"Cannot resolve generic type, not generating a property for relationships referring to org.neo4j.cypherdsl.codegen.sdn6.models.abstract_rels.Actor\");\n\t\t}\n\t\telse {\n\t\t\tCompilationSubject.assertThat(compilation).hadWarningCount(0);\n\t\t}\n\n\t\tvar allExpectedNames = new HashSet<String>();\n\t\tfor (String expectedSourceFile : expected) {\n\t\t\tvar typeName = scenario + \".\" + ((subpackage != null) ? subpackage + \".\" : \"\") + expectedSourceFile + \"_\";\n\t\t\tvar resourceName = typeName.replaceAll(\"\\\\.\", \"/\") + \".java\";\n\t\t\tCompilationSubject.assertThat(compilation)\n\t\t\t\t.generatedSourceFile(\"org.neo4j.cypherdsl.codegen.sdn6.models.\" + typeName)\n\t\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(resourceName));\n\t\t\tallExpectedNames.add(resourceName);\n\t\t}\n\t\tvar generated = compilation.generatedSourceFiles()\n\t\t\t.stream()\n\t\t\t.map(JavaFileObject::getName)\n\t\t\t.map(name -> name.substring(name.lastIndexOf(scenario)))\n\t\t\t.toList();\n\t\tassertThat(generated).containsOnly(allExpectedNames.toArray(String[]::new));\n\t}\n\n\t@Test\n\tvoid bidiMappingsForStaticMetaModelAreFiltered() {\n\n\t\tvar resources = \"org/neo4j/cypherdsl/codegen/sdn6/models/bidi\";\n\t\tCompilation compilation = getCompiler(\"17\").withProcessors(new SDN6AnnotationProcessor())\n\t\t\t.compile(getJavaResources(resources));\n\n\t\tCompilationSubject.assertThat(compilation).succeeded();\n\t\tCompilationSubject.assertThat(compilation).hadWarningCount(1);\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.hadWarningContaining(\n\t\t\t\t\t\"Bidirectional mappings are not supported for the static meta model (Relationship: HAS_PATH_POINTS)\");\n\n\t\tvar basePackage = \"org.neo4j.cypherdsl.codegen.sdn6.models.bidi.\";\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"Element_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"bidi/Element_.java\"));\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"Point_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"bidi/Point_.java\"));\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"HasPathPoints_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"bidi/HasPathPoints_.java\"));\n\t}\n\n\t@Test\n\tvoid sameRelDifferentPackageShouldMakeSense() {\n\n\t\tvar resources = \"org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_package\";\n\t\tCompilation compilation = getCompiler(\"17\").withProcessors(new SDN6AnnotationProcessor())\n\t\t\t.compile(getJavaResources(resources));\n\n\t\tCompilationSubject.assertThat(compilation).succeeded();\n\t\tCompilationSubject.assertThat(compilation).hadWarningCount(0);\n\n\t\tvar basePackage = \"org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.\";\n\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"domain.Company_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"same_rel_different_package/Company_.java\"));\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"domain.DomainEntity_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"same_rel_different_package/DomainEntity_.java\"));\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"domain.DomainEntity2_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"same_rel_different_package/DomainEntity2_.java\"));\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"domain.Place_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"same_rel_different_package/Place_.java\"));\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"domain.In_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"same_rel_different_package/In1_.java\"));\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"domain.Uses_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"same_rel_different_package/Uses1_.java\"));\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"domain.Abuses_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"same_rel_different_package/Abuses1_.java\"));\n\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"application.CompanyModel_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"same_rel_different_package/CompanyModel_.java\"));\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"application.PlaceModel_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"same_rel_different_package/PlaceModel_.java\"));\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"application.In_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"same_rel_different_package/In2_.java\"));\n\t\tCompilationSubject.assertThat(compilation)\n\t\t\t.generatedSourceFile(basePackage + \"application.Uses_\")\n\t\t\t.hasSourceEquivalentTo(JavaFileObjects.forResource(\"same_rel_different_package/Uses2_.java\"));\n\t}\n\n\t/**\n\t * A test converter spotting a non-default constructor, so that it cannot be\n\t * instantiated\n\t */\n\t@SuppressWarnings(\"unused\")\n\tstatic class SomeConverter implements Converter<String, String> {\n\n\t\tSomeConverter(@SuppressWarnings(\"unused\") boolean ignoreMe) {\n\t\t}\n\n\t\t@Override\n\t\tpublic String convert(@NonNull String source) {\n\t\t\treturn new StringBuilder(source).reverse().toString();\n\t\t}\n\n\t}\n\n\tstatic class StringArrayConverter extends SimpleArgumentConverter {\n\n\t\t@Override\n\t\tprotected Object convert(Object source, Class<?> targetType) throws ArgumentConversionException {\n\t\t\tif (source instanceof String && String[].class.isAssignableFrom(targetType)) {\n\t\t\t\treturn Arrays.stream(((String) source).split(\"\\\\s*,\\\\s*\")).map(String::trim).toArray(String[]::new);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"Conversion from \" + source.getClass() + \" to \" + targetType + \" not supported.\");\n\t\t\t}\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/abstract_rels/Actor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.abstract_rels;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.RelationshipProperties;\nimport org.springframework.data.neo4j.core.schema.TargetNode;\n\n/**\n * Example type.\n *\n * @param <T> a type\n * @author Michael J. Simons\n */\n@RelationshipProperties\npublic class Actor<T> {\n\n\t@TargetNode\n\tprivate final T person;\n\n\tprivate List<String> roles = new ArrayList<>();\n\n\tpublic Actor(T person) {\n\t\tthis.person = person;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/abstract_rels/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.abstract_rels;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Property;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\t@Property(\"tagline\")\n\tprivate final String description;\n\n\t@Relationship(type = \"ACTED_IN\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Actor<Person>> actors = new ArrayList<>();\n\n\t@Relationship(type = \"DIRECTED\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Person> directors = new ArrayList<>();\n\n\tpublic Movie(String title, String description) {\n\t\tthis.title = title;\n\t\tthis.description = description;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/abstract_rels/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.abstract_rels;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Person {\n\n\t@Id\n\tprivate String name;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/bidi/Element.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.bidi;\n\nimport java.util.List;\n\nimport org.springframework.data.annotation.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n@Node\npublic class Element {\n\n\t@Id\n\tLong id;\n\n\t@Relationship(type = \"HAS_PATH_POINTS\", direction = Relationship.Direction.OUTGOING)\n\tprivate List<Point> points;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/bidi/Point.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.bidi;\n\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n@Node\npublic class Point {\n\n\t@Relationship(type = \"HAS_PATH_POINTS\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Element> element;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/different_properties_for_rel_type/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.different_properties_for_rel_type;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Movie {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n\tprivate String title;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/different_properties_for_rel_type/MovieAppearance.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.different_properties_for_rel_type;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.RelationshipProperties;\nimport org.springframework.data.neo4j.core.schema.TargetNode;\n\n/**\n * @author Michael J. Simons\n */\n@RelationshipProperties\npublic class MovieAppearance {\n\n\t@TargetNode\n\tprivate Movie movie;\n\n\tprivate List<String> roles = new ArrayList<>();\n\n\tprivate String stuntDouble;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/different_properties_for_rel_type/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.different_properties_for_rel_type;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Person {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n\tprivate String name;\n\n\tprivate Integer born;\n\n\t@Relationship(type = \"ACTED_IN\")\n\tprivate List<MovieAppearance> movies = new ArrayList<>();\n\n\t@Relationship(type = \"ACTED_IN\")\n\tprivate List<TheaterAppearance> plays = new ArrayList<>();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/different_properties_for_rel_type/Play.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.different_properties_for_rel_type;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Play {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n\tprivate String title;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/different_properties_for_rel_type/TheaterAppearance.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.different_properties_for_rel_type;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.RelationshipProperties;\nimport org.springframework.data.neo4j.core.schema.TargetNode;\n\n/**\n * @author Michael J. Simons\n */\n@RelationshipProperties\npublic class TheaterAppearance {\n\n\t@TargetNode\n\tprivate Play play;\n\n\tprivate List<String> roles = new ArrayList<>();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/different_properties_for_rel_type/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * The same relationship type ACTED_IN is used with different properties. Multiple types\n * needs to be generated.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.different_properties_for_rel_type;\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/enums_and_inner_classes/ConnectorTransport.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.enums_and_inner_classes;\n\nimport org.springframework.data.neo4j.core.convert.ConvertWith;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node(labels = \"Transport\")\npublic class ConnectorTransport {\n\n\t@Id\n\tprivate final ConnectorTransportType value;\n\n\tprivate OtherEnum otherEnum;\n\n\t@ConvertWith(converter = InnerInnerClassConverter.class)\n\tprivate InnerClass.InnerInnerClass innerInnerClass;\n\n\tprivate InnerClass.InnerInnerClass innerInnerClassButWithoutConverter;\n\n\tpublic ConnectorTransport(ConnectorTransportType value) {\n\t\tthis.value = value;\n\t}\n\n\t/**\n\t * Some enum\n\t */\n\tpublic enum ConnectorTransportType {\n\n\t\tHTTP, BOLT\n\n\t}\n\n\t/**\n\t * An inner class\n\t */\n\tpublic static class InnerClass {\n\n\t\t/**\n\t\t * With a nested inner class (used to check whether the recursive algorithm stops\n\t\t * at some point)\n\t\t */\n\t\tpublic static class InnerInnerClass {\n\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/enums_and_inner_classes/InnerInnerClassConverter.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.enums_and_inner_classes;\n\nimport org.neo4j.cypherdsl.codegen.sdn6.models.enums_and_inner_classes.ConnectorTransport.InnerClass.InnerInnerClass;\nimport org.neo4j.driver.Value;\n\nimport org.springframework.data.neo4j.core.convert.Neo4jPersistentPropertyConverter;\n\n/**\n * @author Michael J. Simons\n */\npublic class InnerInnerClassConverter implements Neo4jPersistentPropertyConverter<InnerInnerClass> {\n\n\t@Override\n\tpublic Value write(InnerInnerClass innerInnerClass) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic InnerInnerClass read(Value value) {\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/enums_and_inner_classes/OtherEnum.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.enums_and_inner_classes;\n\n/**\n * @author Michael J. Simons\n */\npublic enum OtherEnum {\n\n\tA, B\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/enums_and_inner_classes/SpringBasedConverter.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.enums_and_inner_classes;\n\nimport org.springframework.core.convert.converter.Converter;\n\n/**\n * Will be registered for some tests with the annotation processor.\n *\n * @author Michael J. Simons\n */\npublic class SpringBasedConverter implements Converter<ConnectorTransport.InnerClass.InnerInnerClass, String> {\n\n\t@Override\n\tpublic String convert(ConnectorTransport.InnerClass.InnerInnerClass source) {\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/ids/ExternalGeneratedId.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.ids;\n\nimport java.util.UUID;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class ExternalGeneratedId {\n\n\t@Id\n\t@GeneratedValue(GeneratedValue.UUIDGenerator.class)\n\tprivate UUID id;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/ids/ExternalGeneratedIdImplicit.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.ids;\n\nimport java.util.UUID;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class ExternalGeneratedIdImplicit {\n\n\t@Id\n\t@GeneratedValue\n\tprivate UUID id;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/ids/InternalGeneratedId.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.ids;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class InternalGeneratedId {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/ids/InternalGeneratedIdWithSpringId.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.ids;\n\nimport org.springframework.data.annotation.Id;\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class InternalGeneratedIdWithSpringId {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/ids/InternalGeneratedPrimitiveLongId.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.ids;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class InternalGeneratedPrimitiveLongId {\n\n\t@Id\n\t@GeneratedValue\n\tprivate long id;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/labels/NodesWithDifferentLabelAnnotations.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.labels;\n\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * Tests various ways to define labels. The generated classes will end up in a subpackage\n * as they are static, inner classes.\n *\n * @author Michael J. Simons\n */\npublic class NodesWithDifferentLabelAnnotations {\n\n\t@Node(\"ALabel\")\n\tstatic class LabelOnNode1 {\n\n\t}\n\n\t@SuppressWarnings(\"checkstyle:AnnotationUseStyle\")\n\t@Node(value = \"ALabel\")\n\tstatic class LabelOnNode2 {\n\n\t}\n\n\t@Node(primaryLabel = \"ALabel\")\n\tstatic class LabelOnNode3 {\n\n\t}\n\n\t@SuppressWarnings(\"checkstyle:AnnotationUseStyle\")\n\t@Node(value = { \"Label1\", \"Label2\" })\n\tstatic class MultipleLabels1 {\n\n\t}\n\n\t@Node(primaryLabel = \"PL\", value = { \"Label1\", \"Label2\" })\n\tstatic class MultipleLabels2 {\n\n\t}\n\n\t@Node(primaryLabel = \"PL\", value = { \"Label1\", \"Label2\" }, labels = \"Some more\")\n\tstatic class MultipleLabels3 {\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/primitives/Connector.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.primitives;\n\nimport java.util.UUID;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Florent Biville\n * @author Michael J. Simons\n */\n@Node(primaryLabel = \"Connector\")\npublic class Connector {\n\n\t@Id\n\t@GeneratedValue(GeneratedValue.UUIDGenerator.class)\n\tprivate UUID id;\n\n\tprivate final String uri;\n\n\tprivate final boolean official;\n\n\tprivate int anInt;\n\n\tprivate float aFloat;\n\n\tprivate double aDouble;\n\n\t@Relationship\n\tprivate char aChar;\n\n\tpublic Connector(String uri, boolean official) {\n\t\tthis.uri = uri;\n\t\tthis.official = official;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/records/NodeWithRecordProperties.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.records;\n\nimport org.springframework.data.neo4j.core.convert.ConvertWith;\nimport org.springframework.data.neo4j.core.convert.Neo4jPersistentPropertyConverter;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Property;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * Random test class.\n */\n@Node\npublic class NodeWithRecordProperties {\n\n\t@Id\n\tprivate String id;\n\n\t@ConvertWith(converter = RecordConverter.class)\n\tprivate RecordAsProperty recordAsPropertyWithConversion;\n\n\t@Property\n\tprivate RecordAsProperty yoloingNoConversion;\n\n\t// Inner types for relationships are not supported\n\t@Relationship\n\tprivate RecordTarget recordAsRelationship;\n\n\trecord RecordAsProperty(String value) {\n\t}\n\n\tabstract static class RecordConverter implements Neo4jPersistentPropertyConverter<RecordAsProperty> {\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/records/RecordTarget.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.records;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * Random test class.\n *\n * @param value a value\n */\n@Node\npublic record RecordTarget(@Id String value) {\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_properties_for_rel_type/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_properties_for_rel_type;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Movie {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n\tprivate String title;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_properties_for_rel_type/MovieAppearance.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_properties_for_rel_type;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.RelationshipProperties;\nimport org.springframework.data.neo4j.core.schema.TargetNode;\n\n/**\n * @author Michael J. Simons\n */\n@RelationshipProperties\npublic class MovieAppearance {\n\n\t@TargetNode\n\tprivate Movie movie;\n\n\tprivate List<String> roles = new ArrayList<>();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_properties_for_rel_type/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_properties_for_rel_type;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Person {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n\tprivate String name;\n\n\tprivate Integer born;\n\n\t@Relationship(type = \"ACTED_IN\")\n\tprivate List<MovieAppearance> movies = new ArrayList<>();\n\n\t@Relationship(type = \"ACTED_IN\")\n\tprivate List<TheaterAppearance> plays = new ArrayList<>();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_properties_for_rel_type/Play.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_properties_for_rel_type;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Play {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n\tprivate String title;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_properties_for_rel_type/TheaterAppearance.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_properties_for_rel_type;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.RelationshipProperties;\nimport org.springframework.data.neo4j.core.schema.TargetNode;\n\n/**\n * @author Michael J. Simons\n */\n@RelationshipProperties\npublic class TheaterAppearance {\n\n\t@TargetNode\n\tprivate Play play;\n\n\tprivate List<String> roles = new ArrayList<>();\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_properties_for_rel_type/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * The same relationship type ACTED_IN is used with same properties. Only one type needs\n * to be generated.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_properties_for_rel_type;\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_package/application/CompanyModel.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.application;\n\nimport org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain.DomainEntity;\n\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n@Node(\"Company\")\npublic class CompanyModel {\n\n\t@Relationship(type = \"IN\", direction = Relationship.Direction.OUTGOING)\n\tprivate PlaceModel place;\n\n\t@Relationship(type = \"USES\", direction = Relationship.Direction.OUTGOING)\n\tprivate DomainEntity domainEntity;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_package/application/PlaceModel.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.application;\n\nimport org.springframework.data.neo4j.core.schema.Node;\n\n@Node(\"Place\")\npublic class PlaceModel {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_package/domain/Company.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain;\n\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n@Node(primaryLabel = \"Company\", labels = { \"CompanyId\" })\npublic class Company {\n\n\t@Relationship(type = \"IN\", direction = Relationship.Direction.OUTGOING)\n\tprivate Place place;\n\n\t@Relationship(type = \"USES\", direction = Relationship.Direction.OUTGOING)\n\tprivate DomainEntity domainEntity;\n\n\t@Relationship(type = \"USES\", direction = Relationship.Direction.OUTGOING)\n\tprivate DomainEntity domainEntity2;\n\n\t@Relationship(type = \"ABUSES\", direction = Relationship.Direction.OUTGOING)\n\tprivate DomainEntity de1;\n\n\t@Relationship(type = \"ABUSES\", direction = Relationship.Direction.OUTGOING)\n\tprivate DomainEntity2 de2;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_package/domain/DomainEntity.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain;\n\nimport org.springframework.data.neo4j.core.schema.Node;\n\n@Node\npublic class DomainEntity {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_package/domain/DomainEntity2.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain;\n\nimport org.springframework.data.neo4j.core.schema.Node;\n\n@Node\npublic class DomainEntity2 {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_package/domain/Place.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain;\n\nimport org.springframework.data.neo4j.core.schema.Node;\n\n@Node\npublic class Place {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_source/Book.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_source;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Book {\n\n\t@Id\n\tprivate final String title;\n\n\t@Relationship(value = \"WROTE\", direction = Relationship.Direction.INCOMING)\n\tprivate Person writtenBy;\n\n\tBook(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_source/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_source;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\t@Relationship(value = \"WROTE\", direction = Relationship.Direction.INCOMING)\n\tprivate Person writtenBy;\n\n\tMovie(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_source/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_source;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Person {\n\n\t@Id\n\tprivate String name;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_target/Book.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_target;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Book {\n\n\t@Id\n\tprivate final String title;\n\n\tBook(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_target/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_target;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\tMovie(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_target/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_target;\n\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Person {\n\n\t@Id\n\tprivate String name;\n\n\t@Relationship(\"WROTE\")\n\tprivate List<Movie> writtenMovies;\n\n\t@Relationship(\"WROTE\")\n\tprivate List<Book> writtenBooks;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_different_target/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Here the WROTE relationship targets different entities. It should be generated with a\n * wild card.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_target;\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_mixed/Book.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Book {\n\n\t@Id\n\tprivate final String title;\n\n\t@Relationship(value = \"WROTE\", direction = Relationship.Direction.INCOMING)\n\tprivate Person writtenBy;\n\n\tBook(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_mixed/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\tMovie(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_mixed/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed;\n\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Person {\n\n\t@Id\n\tprivate String name;\n\n\t@Relationship(\"WROTE\")\n\tprivate List<Movie> writtenMovies;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_mixed_different_directions/Book.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed_different_directions;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Book {\n\n\t@Id\n\tprivate final String title;\n\n\t// Makes not much sense, but one never knows\n\t@Relationship(value = \"WROTE\", direction = Relationship.Direction.OUTGOING)\n\tprivate Person writtenBy;\n\n\tBook(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_mixed_different_directions/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed_different_directions;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\t@Relationship(value = \"WROTE\", direction = Relationship.Direction.INCOMING)\n\tprivate Person writtenBy;\n\n\tMovie(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/same_rel_mixed_different_directions/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed_different_directions;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Person {\n\n\t@Id\n\tprivate String name;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/self_referential/Example.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.self_referential;\n\nimport org.springframework.data.annotation.PersistenceCreator;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Example {\n\n\t@Id\n\tprivate final long id;\n\n\t@Relationship(type = \"BELONGS_TO\")\n\tprivate Example parent;\n\n\t@PersistenceCreator\n\tpublic Example(long id) {\n\t\tthis.id = id;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/simple/Actor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.RelationshipProperties;\nimport org.springframework.data.neo4j.core.schema.TargetNode;\n\n/**\n * @author Michael J. Simons\n */\n@RelationshipProperties\npublic class Actor {\n\n\t@TargetNode\n\tprivate final Person person;\n\n\tprivate List<String> roles = new ArrayList<>();\n\n\tpublic Actor(Person person) {\n\t\tthis.person = person;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/simple/Bridge.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.RelationshipProperties;\nimport org.springframework.data.neo4j.core.schema.TargetNode;\n\n/**\n * @author Michael J. Simons\n */\n@RelationshipProperties\npublic class Bridge {\n\n\t@TargetNode\n\tprivate final Target target;\n\n\tprivate List<String> things = new ArrayList<>();\n\n\tpublic Bridge(Target target) {\n\t\tthis.target = target;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/simple/Edge.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.RelationshipProperties;\nimport org.springframework.data.neo4j.core.schema.TargetNode;\n\n/**\n * @author Michael J. Simons\n */\n@RelationshipProperties\npublic class Edge {\n\n\t@TargetNode\n\tprivate final Target2 target;\n\n\tprivate List<String> things = new ArrayList<>();\n\n\tpublic Edge(Target2 target) {\n\t\tthis.target = target;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/simple/Kante.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.RelationshipProperties;\nimport org.springframework.data.neo4j.core.schema.TargetNode;\n\n/**\n * @author Michael J. Simons\n */\n@RelationshipProperties\npublic class Kante {\n\n\t@TargetNode\n\tprivate final Target2 target;\n\n\tprivate List<String> things = new ArrayList<>();\n\n\tpublic Kante(Target2 target) {\n\t\tthis.target = target;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/simple/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Property;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\t@Property(\"tagline\")\n\tprivate final String description;\n\n\t@Relationship(type = \"ACTED_IN\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Actor> actors = new ArrayList<>();\n\n\t@Relationship(type = \"DIRECTED\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Person> directors = new ArrayList<>();\n\n\t// This will be ignored, not annotated and the other type is not a node\n\tprivate SomeType someProp;\n\n\tprivate Integer released;\n\n\tpublic Movie(String title, String description) {\n\t\tthis.title = title;\n\t\tthis.description = description;\n\t}\n\n\tstatic class SomeType {\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/simple/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Person {\n\n\t@Id\n\tprivate String name;\n\n\tprivate Integer born;\n\n\tprivate Person follows;\n\n\tprivate List<Movie> produced;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/simple/Src.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Property;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Src {\n\n\t@Id\n\tprivate final String title;\n\n\t@Property(\"tagline\")\n\tprivate final String description;\n\n\t@Relationship(type = \"R1\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Bridge> bridges = new ArrayList<>();\n\n\t@Relationship(type = \"R2\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Target> targets = new ArrayList<>();\n\n\t@Relationship(type = \"R3\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Edge> edges = new ArrayList<>();\n\n\t// This will be ignored, not annotated and the other type is not a node\n\tprivate SomeType someProp;\n\n\tprivate Integer released;\n\n\tpublic Src(String title, String description) {\n\t\tthis.title = title;\n\t\tthis.description = description;\n\t}\n\n\tstatic class SomeType {\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/simple/Target.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Target {\n\n\t@Id\n\tprivate String name;\n\n\tprivate Integer born;\n\n\tprivate Target rel1;\n\n\tprivate List<Src> rel2;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/simple/Target2.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Target2 {\n\n\t@Id\n\tprivate String name;\n\n\tprivate Integer born;\n\n\tprivate Target2 rel21;\n\n\tprivate List<Src> rel22;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/simple/Target3.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.List;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic class Target3 {\n\n\t@Id\n\tprivate String name;\n\n\tprivate Integer born;\n\n\tprivate Target3 rel31;\n\n\tprivate List<Src> rel32;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/simple/TotallyIgnored.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n@Node\npublic class TotallyIgnored {\n\n\t@Id\n\tprivate final String title;\n\n\tpublic TotallyIgnored(String title) {\n\t\tthis.title = title;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/java/org/neo4j/cypherdsl/codegen/sdn6/models/simple/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * This is basically the \"happy path\" as demonstrated in several examples.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/abstract_rels/Directed_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.abstract_rels;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Directed_ extends RelationshipBase<Person_, Movie_, Directed_> {\n\n\tpublic static final String $TYPE = \"DIRECTED\";\n\n\tpublic Directed_(Person_ start, Movie_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Directed_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Directed_ named(SymbolicName newSymbolicName) {\n\t\treturn new Directed_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Directed_ withProperties(MapExpression newProperties) {\n\t\treturn new Directed_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/abstract_rels/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.abstract_rels;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Property DESCRIPTION = this.property(\"tagline\").referencedAs(\"description\");\n\n\tpublic final Directed_ DIRECTORS = new Directed_(Person_.PERSON, this);\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/abstract_rels/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.abstract_rels;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/bidi/Element_.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.bidi;\n\nimport java.util.List;\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n    value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\",\n    date = \"2019-09-21T21:21:00+01:00\",\n    comments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class Element_ extends NodeBase<Element_> {\n    public static final String $PRIMARY_LABEL = \"Element\";\n\n    public static final Element_ ELEMENT = new Element_();\n\n    public final Property ID = this.property(\"id\");\n\n    public final HasPathPoints_ POINTS = new HasPathPoints_(this, Point_.POINT);\n\n    public Element_() {\n        super($PRIMARY_LABEL);\n    }\n\n    private Element_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n        super(symbolicName, labels, properties);\n    }\n\n    @Override\n    public Element_ named(SymbolicName newSymbolicName) {\n        return new Element_(newSymbolicName, getLabels(), getProperties());\n    }\n\n    @Override\n    public Element_ withProperties(MapExpression newProperties) {\n        return new Element_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n    }\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/bidi/HasPathPoints_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.bidi;\n\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class HasPathPoints_ extends RelationshipBase<Element_, Point_, HasPathPoints_> {\n\tpublic static final String $TYPE = \"HAS_PATH_POINTS\";\n\n\tpublic HasPathPoints_(Element_ start, Point_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate HasPathPoints_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic HasPathPoints_ named(SymbolicName newSymbolicName) {\n\t\treturn new HasPathPoints_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic HasPathPoints_ withProperties(MapExpression newProperties) {\n\t\treturn new HasPathPoints_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n}"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/bidi/Point_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.bidi;\n\nimport java.util.List;\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n    value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\",\n    date = \"2019-09-21T21:21:00+01:00\",\n    comments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class Point_ extends NodeBase<Point_> {\n  public static final String $PRIMARY_LABEL = \"Point\";\n\n  public static final Point_ POINT = new Point_();\n\n  public Point_() {\n    super($PRIMARY_LABEL);\n  }\n\n  private Point_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n    super(symbolicName, labels, properties);\n  }\n\n  @Override\n  public Point_ named(SymbolicName newSymbolicName) {\n    return new Point_(newSymbolicName, getLabels(), getProperties());\n  }\n\n  @Override\n  public Point_ withProperties(MapExpression newProperties) {\n    return new Point_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n  }\n}"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/different_properties_for_rel_type/ActedInMovie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.different_properties_for_rel_type;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ActedInMovie_ extends RelationshipBase<Person_, Movie_, ActedInMovie_> {\n\n\tpublic static final String $TYPE = \"ACTED_IN\";\n\n\tpublic final Property ROLES = this.property(\"roles\");\n\n\tpublic final Property STUNT_DOUBLE = this.property(\"stuntDouble\");\n\n\tpublic ActedInMovie_(Person_ start, Movie_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate ActedInMovie_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic ActedInMovie_ named(SymbolicName newSymbolicName) {\n\t\treturn new ActedInMovie_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic ActedInMovie_ withProperties(MapExpression newProperties) {\n\t\treturn new ActedInMovie_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties),\n\t\t\t\tgetRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/different_properties_for_rel_type/ActedInPlay_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.different_properties_for_rel_type;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ActedInPlay_ extends RelationshipBase<Person_, Play_, ActedInPlay_> {\n\n\tpublic static final String $TYPE = \"ACTED_IN\";\n\n\tpublic final Property ROLES = this.property(\"roles\");\n\n\tpublic ActedInPlay_(Person_ start, Play_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate ActedInPlay_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic ActedInPlay_ named(SymbolicName newSymbolicName) {\n\t\treturn new ActedInPlay_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic ActedInPlay_ withProperties(MapExpression newProperties) {\n\t\treturn new ActedInPlay_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties),\n\t\t\t\tgetRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/different_properties_for_rel_type/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.different_properties_for_rel_type;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/different_properties_for_rel_type/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.different_properties_for_rel_type;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Property BORN = this.property(\"born\");\n\n\tpublic final ActedInMovie_ MOVIES = new ActedInMovie_(this, Movie_.MOVIE);\n\n\tpublic final ActedInPlay_ PLAYS = new ActedInPlay_(this, Play_.PLAY);\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/different_properties_for_rel_type/Play_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.different_properties_for_rel_type;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Play_ extends NodeBase<Play_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Play\";\n\n\tpublic static final Play_ PLAY = new Play_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Play_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Play_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Play_ named(SymbolicName newSymbolicName) {\n\t\treturn new Play_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Play_ withProperties(MapExpression newProperties) {\n\t\treturn new Play_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/enums_and_inner_classes/ConnectorTransportWithGlobalConverter_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.enums_and_inner_classes;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ConnectorTransport_ extends NodeBase<ConnectorTransport_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Transport\";\n\n\tpublic static final ConnectorTransport_ CONNECTOR_TRANSPORT = new ConnectorTransport_();\n\n\tpublic final Property VALUE = this.property(\"value\");\n\n\tpublic final Property OTHER_ENUM = this.property(\"otherEnum\");\n\n\tpublic final Property INNER_INNER_CLASS = this.property(\"innerInnerClass\");\n\n\tpublic final Property INNER_INNER_CLASS_BUT_WITHOUT_CONVERTER = this.property(\"innerInnerClassButWithoutConverter\");\n\n\tpublic ConnectorTransport_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate ConnectorTransport_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic ConnectorTransport_ named(SymbolicName newSymbolicName) {\n\t\treturn new ConnectorTransport_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic ConnectorTransport_ withProperties(MapExpression newProperties) {\n\t\treturn new ConnectorTransport_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/enums_and_inner_classes/ConnectorTransport_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.enums_and_inner_classes;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ConnectorTransport_ extends NodeBase<ConnectorTransport_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Transport\";\n\n\tpublic static final ConnectorTransport_ CONNECTOR_TRANSPORT = new ConnectorTransport_();\n\n\tpublic final Property VALUE = this.property(\"value\");\n\n\tpublic final Property OTHER_ENUM = this.property(\"otherEnum\");\n\n\tpublic final Property INNER_INNER_CLASS = this.property(\"innerInnerClass\");\n\n\tpublic ConnectorTransport_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate ConnectorTransport_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic ConnectorTransport_ named(SymbolicName newSymbolicName) {\n\t\treturn new ConnectorTransport_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic ConnectorTransport_ withProperties(MapExpression newProperties) {\n\t\treturn new ConnectorTransport_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/ids/ExternalGeneratedIdImplicit_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.ids;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ExternalGeneratedIdImplicit_ extends NodeBase<ExternalGeneratedIdImplicit_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"ExternalGeneratedIdImplicit\";\n\n\tpublic static final ExternalGeneratedIdImplicit_ EXTERNAL_GENERATED_ID_IMPLICIT = new ExternalGeneratedIdImplicit_();\n\n\tpublic final Property ID = this.property(\"id\");\n\n\tpublic ExternalGeneratedIdImplicit_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate ExternalGeneratedIdImplicit_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic ExternalGeneratedIdImplicit_ named(SymbolicName newSymbolicName) {\n\t\treturn new ExternalGeneratedIdImplicit_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic ExternalGeneratedIdImplicit_ withProperties(MapExpression newProperties) {\n\t\treturn new ExternalGeneratedIdImplicit_(getSymbolicName().orElse(null), getLabels(),\n\t\t\t\tProperties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/ids/ExternalGeneratedId_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.ids;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ExternalGeneratedId_ extends NodeBase<ExternalGeneratedId_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"ExternalGeneratedId\";\n\n\tpublic static final ExternalGeneratedId_ EXTERNAL_GENERATED_ID = new ExternalGeneratedId_();\n\n\tpublic final Property ID = this.property(\"id\");\n\n\tpublic ExternalGeneratedId_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate ExternalGeneratedId_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic ExternalGeneratedId_ named(SymbolicName newSymbolicName) {\n\t\treturn new ExternalGeneratedId_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic ExternalGeneratedId_ withProperties(MapExpression newProperties) {\n\t\treturn new ExternalGeneratedId_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/ids/InternalGeneratedIdWithSpringId_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.ids;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class InternalGeneratedIdWithSpringId_ extends NodeBase<InternalGeneratedIdWithSpringId_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"InternalGeneratedIdWithSpringId\";\n\n\tpublic static final InternalGeneratedIdWithSpringId_ INTERNAL_GENERATED_ID_WITH_SPRING_ID = new InternalGeneratedIdWithSpringId_();\n\n\tpublic InternalGeneratedIdWithSpringId_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate InternalGeneratedIdWithSpringId_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic InternalGeneratedIdWithSpringId_ named(SymbolicName newSymbolicName) {\n\t\treturn new InternalGeneratedIdWithSpringId_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic InternalGeneratedIdWithSpringId_ withProperties(MapExpression newProperties) {\n\t\treturn new InternalGeneratedIdWithSpringId_(getSymbolicName().orElse(null), getLabels(),\n\t\t\t\tProperties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/ids/InternalGeneratedId_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.ids;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class InternalGeneratedId_ extends NodeBase<InternalGeneratedId_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"InternalGeneratedId\";\n\n\tpublic static final InternalGeneratedId_ INTERNAL_GENERATED_ID = new InternalGeneratedId_();\n\n\tpublic InternalGeneratedId_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate InternalGeneratedId_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic InternalGeneratedId_ named(SymbolicName newSymbolicName) {\n\t\treturn new InternalGeneratedId_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic InternalGeneratedId_ withProperties(MapExpression newProperties) {\n\t\treturn new InternalGeneratedId_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/ids/InternalGeneratedPrimitiveLongId_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.ids;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class InternalGeneratedPrimitiveLongId_ extends NodeBase<InternalGeneratedPrimitiveLongId_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"InternalGeneratedPrimitiveLongId\";\n\n\tpublic static final InternalGeneratedPrimitiveLongId_ INTERNAL_GENERATED_PRIMITIVE_LONG_ID = new InternalGeneratedPrimitiveLongId_();\n\n\tpublic InternalGeneratedPrimitiveLongId_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate InternalGeneratedPrimitiveLongId_(SymbolicName symbolicName, List<NodeLabel> labels,\n\t\t\tProperties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic InternalGeneratedPrimitiveLongId_ named(SymbolicName newSymbolicName) {\n\t\treturn new InternalGeneratedPrimitiveLongId_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic InternalGeneratedPrimitiveLongId_ withProperties(MapExpression newProperties) {\n\t\treturn new InternalGeneratedPrimitiveLongId_(getSymbolicName().orElse(null), getLabels(),\n\t\t\t\tProperties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/labels/nodeswithdifferentlabelannotations/LabelOnNode1_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.labels.nodeswithdifferentlabelannotations;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class LabelOnNode1_ extends NodeBase<LabelOnNode1_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"ALabel\";\n\n\tpublic static final LabelOnNode1_ LABEL_ON_NODE_1 = new LabelOnNode1_();\n\n\tpublic LabelOnNode1_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate LabelOnNode1_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic LabelOnNode1_ named(SymbolicName newSymbolicName) {\n\t\treturn new LabelOnNode1_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic LabelOnNode1_ withProperties(MapExpression newProperties) {\n\t\treturn new LabelOnNode1_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/labels/nodeswithdifferentlabelannotations/LabelOnNode2_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.labels.nodeswithdifferentlabelannotations;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class LabelOnNode2_ extends NodeBase<LabelOnNode2_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"ALabel\";\n\n\tpublic static final LabelOnNode2_ LABEL_ON_NODE_2 = new LabelOnNode2_();\n\n\tpublic LabelOnNode2_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate LabelOnNode2_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic LabelOnNode2_ named(SymbolicName newSymbolicName) {\n\t\treturn new LabelOnNode2_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic LabelOnNode2_ withProperties(MapExpression newProperties) {\n\t\treturn new LabelOnNode2_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/labels/nodeswithdifferentlabelannotations/LabelOnNode3_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.labels.nodeswithdifferentlabelannotations;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class LabelOnNode3_ extends NodeBase<LabelOnNode3_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"ALabel\";\n\n\tpublic static final LabelOnNode3_ LABEL_ON_NODE_3 = new LabelOnNode3_();\n\n\tpublic LabelOnNode3_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate LabelOnNode3_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic LabelOnNode3_ named(SymbolicName newSymbolicName) {\n\t\treturn new LabelOnNode3_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic LabelOnNode3_ withProperties(MapExpression newProperties) {\n\t\treturn new LabelOnNode3_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/labels/nodeswithdifferentlabelannotations/MultipleLabels1_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.labels.nodeswithdifferentlabelannotations;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class MultipleLabels1_ extends NodeBase<MultipleLabels1_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Label1\";\n\n\tpublic static final MultipleLabels1_ MULTIPLE_LABELS_1 = new MultipleLabels1_();\n\n\tpublic MultipleLabels1_() {\n\t\tsuper($PRIMARY_LABEL, \"Label2\");\n\t}\n\n\tprivate MultipleLabels1_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic MultipleLabels1_ named(SymbolicName newSymbolicName) {\n\t\treturn new MultipleLabels1_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic MultipleLabels1_ withProperties(MapExpression newProperties) {\n\t\treturn new MultipleLabels1_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/labels/nodeswithdifferentlabelannotations/MultipleLabels2_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.labels.nodeswithdifferentlabelannotations;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class MultipleLabels2_ extends NodeBase<MultipleLabels2_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"PL\";\n\n\tpublic static final MultipleLabels2_ MULTIPLE_LABELS_2 = new MultipleLabels2_();\n\n\tpublic MultipleLabels2_() {\n\t\tsuper($PRIMARY_LABEL, \"Label1\", \"Label2\");\n\t}\n\n\tprivate MultipleLabels2_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic MultipleLabels2_ named(SymbolicName newSymbolicName) {\n\t\treturn new MultipleLabels2_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic MultipleLabels2_ withProperties(MapExpression newProperties) {\n\t\treturn new MultipleLabels2_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/labels/nodeswithdifferentlabelannotations/MultipleLabels3_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.labels.nodeswithdifferentlabelannotations;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class MultipleLabels3_ extends NodeBase<MultipleLabels3_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"PL\";\n\n\tpublic static final MultipleLabels3_ MULTIPLE_LABELS_3 = new MultipleLabels3_();\n\n\tpublic MultipleLabels3_() {\n\t\tsuper($PRIMARY_LABEL, \"Label1\", \"Label2\", \"Some more\");\n\t}\n\n\tprivate MultipleLabels3_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic MultipleLabels3_ named(SymbolicName newSymbolicName) {\n\t\treturn new MultipleLabels3_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic MultipleLabels3_ withProperties(MapExpression newProperties) {\n\t\treturn new MultipleLabels3_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/org/neo4j/cypherdsl/codegen/sdn6/models/related_classes_not_on_cp_like_in_reallife/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.related_classes_not_on_cp_like_in_reallife;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\n\nimport org.springframework.data.annotation.PersistenceCreator;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Property;\nimport org.springframework.data.neo4j.core.schema.Relationship;\nimport org.springframework.data.neo4j.core.schema.Relationship.Direction;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic final class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\t@Property(\"tagline\")\n\tprivate final String description;\n\n\t@Relationship(value = \"DIRECTED\", direction = Direction.INCOMING)\n\tprivate final List<Person> directors;\n\tprivate Type type;\n\tprivate Integer released;\n\n\tpublic Movie(String title, String description) {\n\t\tthis.title = title;\n\t\tthis.description = description;\n\t\tthis.directors = new ArrayList<>();\n\t}\n\n\t@PersistenceCreator\n\tpublic Movie(String title, String description, List<Person> directors) {\n\t\tthis.title = title;\n\t\tthis.description = description;\n\t\tthis.directors = directors == null ? Collections.emptyList() : new ArrayList<>(directors);\n\t}\n\n\tpublic String getTitle() {\n\t\treturn title;\n\t}\n\n\tpublic String getDescription() {\n\t\treturn description;\n\t}\n\n\tpublic List<Person> getDirectors() {\n\t\treturn Collections.unmodifiableList(this.directors);\n\t}\n\n\tpublic Integer getReleased() {\n\t\treturn released;\n\t}\n\n\tpublic void setReleased(Integer released) {\n\t\tthis.released = released;\n\t}\n\n\tpublic Type getType() {\n\t\treturn type;\n\t}\n\n\tpublic void setType(Type type) {\n\t\tthis.type = type;\n\t}\n\n\tpublic Movie addDirectors(Collection<Person> newDirectors) {\n\t\tthis.directors.addAll(newDirectors);\n\t\treturn this;\n\t}\n\n\tpublic enum Type {\n\n\t\tAKTION_FILM, KOMÖDIE, SCHNULZE\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/org/neo4j/cypherdsl/codegen/sdn6/models/related_classes_not_on_cp_like_in_reallife/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.codegen.sdn6.models.related_classes_not_on_cp_like_in_reallife;\n\nimport org.springframework.data.annotation.PersistenceCreator;\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * @author Michael J. Simons\n */\n@Node\npublic final class Person {\n\n\t@Id\n\t@GeneratedValue\n\tprivate final Long id;\n\n\tprivate final String name;\n\n\tprivate Integer born;\n\n\t@PersistenceCreator\n\tprivate Person(Long id, String name, Integer born) {\n\t\tthis.id = id;\n\t\tthis.born = born;\n\t\tthis.name = name;\n\t}\n\n\tpublic Person(String name, Integer born) {\n\t\tthis(null, name, born);\n\t}\n\n\tpublic Long getId() {\n\t\treturn id;\n\t}\n\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\tpublic Integer getBorn() {\n\t\treturn born;\n\t}\n\n\tpublic void setBorn(Integer born) {\n\t\tthis.born = born;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/primitives/Connector_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.primitives;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Connector_ extends NodeBase<Connector_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Connector\";\n\n\tpublic static final Connector_ CONNECTOR = new Connector_();\n\n\tpublic final Property ID = this.property(\"id\");\n\n\tpublic final Property URI = this.property(\"uri\");\n\n\tpublic final Property OFFICIAL = this.property(\"official\");\n\n\tpublic final Property AN_INT = this.property(\"anInt\");\n\n\tpublic final Property A_FLOAT = this.property(\"aFloat\");\n\n\tpublic final Property A_DOUBLE = this.property(\"aDouble\");\n\n\tpublic Connector_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Connector_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Connector_ named(SymbolicName newSymbolicName) {\n\t\treturn new Connector_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Connector_ withProperties(MapExpression newProperties) {\n\t\treturn new Connector_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/records/NodeWithRecordProperties_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.records;\n\nimport java.util.List;\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class NodeWithRecordProperties_ extends NodeBase<NodeWithRecordProperties_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"NodeWithRecordProperties\";\n\n\tpublic static final NodeWithRecordProperties_ NODE_WITH_RECORD_PROPERTIES = new NodeWithRecordProperties_();\n\n\tpublic final Property ID = this.property(\"id\");\n\n\tpublic final Property RECORD_AS_PROPERTY_WITH_CONVERSION = this.property(\"recordAsPropertyWithConversion\");\n\n\tpublic final Property YOLOING_NO_CONVERSION = this.property(\"yoloingNoConversion\");\n\n\tpublic final RecordAsRelationship_ RECORD_AS_RELATIONSHIP = new RecordAsRelationship_(this,\n\t\t\tRecordTarget_.RECORD_TARGET);\n\n\tpublic NodeWithRecordProperties_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate NodeWithRecordProperties_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic NodeWithRecordProperties_ named(SymbolicName newSymbolicName) {\n\t\treturn new NodeWithRecordProperties_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic NodeWithRecordProperties_ withProperties(MapExpression newProperties) {\n\t\treturn new NodeWithRecordProperties_(getSymbolicName().orElse(null), getLabels(),\n\t\t\t\tProperties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/records/RecordAsRelationship_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.records;\n\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class RecordAsRelationship_\n\t\textends RelationshipBase<NodeWithRecordProperties_, RecordTarget_, RecordAsRelationship_> {\n\n\tpublic static final String $TYPE = \"recordAsRelationship\";\n\n\tpublic RecordAsRelationship_(NodeWithRecordProperties_ start, RecordTarget_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate RecordAsRelationship_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic RecordAsRelationship_ named(SymbolicName newSymbolicName) {\n\t\treturn new RecordAsRelationship_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic RecordAsRelationship_ withProperties(MapExpression newProperties) {\n\t\treturn new RecordAsRelationship_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties),\n\t\t\t\tgetRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/records/RecordTarget_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.records;\n\nimport java.util.List;\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class RecordTarget_ extends NodeBase<RecordTarget_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"RecordTarget\";\n\n\tpublic static final RecordTarget_ RECORD_TARGET = new RecordTarget_();\n\n\tpublic final Property VALUE = this.property(\"value\");\n\n\tpublic RecordTarget_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate RecordTarget_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic RecordTarget_ named(SymbolicName newSymbolicName) {\n\t\treturn new RecordTarget_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic RecordTarget_ withProperties(MapExpression newProperties) {\n\t\treturn new RecordTarget_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/related_classes_not_on_cp_like_in_reallife/Directed_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.related_classes_not_on_cp_like_in_reallife;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class Directed_ extends RelationshipBase<Person_, Movie_, Directed_> {\n\tpublic static final String $TYPE = \"DIRECTED\";\n\n\tpublic Directed_(Person_ start, Movie_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Directed_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Directed_ named(SymbolicName newSymbolicName) {\n\t\treturn new Directed_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Directed_ withProperties(MapExpression newProperties) {\n\t\treturn new Directed_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/related_classes_not_on_cp_like_in_reallife/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.related_classes_not_on_cp_like_in_reallife;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Property DESCRIPTION = this.property(\"tagline\").referencedAs(\"description\");\n\n\tpublic final Property TYPE = this.property(\"type\");\n\n\tpublic final Property RELEASED = this.property(\"released\");\n\n\tpublic final Directed_ DIRECTORS = new Directed_(Person_.PERSON, this);\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/related_classes_not_on_cp_like_in_reallife/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.related_classes_not_on_cp_like_in_reallife;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Property BORN = this.property(\"born\");\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_properties_for_rel_type/ActedIn_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_properties_for_rel_type;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ActedIn_<E extends NodeBase<?>> extends RelationshipBase<Person_, E, ActedIn_<E>> {\n\n\tpublic static final String $TYPE = \"ACTED_IN\";\n\n\tpublic final Property ROLES = this.property(\"roles\");\n\n\tpublic ActedIn_(Person_ start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate ActedIn_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic ActedIn_<E> named(SymbolicName newSymbolicName) {\n\t\treturn new ActedIn_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic ActedIn_<E> withProperties(MapExpression newProperties) {\n\t\treturn new ActedIn_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_properties_for_rel_type/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_properties_for_rel_type;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_properties_for_rel_type/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_properties_for_rel_type;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Property BORN = this.property(\"born\");\n\n\tpublic final ActedIn_<Movie_> MOVIES = new ActedIn_<Movie_>(this, Movie_.MOVIE);\n\n\tpublic final ActedIn_<Play_> PLAYS = new ActedIn_<Play_>(this, Play_.PLAY);\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_properties_for_rel_type/Play_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_properties_for_rel_type;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Play_ extends NodeBase<Play_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Play\";\n\n\tpublic static final Play_ PLAY = new Play_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Play_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Play_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Play_ named(SymbolicName newSymbolicName) {\n\t\treturn new Play_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Play_ withProperties(MapExpression newProperties) {\n\t\treturn new Play_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_package/Abuses1_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain;\n\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class Abuses_<E extends NodeBase<?>> extends RelationshipBase<Company_, E, Abuses_<E>> {\n\tpublic static final String $TYPE = \"ABUSES\";\n\n\tpublic Abuses_(Company_ start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Abuses_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Abuses_<E> named(SymbolicName newSymbolicName) {\n\t\treturn new Abuses_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Abuses_<E> withProperties(MapExpression newProperties) {\n\t\treturn new Abuses_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_package/CompanyModel_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.application;\n\nimport java.util.List;\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain.DomainEntity_;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class CompanyModel_ extends NodeBase<CompanyModel_> {\n\tpublic static final String $PRIMARY_LABEL = \"Company\";\n\n\tpublic static final CompanyModel_ COMPANY_MODEL = new CompanyModel_();\n\n\tpublic final In_ PLACE = new In_(this, PlaceModel_.PLACE_MODEL);\n\n\tpublic final Uses_ DOMAIN_ENTITY = new Uses_(this, DomainEntity_.DOMAIN_ENTITY);\n\n\tpublic CompanyModel_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate CompanyModel_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic CompanyModel_ named(SymbolicName newSymbolicName) {\n\t\treturn new CompanyModel_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic CompanyModel_ withProperties(MapExpression newProperties) {\n\t\treturn new CompanyModel_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_package/Company_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain;\n\nimport java.util.List;\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class Company_ extends NodeBase<Company_> {\n\tpublic static final String $PRIMARY_LABEL = \"Company\";\n\n\tpublic static final Company_ COMPANY = new Company_();\n\n\tpublic final In_ PLACE = new In_(this, Place_.PLACE);\n\n\tpublic final Abuses_<DomainEntity_> DE_1 = new Abuses_<DomainEntity_>(this, DomainEntity_.DOMAIN_ENTITY);\n\n\tpublic final Abuses_<DomainEntity2_> DE_2 = new Abuses_<DomainEntity2_>(this, DomainEntity2_.DOMAIN_ENTITY_2);\n\n\tpublic final Uses_ DOMAIN_ENTITY = new Uses_(this, DomainEntity_.DOMAIN_ENTITY);\n\n\tpublic final Uses_ DOMAIN_ENTITY_2 = new Uses_(this, DomainEntity_.DOMAIN_ENTITY);\n\n\tpublic Company_() {\n\t\tsuper($PRIMARY_LABEL, \"CompanyId\");\n\t}\n\n\tprivate Company_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Company_ named(SymbolicName newSymbolicName) {\n\t\treturn new Company_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Company_ withProperties(MapExpression newProperties) {\n\t\treturn new Company_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_package/DomainEntity2_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain;\n\nimport java.util.List;\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class DomainEntity2_ extends NodeBase<DomainEntity2_> {\n\tpublic static final String $PRIMARY_LABEL = \"DomainEntity2\";\n\n\tpublic static final DomainEntity2_ DOMAIN_ENTITY_2 = new DomainEntity2_();\n\n\tpublic DomainEntity2_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate DomainEntity2_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic DomainEntity2_ named(SymbolicName newSymbolicName) {\n\t\treturn new DomainEntity2_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic DomainEntity2_ withProperties(MapExpression newProperties) {\n\t\treturn new DomainEntity2_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_package/DomainEntity_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain;\n\nimport java.util.List;\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class DomainEntity_ extends NodeBase<DomainEntity_> {\n\tpublic static final String $PRIMARY_LABEL = \"DomainEntity\";\n\n\tpublic static final DomainEntity_ DOMAIN_ENTITY = new DomainEntity_();\n\n\tpublic DomainEntity_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate DomainEntity_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic DomainEntity_ named(SymbolicName newSymbolicName) {\n\t\treturn new DomainEntity_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic DomainEntity_ withProperties(MapExpression newProperties) {\n\t\treturn new DomainEntity_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_package/In1_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain;\n\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class In_ extends RelationshipBase<Company_, Place_, In_> {\n\tpublic static final String $TYPE = \"IN\";\n\n\tpublic In_(Company_ start, Place_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate In_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic In_ named(SymbolicName newSymbolicName) {\n\t\treturn new In_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic In_ withProperties(MapExpression newProperties) {\n\t\treturn new In_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_package/In2_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.application;\n\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class In_ extends RelationshipBase<CompanyModel_, PlaceModel_, In_> {\n\tpublic static final String $TYPE = \"IN\";\n\n\tpublic In_(CompanyModel_ start, PlaceModel_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate In_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic In_ named(SymbolicName newSymbolicName) {\n\t\treturn new In_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic In_ withProperties(MapExpression newProperties) {\n\t\treturn new In_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_package/PlaceModel_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.application;\n\nimport java.util.List;\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class PlaceModel_ extends NodeBase<PlaceModel_> {\n\tpublic static final String $PRIMARY_LABEL = \"Place\";\n\n\tpublic static final PlaceModel_ PLACE_MODEL = new PlaceModel_();\n\n\tpublic PlaceModel_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate PlaceModel_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic PlaceModel_ named(SymbolicName newSymbolicName) {\n\t\treturn new PlaceModel_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic PlaceModel_ withProperties(MapExpression newProperties) {\n\t\treturn new PlaceModel_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_package/Place_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain;\n\nimport java.util.List;\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class Place_ extends NodeBase<Place_> {\n\tpublic static final String $PRIMARY_LABEL = \"Place\";\n\n\tpublic static final Place_ PLACE = new Place_();\n\n\tpublic Place_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Place_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Place_ named(SymbolicName newSymbolicName) {\n\t\treturn new Place_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Place_ withProperties(MapExpression newProperties) {\n\t\treturn new Place_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_package/Uses1_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain;\n\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class Uses_ extends RelationshipBase<Company_, DomainEntity_, Uses_> {\n\tpublic static final String $TYPE = \"USES\";\n\n\tpublic Uses_(Company_ start, DomainEntity_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Uses_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Uses_ named(SymbolicName newSymbolicName) {\n\t\treturn new Uses_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Uses_ withProperties(MapExpression newProperties) {\n\t\treturn new Uses_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_package/Uses2_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.application;\n\nimport javax.annotation.processing.Generated;\nimport org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_package.domain.DomainEntity_;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class Uses_ extends RelationshipBase<CompanyModel_, DomainEntity_, Uses_> {\n\tpublic static final String $TYPE = \"USES\";\n\n\tpublic Uses_(CompanyModel_ start, DomainEntity_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Uses_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Uses_ named(SymbolicName newSymbolicName) {\n\t\treturn new Uses_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Uses_ withProperties(MapExpression newProperties) {\n\t\treturn new Uses_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_source/Book_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_source;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Book_ extends NodeBase<Book_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Book\";\n\n\tpublic static final Book_ BOOK = new Book_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Wrote_<Book_> WRITTEN_BY = new Wrote_<Book_>(Person_.PERSON, this);\n\n\tpublic Book_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Book_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Book_ named(SymbolicName newSymbolicName) {\n\t\treturn new Book_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Book_ withProperties(MapExpression newProperties) {\n\t\treturn new Book_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_source/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_source;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Wrote_<Movie_> WRITTEN_BY = new Wrote_<Movie_>(Person_.PERSON, this);\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_source/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_source;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_source/Wrote_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_source;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Wrote_<E extends NodeBase<?>> extends RelationshipBase<Person_, E, Wrote_<E>> {\n\n\tpublic static final String $TYPE = \"WROTE\";\n\n\tpublic Wrote_(Person_ start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Wrote_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Wrote_<E> named(SymbolicName newSymbolicName) {\n\t\treturn new Wrote_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Wrote_<E> withProperties(MapExpression newProperties) {\n\t\treturn new Wrote_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_target/Book_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_target;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Book_ extends NodeBase<Book_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Book\";\n\n\tpublic static final Book_ BOOK = new Book_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Book_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Book_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Book_ named(SymbolicName newSymbolicName) {\n\t\treturn new Book_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Book_ withProperties(MapExpression newProperties) {\n\t\treturn new Book_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_target/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_target;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_target/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_target;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Wrote_<Movie_> WRITTEN_MOVIES = new Wrote_<Movie_>(this, Movie_.MOVIE);\n\n\tpublic final Wrote_<Book_> WRITTEN_BOOKS = new Wrote_<Book_>(this, Book_.BOOK);\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_different_target/Wrote_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_different_target;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Wrote_<E extends NodeBase<?>> extends RelationshipBase<Person_, E, Wrote_<E>> {\n\n\tpublic static final String $TYPE = \"WROTE\";\n\n\tpublic Wrote_(Person_ start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Wrote_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Wrote_<E> named(SymbolicName newSymbolicName) {\n\t\treturn new Wrote_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Wrote_<E> withProperties(MapExpression newProperties) {\n\t\treturn new Wrote_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_mixed/Book_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Book_ extends NodeBase<Book_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Book\";\n\n\tpublic static final Book_ BOOK = new Book_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Wrote_<Book_> WRITTEN_BY = new Wrote_<Book_>(Person_.PERSON, this);\n\n\tpublic Book_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Book_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Book_ named(SymbolicName newSymbolicName) {\n\t\treturn new Book_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Book_ withProperties(MapExpression newProperties) {\n\t\treturn new Book_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_mixed/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_mixed/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Wrote_<Movie_> WRITTEN_MOVIES = new Wrote_<Movie_>(this, Movie_.MOVIE);\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_mixed/Wrote_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Wrote_<E extends NodeBase<?>> extends RelationshipBase<Person_, E, Wrote_<E>> {\n\n\tpublic static final String $TYPE = \"WROTE\";\n\n\tpublic Wrote_(Person_ start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Wrote_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Wrote_<E> named(SymbolicName newSymbolicName) {\n\t\treturn new Wrote_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Wrote_<E> withProperties(MapExpression newProperties) {\n\t\treturn new Wrote_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_mixed_different_directions/Book_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed_different_directions;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Book_ extends NodeBase<Book_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Book\";\n\n\tpublic static final Book_ BOOK = new Book_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Wrote_<Book_, Person_> WRITTEN_BY = new Wrote_<Book_, Person_>(this, Person_.PERSON);\n\n\tpublic Book_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Book_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Book_ named(SymbolicName newSymbolicName) {\n\t\treturn new Book_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Book_ withProperties(MapExpression newProperties) {\n\t\treturn new Book_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_mixed_different_directions/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed_different_directions;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Wrote_<Person_, Movie_> WRITTEN_BY = new Wrote_<Person_, Movie_>(Person_.PERSON, this);\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_mixed_different_directions/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed_different_directions;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/same_rel_mixed_different_directions/Wrote_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.same_rel_mixed_different_directions;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Wrote_<S extends NodeBase<?>, E extends NodeBase<?>> extends RelationshipBase<S, E, Wrote_<S, E>> {\n\n\tpublic static final String $TYPE = \"WROTE\";\n\n\tpublic Wrote_(S start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Wrote_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Wrote_<S, E> named(SymbolicName newSymbolicName) {\n\t\treturn new Wrote_<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Wrote_<S, E> withProperties(MapExpression newProperties) {\n\t\treturn new Wrote_<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/self_referential/BelongsTo_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.self_referential;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class BelongsTo_ extends RelationshipBase<Example_, Example_, BelongsTo_> {\n\tpublic static final String $TYPE = \"BELONGS_TO\";\n\n\tpublic BelongsTo_(Example_ start, Example_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate BelongsTo_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic BelongsTo_ named(SymbolicName newSymbolicName) {\n\t\treturn new BelongsTo_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic BelongsTo_ withProperties(MapExpression newProperties) {\n\t\treturn new BelongsTo_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/self_referential/Example_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.self_referential;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Example_ extends NodeBase<Example_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Example\";\n\n\tpublic static final Example_ EXAMPLE = new Example_();\n\n\tpublic final Property ID = this.property(\"id\");\n\n\tpublic Example_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Example_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Example_ named(SymbolicName newSymbolicName) {\n\t\treturn new Example_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Example_ withProperties(MapExpression newProperties) {\n\t\treturn new Example_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n\tpublic BelongsTo_ withParent(Example_ parent) {\n\t\treturn new BelongsTo_(this, parent);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/simple/ActedIn_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class ActedIn_ extends RelationshipBase<Person_, Movie_, ActedIn_> {\n\n\tpublic static final String $TYPE = \"ACTED_IN\";\n\n\tpublic final Property ROLES = this.property(\"roles\");\n\n\tpublic ActedIn_(Person_ start, Movie_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate ActedIn_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic ActedIn_ named(SymbolicName newSymbolicName) {\n\t\treturn new ActedIn_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic ActedIn_ withProperties(MapExpression newProperties) {\n\t\treturn new ActedIn_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/simple/Directed_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Directed_ extends RelationshipBase<Person_, Movie_, Directed_> {\n\n\tpublic static final String $TYPE = \"DIRECTED\";\n\n\tpublic Directed_(Person_ start, Movie_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Directed_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Directed_ named(SymbolicName newSymbolicName) {\n\t\treturn new Directed_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Directed_ withProperties(MapExpression newProperties) {\n\t\treturn new Directed_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/simple/Follows_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Follows_ extends RelationshipBase<Person_, Person_, Follows_> {\n\n\tpublic static final String $TYPE = \"follows\";\n\n\tpublic Follows_(Person_ start, Person_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Follows_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Follows_ named(SymbolicName newSymbolicName) {\n\t\treturn new Follows_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Follows_ withProperties(MapExpression newProperties) {\n\t\treturn new Follows_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/simple/Movie_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Movie_ extends NodeBase<Movie_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Movie\";\n\n\tpublic static final Movie_ MOVIE = new Movie_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Property DESCRIPTION = this.property(\"tagline\").referencedAs(\"description\");\n\n\tpublic final Property RELEASED = this.property(\"released\");\n\n\tpublic final ActedIn_ ACTORS = new ActedIn_(Person_.PERSON, this);\n\n\tpublic final Directed_ DIRECTORS = new Directed_(Person_.PERSON, this);\n\n\tpublic Movie_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Movie_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie_ named(SymbolicName newSymbolicName) {\n\t\treturn new Movie_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie_ withProperties(MapExpression newProperties) {\n\t\treturn new Movie_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/simple/Person_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Person_ extends NodeBase<Person_> {\n\n\tpublic static final String $PRIMARY_LABEL = \"Person\";\n\n\tpublic static final Person_ PERSON = new Person_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Property BORN = this.property(\"born\");\n\n\tpublic final Produced_ PRODUCED = new Produced_(this, Movie_.MOVIE);\n\n\tpublic Person_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Person_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person_ named(SymbolicName newSymbolicName) {\n\t\treturn new Person_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person_ withProperties(MapExpression newProperties) {\n\t\treturn new Person_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n\tpublic Follows_ withFollows(Person_ follows) {\n\t\treturn new Follows_(this, follows);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/simple/Produced_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(value = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\", date = \"2019-09-21T21:21:00+01:00\",\n\t\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\")\npublic final class Produced_ extends RelationshipBase<Person_, Movie_, Produced_> {\n\n\tpublic static final String $TYPE = \"produced\";\n\n\tpublic Produced_(Person_ start, Movie_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Produced_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Produced_ named(SymbolicName newSymbolicName) {\n\t\treturn new Produced_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Produced_ withProperties(MapExpression newProperties) {\n\t\treturn new Produced_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/simple/Rel21_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class Rel21_ extends RelationshipBase<Target2_, Target2_, Rel21_> {\n\tpublic static final String $TYPE = \"rel21\";\n\n\tpublic Rel21_(Target2_ start, Target2_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Rel21_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Rel21_ named(SymbolicName newSymbolicName) {\n\t\treturn new Rel21_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Rel21_ withProperties(MapExpression newProperties) {\n\t\treturn new Rel21_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/simple/Rel22_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.RelationshipImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class Rel22_ extends RelationshipBase<Target2_, Src_, Rel22_> {\n\tpublic static final String $TYPE = \"rel22\";\n\n\tpublic Rel22_(Target2_ start, Src_ end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Rel22_(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Rel22_ named(SymbolicName newSymbolicName) {\n\t\treturn new Rel22_(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Rel22_ withProperties(MapExpression newProperties) {\n\t\treturn new Rel22_(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/simple/Src_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class Src_ extends NodeBase<Src_> {\n\tpublic static final String $PRIMARY_LABEL = \"Src\";\n\n\tpublic static final Src_ SRC = new Src_();\n\n\tpublic final Property TITLE = this.property(\"title\");\n\n\tpublic final Property DESCRIPTION = this.property(\"tagline\").referencedAs(\"description\");\n\n\tpublic final Property RELEASED = this.property(\"released\");\n\n\tpublic Src_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Src_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Src_ named(SymbolicName newSymbolicName) {\n\t\treturn new Src_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Src_ withProperties(MapExpression newProperties) {\n\t\treturn new Src_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/neo4j-cypher-dsl-codegen-sdn6/src/test/resources/simple/Target2_.java",
    "content": "package org.neo4j.cypherdsl.codegen.sdn6.models.simple;\n\nimport java.util.List;\nimport javax.annotation.Generated;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n@Generated(\n\tvalue = \"org.neo4j.cypherdsl.codegen.core.NodeImplBuilder\",\n\tdate = \"2019-09-21T21:21:00+01:00\",\n\tcomments = \"This class is generated by the Neo4j Cypher-DSL. All changes to it will be lost after regeneration.\"\n)\npublic final class Target2_ extends NodeBase<Target2_> {\n\tpublic static final String $PRIMARY_LABEL = \"Target2\";\n\n\tpublic static final Target2_ TARGET_2 = new Target2_();\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Property BORN = this.property(\"born\");\n\n\tpublic final Rel22_ REL_2_2 = new Rel22_(this, Src_.SRC);\n\n\tpublic Target2_() {\n\t\tsuper($PRIMARY_LABEL);\n\t}\n\n\tprivate Target2_(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Target2_ named(SymbolicName newSymbolicName) {\n\t\treturn new Target2_(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Target2_ withProperties(MapExpression newProperties) {\n\t\treturn new Target2_(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n\tpublic Rel21_ withRel21(Target2_ rel21) {\n\t\treturn new Rel21_(this, rel21);\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-codegen/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-parent</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-codegen</artifactId>\n\t<packaging>pom</packaging>\n\t<name>Neo4j Cypher DSL (Code Generator)</name>\n\n\t<modules>\n\t\t<module>neo4j-cypher-dsl-codegen-core</module>\n\t\t<module>neo4j-cypher-dsl-codegen-ogm</module>\n\t\t<module>neo4j-cypher-dsl-codegen-sdn6</module>\n\t</modules>\n\n\t<properties>\n\t\t<java-module-name>org.neo4j.cypherdsl.codegen</java-module-name>\n\t</properties>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-dsl-bom</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/README.adoc",
    "content": "== Docs\n\nThis project contains a lot of fragments.\nThose fragments are not meant to be used together all at once.\nThey are here to be included in our docs.\nBy having them compiled as part of our build, we can make sure we don't have any invalid docs.\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-examples</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-examples-core</artifactId>\n\n\t<name>Examples (Core)</name>\n\t<description>Examples for the core Cypher-DSL used in the documentation.</description>\n\n\t<properties>\n\t\t<java-module-name>org.neo4j.cypherdsl.examples.core</java-module-name>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl</artifactId>\n\t\t\t<version>${revision}${sha1}${changelist}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.assertj</groupId>\n\t\t\t<artifactId>assertj-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-jar-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skipIfEmpty>true</skipIfEmpty>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-install-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-failsafe-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>integration-test</goal>\n\t\t\t\t\t\t\t<goal>verify</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/ArbitraryProceduresAndFunctionsTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.core;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n *\n */\nclass ArbitraryProceduresAndFunctionsTests {\n\n\tprivate static final Renderer cypherRenderer = Renderer.getDefaultRenderer();\n\n\t@Test\n\tvoid standaloneCalls() {\n\t\t// tag::standalone-call[]\n\t\tvar call = Cypher.call(\"db\", \"labels\").build(); // <.>\n\t\tassertThat(cypherRenderer.render(call)).isEqualTo(\"CALL db.labels()\");\n\n\t\tcall = Cypher.call(\"db.labels\").build(); // <.>\n\t\tassertThat(cypherRenderer.render(call)).isEqualTo(\"CALL db.labels()\");\n\t\t// end::standalone-call[]\n\n\t}\n\n\t@Test\n\tvoid standaloneCallWithArgs() {\n\t\t// tag::standalone-call-with-args[]\n\t\tvar call = Cypher.call(\"dbms.security.createUser\")\n\t\t\t.withArgs(Cypher.literalOf(\"johnsmith\"), Cypher.literalOf(\"h6u4%kr\"), Cypher.literalFalse())\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(call))\n\t\t\t.isEqualTo(\"CALL dbms.security.createUser('johnsmith', 'h6u4%kr', false)\");\n\t\t// end::standalone-call-with-args[]\n\t}\n\n\t@Test\n\tvoid standaloneCallYielding() {\n\t\t// tag::standalone-call-yielding[]\n\t\tvar call = Cypher.call(\"dbms.procedures\").yield(\"name\", \"signature\").build(); // <.>\n\t\tassertThat(cypherRenderer.render(call)).isEqualTo(\"CALL dbms.procedures() YIELD name, signature\");\n\n\t\tcall = Cypher.call(\"dbms.procedures\").yield(Cypher.name(\"name\"), Cypher.name(\"signature\")).build(); // <.>\n\t\tassertThat(cypherRenderer.render(call)).isEqualTo(\"CALL dbms.procedures() YIELD name, signature\");\n\t\t// end::standalone-call-yielding[]\n\t}\n\n\t@Test\n\tvoid standaloneCallWhere() {\n\t\t// tag::standalone-call-where[]\n\t\tvar name = Cypher.name(\"name\");\n\t\tvar call = Cypher.call(\"dbms.listConfig\")\n\t\t\t.withArgs(Cypher.literalOf(\"browser\"))\n\t\t\t.yield(name)\n\t\t\t.where(name.matches(\"browser\\\\.allow.*\"))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(call))\n\t\t\t.isEqualTo(\"CALL dbms.listConfig('browser') YIELD name WHERE name =~ 'browser\\\\\\\\.allow.*' RETURN *\");\n\t\t// end::standalone-call-where[]\n\t}\n\n\t@Test\n\tvoid inQueryCalls() {\n\n\t\t// tag::in-query-calls[]\n\t\tvar label = Cypher.name(\"label\");\n\t\tvar statement = Cypher.match(Cypher.anyNode().named(\"n\"))\n\t\t\t.with(\"n\")\n\t\t\t.call(\"db.labels\")\n\t\t\t.yield(label)\n\t\t\t.with(label)\n\t\t\t.returning(Cypher.count(label).as(\"numLabels\"))\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t.isEqualTo(\"MATCH (n) WITH n CALL db.labels() YIELD label WITH label RETURN count(label) AS numLabels\");\n\t\t// end::in-query-calls[]\n\t}\n\n\t@Test\n\tvoid asFunction() {\n\n\t\t// tag::as-function[]\n\t\tvar p = Cypher.node(\"Person\").named(\"p\");\n\t\tvar createUuid = Cypher.call(\"apoc.create.uuid\").asFunction(); // <.>\n\t\tvar statement = Cypher.merge(p.withProperties(Cypher.mapOf(\"id\", createUuid))) // <.>\n\t\t\t.set(p.property(\"firstName\").to(Cypher.literalOf(\"Michael\")),\n\t\t\t\t\tp.property(\"surname\").to(Cypher.literalOf(\"Hunger\")))\n\t\t\t.returning(p)\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MERGE (p:`Person` {id: apoc.create.uuid()}) \"\n\t\t\t\t+ \"SET p.firstName = 'Michael', p.surname = 'Hunger' \" + \"RETURN p\");\n\t\t// end::as-function[]\n\t}\n\n\t@Test\n\tvoid asFunctionWithArgs() {\n\n\t\t// tag::as-function-with-args[]\n\t\tvar p = Cypher.node(\"Person\").named(\"p\");\n\t\tvar createUuid = Cypher.call(\"apoc.create.uuid\").asFunction(); // <.>\n\t\tvar toCamelCase = Cypher.call(\"apoc.text.camelCase\")\n\t\t\t.withArgs(Cypher.literalOf(\"first name\")) // <.>\n\t\t\t.asFunction();\n\t\tvar statement = Cypher.merge(p.withProperties(Cypher.mapOf(\"id\", createUuid)))\n\t\t\t.set(p.property(\"surname\").to(Cypher.literalOf(\"Simons\")))\n\t\t\t.with(p)\n\t\t\t.call(\"apoc.create.setProperty\")\n\t\t\t.withArgs(p.getRequiredSymbolicName(), toCamelCase, Cypher.parameter(\"nameParam\") // <.>\n\t\t\t)\n\t\t\t.yield(\"node\")\n\t\t\t.returning(\"node\")\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t.isEqualTo(\"MERGE (p:`Person` {id: apoc.create.uuid()}) SET p.surname = 'Simons' \"\n\t\t\t\t\t+ \"WITH p CALL apoc.create.setProperty(p, apoc.text.camelCase('first name'), $nameParam) \"\n\t\t\t\t\t+ \"YIELD node RETURN node\");\n\t\t// end::as-function-with-args[]\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/CypherDSLExamplesTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.core;\n\n// tag::cypher-dsl-imports[]\n\nimport java.util.Collection;\nimport java.util.Locale;\nimport java.util.Map;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.SortItem;\nimport org.neo4j.cypherdsl.core.Statement;\nimport org.neo4j.cypherdsl.core.SymbolicName;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n// end::cypher-dsl-imports[]\n\n/**\n * Examples for the Cypher DSL.\n *\n * @author Michael J. Simons\n * @since 1.0\n */\nclass CypherDSLExamplesTests {\n\n\tprivate static final Renderer cypherRenderer = Renderer.getDefaultRenderer();\n\n\t@Test\n\tvoid escapingNames() {\n\n\t\t// tag::escaping[]\n\t\tvar relationship = Cypher.node(\"Person\")\n\t\t\t.named(\"a\")\n\t\t\t.relationshipTo(Cypher.node(\"Movie\").named(\"m\"), \"ACTED_IN\")\n\t\t\t.named(\"r\");\n\n\t\tvar statement = Cypher.match(relationship).returning(relationship).build();\n\n\t\tvar defaultRenderer = Renderer.getDefaultRenderer();\n\t\tassertThat(defaultRenderer.render(statement))\n\t\t\t.isEqualTo(\"MATCH (a:`Person`)-[r:`ACTED_IN`]->(m:`Movie`) RETURN r\");\n\n\t\tvar escapeOnlyIfNecessary = Configuration.newConfig().alwaysEscapeNames(false).build();\n\n\t\tvar renderer = Renderer.getRenderer(escapeOnlyIfNecessary);\n\t\tassertThat(renderer.render(statement)).isEqualTo(\"MATCH (a:Person)-[r:ACTED_IN]->(m:Movie) RETURN r\");\n\n\t\trenderer = Renderer.getRenderer(Configuration.prettyPrinting());\n\t\tassertThat(renderer.render(statement)).isEqualTo(\"MATCH (a:Person)-[r:ACTED_IN]->(m:Movie)\\nRETURN r\");\n\t\t// end::escaping[]\n\t}\n\n\t@Test\n\tvoid findAllMovies() {\n\n\t\t// tag::cypher-dsl-e1[]\n\t\tvar m = Cypher.node(\"Movie\").named(\"m\"); // <.>\n\t\tvar statement = Cypher.match(m) // <.>\n\t\t\t.returning(m)\n\t\t\t.build(); // <.>\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (m:`Movie`) RETURN m\");\n\t\t// end::cypher-dsl-e1[]\n\t}\n\n\t@Test\n\tvoid playMovieGraphFind() {\n\n\t\t// tag::cypher-dsl-e2[]\n\t\tvar tom = Cypher.anyNode().named(\"tom\").withProperties(\"name\", Cypher.literalOf(\"Tom Hanks\"));\n\t\tvar statement = Cypher.match(tom).returning(tom).build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (tom {name: 'Tom Hanks'}) RETURN tom\");\n\t\t// end::cypher-dsl-e2[]\n\n\t\t// tag::cypher-dsl-e3[]\n\t\tvar cloudAtlas = Cypher.anyNode().named(\"cloudAtlas\").withProperties(\"title\", Cypher.literalOf(\"Cloud Atlas\"));\n\t\tstatement = Cypher.match(cloudAtlas).returning(cloudAtlas).build();\n\n\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t.isEqualTo(\"MATCH (cloudAtlas {title: 'Cloud Atlas'}) RETURN cloudAtlas\");\n\t\t// end::cypher-dsl-e3[]\n\n\t\t// tag::cypher-dsl-e4[]\n\t\tvar people = Cypher.node(\"Person\").named(\"people\");\n\t\tstatement = Cypher.match(people).returning(people.property(\"name\")).limit(10).build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"MATCH (people:`Person`) RETURN people.name LIMIT 10\");\n\t\t// end::cypher-dsl-e4[]\n\n\t\t// tag::cypher-dsl-e5[]\n\t\tvar nineties = Cypher.node(\"Movie\").named(\"nineties\");\n\t\tvar released = nineties.property(\"released\");\n\t\tstatement = Cypher.match(nineties)\n\t\t\t.where(released.gte(Cypher.literalOf(1990)).and(released.lt(Cypher.literalOf(2000))))\n\t\t\t.returning(nineties.property(\"title\"))\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"MATCH (nineties:`Movie`) WHERE (nineties.released >= 1990 AND nineties.released < 2000) RETURN nineties.title\");\n\t\t// end::cypher-dsl-e5[]\n\t}\n\n\t@Test\n\tvoid playMovieGraphQuery() {\n\n\t\t// tag::cypher-dsl-e6[]\n\t\tvar tom = Cypher.node(\"Person\").named(\"tom\").withProperties(\"name\", Cypher.literalOf(\"Tom Hanks\"));\n\t\tvar tomHanksMovies = Cypher.anyNode(\"tomHanksMovies\");\n\t\tvar statement = Cypher.match(tom.relationshipTo(tomHanksMovies, \"ACTED_IN\"))\n\t\t\t.returning(tom, tomHanksMovies)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"MATCH (tom:`Person` {name: 'Tom Hanks'})-[:`ACTED_IN`]->(tomHanksMovies) RETURN tom, tomHanksMovies\");\n\t\t// end::cypher-dsl-e6[]\n\n\t\t// tag::cypher-dsl-e7[]\n\t\tvar cloudAtlas = Cypher.anyNode(\"cloudAtlas\").withProperties(\"title\", Cypher.literalOf(\"Cloud Atlas\"));\n\t\tvar directors = Cypher.anyNode(\"directors\");\n\t\tstatement = Cypher.match(cloudAtlas.relationshipFrom(directors, \"DIRECTED\"))\n\t\t\t.returning(directors.property(\"name\"))\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t.isEqualTo(\"MATCH (cloudAtlas {title: 'Cloud Atlas'})<-[:`DIRECTED`]-(directors) RETURN directors.name\");\n\t\t// end::cypher-dsl-e7[]\n\n\t\t// tag::cypher-dsl-e8[]\n\t\ttom = Cypher.node(\"Person\").named(\"tom\").withProperties(\"name\", Cypher.literalOf(\"Tom Hanks\"));\n\t\tvar movie = Cypher.anyNode(\"m\");\n\t\tvar coActors = Cypher.anyNode(\"coActors\");\n\t\tvar people = Cypher.node(\"Person\").named(\"people\");\n\t\tstatement = Cypher.match(tom.relationshipTo(movie, \"ACTED_IN\").relationshipFrom(coActors, \"ACTED_IN\"))\n\t\t\t.returning(coActors.property(\"name\"))\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"MATCH (tom:`Person` {name: 'Tom Hanks'})-[:`ACTED_IN`]->(m)<-[:`ACTED_IN`]-(coActors) RETURN coActors.name\");\n\t\t// end::cypher-dsl-e8[]\n\n\t\t// tag::cypher-dsl-e9[]\n\t\tcloudAtlas = Cypher.node(\"Movie\").withProperties(\"title\", Cypher.literalOf(\"Cloud Atlas\"));\n\t\tpeople = Cypher.node(\"Person\").named(\"people\");\n\t\tvar relatedTo = people.relationshipBetween(cloudAtlas).named(\"relatedTo\");\n\t\tstatement = Cypher.match(relatedTo)\n\t\t\t.returning(people.property(\"name\"), Cypher.type(relatedTo), relatedTo.getRequiredSymbolicName())\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"MATCH (people:`Person`)-[relatedTo]-(:`Movie` {title: 'Cloud Atlas'}) RETURN people.name, type(relatedTo), relatedTo\");\n\t\t// end::cypher-dsl-e9[]\n\t}\n\n\t@Test\n\tvoid playMovieGraphSolve() {\n\n\t\t// tag::cypher-dsl-bacon[]\n\t\tvar bacon = Cypher.node(\"Person\").named(\"bacon\").withProperties(\"name\", Cypher.literalOf(\"Kevin Bacon\"));\n\t\tvar hollywood = Cypher.anyNode(\"hollywood\");\n\t\tvar statement = Cypher.match(bacon.relationshipBetween(hollywood).length(1, 4))\n\t\t\t.returningDistinct(hollywood)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t.isEqualTo(\"MATCH (bacon:`Person` {name: 'Kevin Bacon'})-[*1..4]-(hollywood) RETURN DISTINCT hollywood\");\n\t\t// end::cypher-dsl-bacon[]\n\t}\n\n\t@Test\n\tvoid playMovieGraphRecommend() {\n\n\t\t// tag::cypher-dsl-r[]\n\t\tvar tom = Cypher.node(\"Person\").named(\"tom\").withProperties(\"name\", Cypher.literalOf(\"Tom Hanks\"));\n\t\tvar coActors = Cypher.anyNode(\"coActors\");\n\t\tvar cocoActors = Cypher.anyNode(\"cocoActors\");\n\t\tvar strength = Cypher.count(Cypher.asterisk()).as(\"Strength\");\n\t\tvar statement = Cypher\n\t\t\t.match(tom.relationshipTo(Cypher.anyNode(\"m\"), \"ACTED_IN\").relationshipFrom(coActors, \"ACTED_IN\"),\n\t\t\t\t\tcoActors.relationshipTo(Cypher.anyNode(\"m2\"), \"ACTED_IN\").relationshipFrom(cocoActors, \"ACTED_IN\"))\n\t\t\t.where(Cypher\n\t\t\t\t.not(tom.relationshipTo(Cypher.anyNode(), \"ACTED_IN\").relationshipFrom(cocoActors, \"ACTED_IN\")))\n\t\t\t.and(tom.isNotEqualTo(cocoActors))\n\t\t\t.returning(cocoActors.property(\"name\").as(\"Recommended\"), strength)\n\t\t\t.orderBy(strength.asName().descending())\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"\" + \"MATCH \" + \"(tom:`Person` {name: 'Tom Hanks'})-[:`ACTED_IN`]->(m)<-[:`ACTED_IN`]-(coActors), \"\n\t\t\t\t\t\t+ \"(coActors)-[:`ACTED_IN`]->(m2)<-[:`ACTED_IN`]-(cocoActors) \"\n\t\t\t\t\t\t+ \"WHERE (NOT (tom)-[:`ACTED_IN`]->()<-[:`ACTED_IN`]-(cocoActors) AND tom <> cocoActors) \"\n\t\t\t\t\t\t+ \"RETURN cocoActors.name AS Recommended, count(*) AS Strength ORDER BY Strength DESC\");\n\t\t// end::cypher-dsl-r[]\n\t}\n\n\t@Test // GH-82\n\tvoid storedProceduresCanBeCalled() {\n\n\t\tStatement call = Cypher.call(\"dbms.listConfig\").withArgs(Cypher.literalOf(\"browser\")).yield(\"name\").build();\n\t\tassertThat(cypherRenderer.render(call)).isEqualTo(\"CALL dbms.listConfig('browser') YIELD name\");\n\t}\n\n\t@Test\n\tvoid where() {\n\n\t\tSymbolicName name = Cypher.name(\"name\");\n\t\tStatement call = Cypher.call(\"dbms.listConfig\")\n\t\t\t.withArgs(Cypher.literalOf(\"browser\"))\n\t\t\t.yield(name)\n\t\t\t.where(name.matches(\"browser\\\\.allow.*\"))\n\t\t\t.returning(Cypher.asterisk())\n\t\t\t.build();\n\t\tassertThat(cypherRenderer.render(call))\n\t\t\t.isEqualTo(\"CALL dbms.listConfig('browser') YIELD name WHERE name =~ 'browser\\\\\\\\.allow.*' RETURN *\");\n\t}\n\n\t@Test\n\tvoid collectingParameters() {\n\n\t\t// tag::collecting-params[]\n\t\tvar person = Cypher.node(\"Person\").named(\"p\");\n\t\tvar statement = Cypher.match(person)\n\t\t\t.where(person.property(\"nickname\").isEqualTo(Cypher.parameter(\"nickname\")))\n\t\t\t.set(person.property(\"firstName\").to(Cypher.parameter(\"firstName\").withValue(\"Thomas\")),\n\t\t\t\t\tperson.property(\"name\").to(Cypher.parameter(\"name\", \"Anderson\")))\n\t\t\t.returning(person)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"MATCH (p:`Person`) WHERE p.nickname = $nickname SET p.firstName = $firstName, p.name = $name RETURN p\");\n\n\t\tCollection<String> parameterNames = statement.getCatalog().getParameterNames();\n\t\tassertThat(parameterNames).containsExactlyInAnyOrder(\"nickname\", \"firstName\", \"name\"); // <.>\n\n\t\tMap<String, Object> parameters = statement.getCatalog().getParameters();\n\t\tassertThat(parameters).hasSize(2); // <.>\n\t\tassertThat(parameters).containsEntry(\"firstName\", \"Thomas\").containsEntry(\"name\", \"Anderson\");\n\t\t// end::collecting-params[]\n\t}\n\n\t@Test\n\tvoid prettyPrintExample() {\n\n\t\t// tag::pretty-printing-examle[]\n\t\tvar n = Cypher.anyNode(\"n\");\n\t\tvar a = Cypher.node(\"A\").named(\"a\");\n\t\tvar b = Cypher.node(\"B\").named(\"b\");\n\n\t\tvar mergeStatement = Cypher.merge(n)\n\t\t\t.onCreate()\n\t\t\t.set(n.property(\"prop\").to(Cypher.literalOf(0)))\n\t\t\t.merge(a.relationshipBetween(b, \"T\"))\n\t\t\t.onCreate()\n\t\t\t.set(a.property(\"name\").to(Cypher.literalOf(\"me\")))\n\t\t\t.onMatch()\n\t\t\t.set(b.property(\"name\").to(Cypher.literalOf(\"you\")))\n\t\t\t.returning(a.property(\"prop\"))\n\t\t\t.build();\n\n\t\tvar renderer = Renderer.getRenderer(Configuration.prettyPrinting()); // <.>\n\t\tassertThat(renderer.render(mergeStatement))\n\t\t\t.isEqualTo(\"MERGE (n)\\n\" + \"  ON CREATE SET n.prop = 0\\n\" + \"MERGE (a:A)-[:T]-(b:B)\\n\"\n\t\t\t\t\t+ \"  ON CREATE SET a.name = 'me'\\n\" + \"  ON MATCH SET b.name = 'you'\\n\" + \"RETURN a.prop\"); // <.>\n\t\t// end::pretty-printing-examle[]\n\t}\n\n\t@Test\n\tvoid rawCypher() {\n\n\t\t// tag::raw-cypher[]\n\t\tvar key = Cypher.name(\"key\");\n\t\tvar cypher = Cypher.call(\"apoc.meta.schema\")\n\t\t\t.yield(\"value\")\n\t\t\t.with(\"value\")\n\t\t\t.unwind(Cypher.keys(Cypher.name(\"value\")))\n\t\t\t.as(key)\n\t\t\t.returning(key, Cypher.raw(\"value[$E]\", key).as(\"value\") // <.>\n\t\t\t)\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"CALL apoc.meta.schema() YIELD value WITH value UNWIND keys(value) AS key RETURN key, value[key] AS value\");\n\t\t// end::raw-cypher[]\n\t}\n\n\t@Test\n\tvoid fromTheGeniusBar1() {\n\n\t\tvar orderBy = \"some property\";\n\t\tvar order = \"asc\";\n\t\tvar skip = \"21\";\n\t\tvar limit = \"42\";\n\n\t\tvar direction = SortItem.Direction.valueOf(order.toUpperCase(Locale.ROOT));\n\n\t\tvar m = Cypher.node(\"Movie\").named(\"m\");\n\t\tvar dynamicProperty = m.property(orderBy);\n\n\t\tvar statement = Cypher.match(m)\n\t\t\t.where(Cypher.exists(dynamicProperty))\n\t\t\t.returning(m.project(Cypher.asterisk()))\n\t\t\t.orderBy(dynamicProperty.sorted(direction))\n\t\t\t.skip(Integer.parseInt(skip))\n\t\t\t.limit(Integer.parseInt(limit))\n\t\t\t.build();\n\t\tassertThat(statement.getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (m:`Movie`) WHERE m.`some property` IS NOT NULL RETURN m{.*} ORDER BY m.`some property` ASC SKIP 21 LIMIT 42\");\n\t}\n\n\t@Test\n\tvoid fromTheGeniusBar2() {\n\n\t\tvar orderBy = \"some property\";\n\t\tvar order = \"asc\";\n\t\tvar skip = \"21\";\n\t\tvar limit = \"42\";\n\n\t\tvar direction = SortItem.Direction.valueOf(order.toUpperCase(Locale.ROOT));\n\n\t\tvar m = Cypher.node(\"Movie\").named(\"m\");\n\t\tvar dynamicProperty = m.property(Cypher.anonParameter(orderBy));\n\n\t\tvar statement = Cypher.match(m)\n\t\t\t.where(Cypher.exists(dynamicProperty))\n\t\t\t.returning(m.project(Cypher.asterisk()))\n\t\t\t.orderBy(dynamicProperty.sorted(direction))\n\t\t\t.skip(Cypher.anonParameter(Integer.parseInt(skip)))\n\t\t\t.limit(Cypher.anonParameter(Integer.parseInt(limit)))\n\t\t\t.build();\n\t\tassertThat(statement.getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (m:`Movie`) WHERE m[$pcdsl01] IS NOT NULL RETURN m{.*} ORDER BY m[$pcdsl01] ASC SKIP $pcdsl02 LIMIT $pcdsl03\");\n\t\tassertThat(statement.getCatalog().getParameters())\n\t\t\t.containsAllEntriesOf(Map.of(\"pcdsl01\", \"some property\", \"pcdsl02\", 21, \"pcdsl03\", 42));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/FunctionsListTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.core;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n *\n */\nclass FunctionsListTests {\n\n\tprivate static final Renderer cypherRenderer = Renderer.getDefaultRenderer();\n\n\t// tag::functions-list-operator[]\n\t@Test\n\tvoid valueAtExample() {\n\n\t\t// tag::functions-list-range[]\n\t\tvar range = Cypher.range(0, 10);\n\t\t// end::functions-list-range[]\n\n\t\tvar statement = Cypher.returning(Cypher.valueAt(range, 3)).build();\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN range(0, 10)[3]\");\n\t}\n\n\t@Test\n\tvoid subListUntilExample() {\n\n\t\tvar range = Cypher.range(Cypher.literalOf(0), Cypher.literalOf(10));\n\n\t\tvar statement = Cypher.returning(Cypher.subListUntil(range, 3)).build();\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN range(0, 10)[..3]\");\n\t}\n\n\t@Test\n\tvoid subListFromExample() {\n\n\t\t// tag::functions-list-range-step[]\n\t\tvar range = Cypher.range(0, 10, 1);\n\t\t// end::functions-list-range-step[]\n\n\t\tvar statement = Cypher.returning(Cypher.subListFrom(range, -3)).build();\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN range(0, 10, 1)[-3..]\");\n\t}\n\n\t@Test\n\tvoid subListExample() {\n\n\t\tvar range = Cypher.range(Cypher.literalOf(0), Cypher.literalOf(10), Cypher.literalOf(1));\n\n\t\tvar statement = Cypher.returning(Cypher.subList(range, 2, 4)).build();\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN range(0, 10, 1)[2..4]\");\n\t}\n\t// end::functions-list-operator[]\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/IssuesExamplesTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.core;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass IssuesExamplesTests {\n\n\tprivate static final Renderer cypherRenderer = Renderer.getDefaultRenderer();\n\n\t@Test\n\tvoid gh48() {\n\t\tvar n = Cypher.node(\"Label\").named(\"n\");\n\t\tvar statement = Cypher.match(n)\n\t\t\t.set(n, Cypher.mapOf(\"a\", Cypher.literalOf(\"bar\"), \"b\", Cypher.literalOf(\"baz\")))\n\t\t\t.returning(n)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t.isEqualTo(\"MATCH (n:`Label`) SET n = {a: 'bar', b: 'baz'} RETURN n\");\n\t}\n\n\t@Test\n\tvoid gh51() {\n\n\t\tvar n = Cypher.anyNode(\"n\");\n\t\tvar foobarProp = Cypher.property(\"n\", \"foobar\");\n\t\tvar statement = Cypher.match(n)\n\t\t\t.where(foobarProp.contains(Cypher.literalOf(\"baz\")))\n\t\t\t.or(foobarProp.startsWith(Cypher.literalOf(\"a\")))\n\t\t\t.or(foobarProp.endsWith(Cypher.literalOf(\"b\")))\n\t\t\t.returning(n)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).isEqualTo(\n\t\t\t\t\"MATCH (n) WHERE (n.foobar CONTAINS 'baz' OR n.foobar STARTS WITH 'a' OR n.foobar ENDS WITH 'b') RETURN n\");\n\t}\n\n\t@SuppressWarnings(\"deprecation\")\n\t@Test\n\tvoid gh59() {\n\t\tvar change = Cypher.node(\"Change\").named(\"change\");\n\t\tvar code = Cypher.anyNode().named(\"code\");\n\t\tvar codeRelation = change.relationshipBetween(code, \"CODE\").named(\"codeRelation\");\n\t\tvar changeDetail = Cypher.anyNode().named(\"changeDetail\");\n\t\tvar changeDetailsRelation = change.relationshipBetween(changeDetail, \"CHANGE_DETAILS\")\n\t\t\t.named(\"changeDetailsRelation\");\n\n\t\tvar idIsEqualTo147 = code.internalId().isEqualTo(Cypher.literalOf(147));\n\t\tvar statement = Cypher.match(codeRelation)\n\t\t\t.where(idIsEqualTo147)\n\t\t\t.optionalMatch(changeDetailsRelation)\n\t\t\t.where(idIsEqualTo147)\n\t\t\t.returning(change, codeRelation, changeDetailsRelation, changeDetail)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t.isEqualTo(\"MATCH (change:`Change`)-[codeRelation:`CODE`]-(code) \" + \"WHERE id(code) = 147 \"\n\t\t\t\t\t+ \"OPTIONAL MATCH (change)-[changeDetailsRelation:`CHANGE_DETAILS`]-(changeDetail) \"\n\t\t\t\t\t+ \"WHERE id(code) = 147 RETURN change, codeRelation, changeDetailsRelation, changeDetail\");\n\t}\n\n\t@Test\n\tvoid gh60() {\n\n\t\tvar src = Cypher.anyNode().withProperties(\"id\", Cypher.literalOf(10));\n\t\tvar n = Cypher.anyNode().named(\"n\");\n\t\tvar statement = Cypher.match(src.relationshipTo(n, \"LINKS_WITH\").named(\"r\"))\n\t\t\t.where(Cypher.literalOf(\"France\").in(Cypher.property(\"r\", \"markets\")))\n\t\t\t.returning(n)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t.isEqualTo(\"MATCH ( {id: 10})-[r:`LINKS_WITH`]->(n) WHERE 'France' IN r.markets RETURN n\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/core/PropertiesTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.core;\n\nimport java.util.Map;\nimport java.util.regex.Pattern;\n\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n *\n */\nclass PropertiesTests {\n\n\tprivate static final Renderer cypherRenderer = Renderer.getDefaultRenderer();\n\n\t@Test\n\tvoid propertiesOnNodesAndRel() {\n\n\t\t// tag::properties-on-nodes-and-rel[]\n\t\tvar personNode = Cypher.node(\"Person\").named(\"p\");\n\t\tvar movieNode = Cypher.node(\"Movie\");\n\t\tvar ratedRel = personNode.relationshipTo(movieNode, \"RATED\").named(\"r\");\n\t\tvar statement = Cypher.match(ratedRel)\n\t\t\t.returning(personNode.property(\"name\"), // <.>\n\t\t\t\t\tratedRel.property(\"rating\")) // <.>\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t.isEqualTo(\"MATCH (p:`Person`)-[r:`RATED`]->(:`Movie`) RETURN p.name, r.rating\");\n\t\t// end::properties-on-nodes-and-rel[]\n\t}\n\n\t@Test\n\tvoid propertiesOnNodesAndRelUnnamned() {\n\n\t\t// tag::properties-on-nodes-and-rel-unnamed[]\n\t\tvar personNode = Cypher.node(\"Person\");\n\t\tvar movieNode = Cypher.node(\"Movie\");\n\t\tvar ratedRel = personNode.relationshipTo(movieNode, \"RATED\");\n\t\tvar statement = Cypher.match(ratedRel)\n\t\t\t.returning(personNode.property(\"name\"), // <.>\n\t\t\t\t\tratedRel.property(\"rating\")) // <.>\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement)).matches(Pattern.quote(\"MATCH (\") + \"\\\\w+\"\n\t\t\t\t+ Pattern.quote(\":`Person`)-[\") + \"\\\\w+\" + Pattern.quote(\":`RATED`]->(:`Movie`) RETURN \") + \"\\\\w+\"\n\t\t\t\t+ Pattern.quote(\".name, \") + \"\\\\w+\" + Pattern.quote(\".rating\"));\n\t\t// end::properties-on-nodes-and-rel-unnamed[]\n\t}\n\n\t@Test\n\tvoid propertiesOfExpressions() {\n\n\t\t// tag::properties-on-expressions[]\n\t\tvar epochSeconds = Cypher.property(Cypher.datetime(), \"epochSeconds\"); // <.>\n\t\tvar statement = Cypher.returning(epochSeconds).build();\n\t\tAssertions.assertThat(cypherRenderer.render(statement)).isEqualTo(\"RETURN datetime().epochSeconds\");\n\t\t// end::properties-on-expressions[]\n\t}\n\n\t@Test\n\tvoid nestedProperties() {\n\n\t\t// tag::nested-properties[]\n\t\tvar node = Cypher.node(\"Person\").named(\"p\");\n\n\t\tvar locationPropV1 = Cypher.property(node.getRequiredSymbolicName(), \"home.location\", \"y\");\n\t\tvar locationPropV2 = Cypher.property(\"p\", \"home.location\", \"y\");\n\n\t\tvar statement = Cypher.match(node)\n\t\t\t.where(locationPropV1.gt(Cypher.literalOf(50)))\n\t\t\t.returning(locationPropV2)\n\t\t\t.build();\n\n\t\tassertThat(cypherRenderer.render(statement))\n\t\t\t.isEqualTo(\"MATCH (p:`Person`) WHERE p.`home.location`.y > 50 RETURN p.`home.location`.y\");\n\t\t// end::nested-properties[]\n\t}\n\n\t@Test\n\tvoid usingExistingJavaMaps() {\n\n\t\tvar node = Cypher.node(\"ANode\").named(\"n\").withProperties(Map.of(\"aProperty\", 23));\n\n\t\tassertThat(Cypher.match(node).returning(node).build().getCypher())\n\t\t\t.isEqualTo(\"MATCH (n:`ANode` {aProperty: 23}) RETURN n\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/AbstractNodeDefinition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.model;\n\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n/**\n * An example for a set of shared properties for the nodes in a domain.\n *\n * @param <T> the final type of what is described here\n * @author Michael J. Simons\n */\npublic abstract class AbstractNodeDefinition<T extends AbstractNodeDefinition<T>> extends NodeBase<T> {\n\n\t@SuppressWarnings(\"this-escape\")\n\tpublic final Property ID = this.property(\"id\");\n\n\t@SuppressWarnings(\"this-escape\")\n\tpublic final Property NAME = this.property(\"name\");\n\n\tprotected AbstractNodeDefinition(String... additionalLabel) {\n\t\tsuper(\"DefaultNode\", additionalLabel);\n\t}\n\n\tprotected AbstractNodeDefinition(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) { // <.>\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/AbstractRelationshipDefinition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.model;\n\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n/**\n * An example for a set of shared properties for the relationships in a domain.\n *\n * @param <S> start node\n * @param <E> end node\n * @author Michael J. Simons\n */\npublic abstract class AbstractRelationshipDefinition<S extends AbstractNodeDefinition<?>, E extends AbstractNodeDefinition<?>>\n\t\textends RelationshipBase<S, E, AbstractRelationshipDefinition<S, E>> {\n\n\tpublic static final String $DEFAULT_TYPE = \"COOP_REL\";\n\n\t@SuppressWarnings(\"this-escape\")\n\tpublic final Property CREATED_AT = this.property(\"createdAt\");\n\n\tprotected AbstractRelationshipDefinition(S start, E end, String... additionalTypes) {\n\n\t\tsuper(start, $DEFAULT_TYPE, end, additionalTypes);\n\t}\n\n\tprotected AbstractRelationshipDefinition(SymbolicName symbolicName, Node start, Properties properties, Node end,\n\t\t\tString... additionalTypes) {\n\t\tsuper(symbolicName, start, $DEFAULT_TYPE, properties, end, additionalTypes);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/ActedIn.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.model;\n\n// tag::simple-model[]\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n// end::simple-model[]\n/**\n * @author Michael J. Simons\n *\n */\n// tag::simple-model[]\npublic final class ActedIn extends RelationshipBase<Person, Movie, ActedIn> {\n\n\t// <.>\n\n\tpublic static final String $TYPE = \"ACTED_IN\";\n\n\tpublic final Property ROLE = this.property(\"role\"); // <.>\n\n\tprotected ActedIn(Person start, Movie end) {\n\t\tsuper(start, $TYPE, end); // <.>\n\t}\n\n\tprivate ActedIn(SymbolicName symbolicName, Node start, Properties properties, Node end) { // <.>\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic ActedIn named(SymbolicName newSymbolicName) { // <.>\n\n\t\treturn new ActedIn(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic ActedIn withProperties(MapExpression newProperties) { // <.>\n\n\t\treturn new ActedIn(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n// end::simple-model[]\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/BelongsTo.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.model;\n\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n/**\n * Defines additional types for a relationship model based on a common type.\n *\n * @author Michael J. Simons\n */\npublic final class BelongsTo extends AbstractRelationshipDefinition<Department, Division> {\n\n\tpublic static final String $TYPE = \"BELONGS_TO\";\n\n\tprotected BelongsTo(Department start, Division end) {\n\t\tsuper(start, end, $TYPE);\n\t}\n\n\tprivate BelongsTo(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, properties, end, $TYPE);\n\t}\n\n\t@Override\n\tpublic BelongsTo named(SymbolicName newSymbolicName) {\n\n\t\treturn new BelongsTo(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic BelongsTo withProperties(MapExpression newProperties) {\n\n\t\treturn new BelongsTo(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/Department.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.model;\n\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n/**\n * Defines additional labels for a node model based on a common type.\n *\n * @author Michael J. Simons\n */\npublic final class Department extends AbstractNodeDefinition<Department> {\n\n\tpublic static final Department DEPARTMENT = new Department();\n\n\tpublic final BelongsTo BELONGS_TO = new BelongsTo(this, Division.DIVISION);\n\n\tpublic Department() {\n\t\tsuper(\"Department\");\n\t}\n\n\tprivate Department(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Department named(SymbolicName newSymbolicName) {\n\t\treturn new Department(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Department withProperties(MapExpression newProperties) {\n\t\treturn new Department(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/Directed.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.model;\n\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n/**\n * I modelled the relationships \"DIRECTED\" and \"ACTED_IN\" in this test slightly different\n * to get a feeling how to deal with the same type of relationship between different\n * nodes. A person might as well be the director of a musical etc.\n *\n * @param <E> end node\n * @author Michael J. Simons\n */\npublic final class Directed<E extends NodeBase<?>> extends RelationshipBase<Person, E, Directed<E>> {\n\n\tpublic static final String $TYPE = \"DIRECTED\";\n\n\tprotected Directed(Person start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate Directed(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic Directed<E> named(SymbolicName newSymbolicName) {\n\n\t\treturn new Directed<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic Directed<E> withProperties(MapExpression newProperties) {\n\n\t\treturn new Directed<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties), getRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/Division.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.model;\n\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n/**\n * Defines additional labels for a node model based on a common type.\n *\n * @author Michael J. Simons\n */\npublic final class Division extends AbstractNodeDefinition<Division> {\n\n\tpublic static final Division DIVISION = new Division();\n\n\tpublic Division() {\n\t\tsuper(\"Division\");\n\t}\n\n\tprivate Division(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Division named(SymbolicName newSymbolicName) {\n\t\treturn new Division(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Division withProperties(MapExpression newProperties) {\n\t\treturn new Division(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.model;\n\n// tag::simple-model[]\n\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n// end::simple-model[]\n\n/**\n * @author Michael J. Simons\n */\n// tag::simple-model[]\n// tag::add-properties[]\npublic final class Movie extends NodeBase<Movie> {\n\n\t// <.>\n\n\t// end::add-properties[]\n\tpublic static final Movie MOVIE = new Movie(); // <.>\n\n\t// end::simple-model[]\n\tpublic final Property TAGLINE = this.property(\"tagline\");\n\n\t// tag::add-properties[]\n\tpublic final Property TITLE = this.property(\"title\"); // <.>\n\n\t// end::add-properties[]\n\n\tpublic final Property RELEASED = this.property(\"released\");\n\n\t// tag::simple-model[]\n\tpublic Movie() {\n\t\tsuper(\"Movie\"); // <.>\n\t}\n\n\tprivate Movie(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) { // <.>\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Movie named(SymbolicName newSymbolicName) { // <.>\n\n\t\treturn new Movie(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Movie withProperties(MapExpression newProperties) { // <.>\n\n\t\treturn new Movie(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\t// tag::add-properties[]\n\n}\n// end::simple-model[]\n// end::add-properties[]\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.model;\n\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n/**\n * @author Michael J. Simons\n *\n */\n// tag::simple-model[]\npublic final class Person extends NodeBase<Person> {\n\n\tpublic static final Person PERSON = new Person();\n\n\tpublic final Directed<Movie> DIRECTED = new Directed<>(this, Movie.MOVIE);\n\n\tpublic final ActedIn ACTED_IN = new ActedIn(this, Movie.MOVIE); // <.>\n\n\tpublic final Property NAME = this.property(\"name\");\n\n\tpublic final Property FIRST_NAME = this.property(\"firstName\");\n\n\tpublic final Property BORN = this.property(\"born\");\n\n\t// end::simple-model[]\n\n\tpublic Person() {\n\t\tsuper(\"Person\");\n\t}\n\n\tprivate Person(SymbolicName symbolicName, List<NodeLabel> labels, Properties properties) {\n\t\tsuper(symbolicName, labels, properties);\n\t}\n\n\t@Override\n\tpublic Person named(SymbolicName newSymbolicName) {\n\n\t\treturn new Person(newSymbolicName, getLabels(), getProperties());\n\t}\n\n\t@Override\n\tpublic Person withProperties(MapExpression newProperties) {\n\n\t\treturn new Person(getSymbolicName().orElse(null), getLabels(), Properties.create(newProperties));\n\t}\n\t// tag::simple-model[]\n\n}\n// end::simple-model[]\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/StaticModelIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.model;\n\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.Cypher;\n\n/**\n * @author Michael J. Simons\n */\nclass StaticModelIT {\n\n\t@Test\n\tvoid simpleMatchShouldWork() {\n\n\t\t// tag::simple-model[]\n\t\tvar cypher = Cypher.match(Movie.MOVIE).returning(Movie.MOVIE).build().getCypher();\n\t\t// end::simple-model[]\n\n\t\tAssertions.assertThat(cypher).matches(\"MATCH \\\\(\\\\w+:`Movie`\\\\) RETURN \\\\w+\");\n\t}\n\n\t@Test\n\tvoid simpleMatchRenamedShouldWork() {\n\n\t\t// tag::simple-model-renamed[]\n\t\tvar movie = Movie.MOVIE.named(\"m\");\n\t\tvar cypher = Cypher.match(movie).returning(movie).build().getCypher();\n\t\t// end::simple-model-renamed[]\n\n\t\tAssertions.assertThat(cypher).isEqualTo(\"MATCH (m:`Movie`) RETURN m\");\n\t}\n\n\t@Test\n\tvoid renamingShouldWork() {\n\n\t\t// tag::add-properties[]\n\t\tvar movie = Movie.MOVIE.named(\"m\");\n\t\tvar cypher = Cypher.match(movie)\n\t\t\t.where(movie.TITLE.isEqualTo(Cypher.literalOf(\"The Matrix\"))) // <.>\n\t\t\t.returning(movie)\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tAssertions.assertThat(cypher).isEqualTo(\"MATCH (m:`Movie`) WHERE m.title = 'The Matrix' RETURN m\");\n\t\t// end::add-properties[]\n\t}\n\n\t@Test\n\tvoid propertiesShouldWorkInMatchWithType() {\n\n\t\t// tag::query-node-by-properties[]\n\t\tvar movie = Movie.MOVIE.withProperties(Movie.MOVIE.TITLE, Cypher.literalOf(\"The Matrix\")).named(\"m1\");\n\t\tvar cypher = Cypher.match(movie).returning(movie).build().getCypher();\n\n\t\tAssertions.assertThat(cypher).isEqualTo(\"MATCH (m1:`Movie` {title: 'The Matrix'}) RETURN m1\");\n\t\t// end::query-node-by-properties[]\n\t}\n\n\t@Test\n\tvoid relRropertiesShouldWorkInMatchWithType() {\n\n\t\tvar actedIn = Person.PERSON.ACTED_IN.withProperties(Person.PERSON.ACTED_IN.ROLE, Cypher.literalOf(\"Neo\"))\n\t\t\t.named(\"n\");\n\t\tvar cypher = Cypher.match(actedIn).returning(Movie.MOVIE).build().getCypher();\n\n\t\tAssertions.assertThat(cypher)\n\t\t\t.matches(\"MATCH \\\\(\\\\w+:`Person`\\\\)-\\\\[n:`ACTED_IN` \\\\{role: 'Neo'}]->\\\\(\\\\w+:`Movie`\\\\) RETURN \\\\w+\");\n\t}\n\n\t@Test\n\tvoid relRropertiesShouldWorkInMatchWithTypeCustomName() {\n\n\t\t// tag::query-rel-by-properties[]\n\t\tvar actedIn = Person.PERSON.ACTED_IN.withProperties(Person.PERSON.ACTED_IN.ROLE, Cypher.literalOf(\"Neo\"));\n\t\tvar cypher = Cypher.match(actedIn).returning(Movie.MOVIE).build().getCypher();\n\n\t\tAssertions.assertThat(cypher)\n\t\t\t.matches(\"MATCH \\\\(\\\\w+:`Person`\\\\)-\\\\[\\\\w+:`ACTED_IN` \\\\{role: 'Neo'}]->\\\\(\\\\w+:`Movie`\\\\) RETURN \\\\w+\");\n\t\t// end::query-rel-by-properties[]\n\t}\n\n\t@Test\n\tvoid renamingRelationshipsShouldWork() {\n\n\t\tvar directed = Person.PERSON.DIRECTED.named(\"d\");\n\t\tvar cypher = Cypher.match(directed).returning(Movie.MOVIE).build().getCypher();\n\n\t\tAssertions.assertThat(cypher)\n\t\t\t.matches(\"MATCH \\\\(\\\\w+:`Person`\\\\)-\\\\[d:`DIRECTED`]->\\\\(\\\\w+:`Movie`\\\\) RETURN \\\\w+\");\n\t}\n\n\t@Test\n\tvoid matchOnRelationshipsShouldWork() {\n\n\t\tvar cypher = Cypher.match(Person.PERSON.DIRECTED).returning(Movie.MOVIE).build().getCypher();\n\n\t\tAssertions.assertThat(cypher)\n\t\t\t.matches(\"MATCH \\\\(\\\\w+:`Person`\\\\)-\\\\[\\\\w+:`DIRECTED`]->\\\\(\\\\w+:`Movie`\\\\) RETURN \\\\w+\");\n\t}\n\n\t@Test\n\tvoid matchOnRelationshipsShouldWorkInverse() {\n\n\t\tvar cypher = Cypher.match(Person.PERSON.DIRECTED.inverse()).returning(Person.PERSON).build().getCypher();\n\n\t\tAssertions.assertThat(cypher)\n\t\t\t.matches(\"MATCH \\\\(\\\\w+:`Movie`\\\\)<-\\\\[:`DIRECTED`]-\\\\(\\\\w+:`Person`\\\\) RETURN \\\\w+\");\n\t}\n\n\t@Test\n\tvoid multipleRelationships() {\n\n\t\t// tag::multiple-relationships[]\n\t\tvar cypher = Cypher.match(Person.PERSON.DIRECTED)\n\t\t\t.match(Person.PERSON.ACTED_IN)\n\t\t\t.returning(Person.PERSON.DIRECTED, Person.PERSON.ACTED_IN)\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\t// end::multiple-relationships[]\n\n\t\tAssertions.assertThat(cypher)\n\t\t\t.matches(\n\t\t\t\t\t\"MATCH \\\\(\\\\w+:`Person`\\\\)-\\\\[\\\\w+:`DIRECTED`]->\\\\(\\\\w+:`Movie`\\\\) MATCH \\\\(\\\\w+\\\\)-\\\\[\\\\w+:`ACTED_IN`]->\\\\(\\\\w+\\\\) RETURN \\\\w+, \\\\w+\");\n\t}\n\n\t@Test\n\tvoid chaining() {\n\n\t\t// tag::chaining-relationships[]\n\t\tvar otherPerson = Person.PERSON.named(\"o\");\n\t\tvar cypher = Cypher.match(Person.PERSON.DIRECTED.inverse().relationshipTo(otherPerson, \"FOLLOWS\") // <.>\n\t\t).where(otherPerson.NAME.isEqualTo(Cypher.literalOf(\"Someone\"))).returning(Person.PERSON).build().getCypher();\n\n\t\tAssertions.assertThat(cypher)\n\t\t\t.matches(\n\t\t\t\t\t\"MATCH \\\\(\\\\w+:`Movie`\\\\)<-\\\\[:`DIRECTED`]-\\\\(\\\\w+:`Person`\\\\)-\\\\[:`FOLLOWS`]->\\\\(o:`Person`\\\\) WHERE o\\\\.name = 'Someone' RETURN \\\\w+\");\n\t\t// end::chaining-relationships[]\n\t}\n\n\t@Test\n\tvoid workWithPropertiesShouldBePossible() {\n\n\t\t// tag::work-with-properties[]\n\t\tvar cypher = Cypher.match(Person.PERSON).returning(Person.PERSON.NAME, Person.PERSON.BORN).build().getCypher();\n\n\t\tAssertions.assertThat(cypher).matches(\"MATCH \\\\(\\\\w+:`Person`\\\\) RETURN \\\\w+\\\\.name, \\\\w+\\\\.born\");\n\t\t// end::work-with-properties[]\n\t}\n\n\t@Test\n\tvoid queryingNonStaticInformationAndPathsShouldWork() {\n\n\t\tvar otherPerson = Person.PERSON.named(\"o\");\n\t\tvar cypher = Cypher\n\t\t\t.match(Person.PERSON.withProperties(Person.PERSON.NAME, Cypher.literalOf(\"Tom Hanks\"))\n\t\t\t\t.relationshipTo(otherPerson, \"WORKED_WITH\")) // <.>\n\t\t\t.returning(otherPerson.NAME)\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tAssertions.assertThat(cypher)\n\t\t\t.matches(\n\t\t\t\t\t\"MATCH \\\\(\\\\w+:`Person` \\\\{name: 'Tom Hanks'}\\\\)-\\\\[:`WORKED_WITH`]->\\\\(o:`Person`\\\\) RETURN o\\\\.name\");\n\t}\n\n\t@Test\n\tvoid workingOnTheDelegateShouldMakeSens() {\n\n\t\t// tag::deriving-new-properties[]\n\t\tvar cypher = Cypher.match(Person.PERSON)\n\t\t\t.returning(Person.PERSON.NAME.concat(Cypher.literalOf(\" whatever\")))\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tAssertions.assertThat(cypher).matches(\"MATCH \\\\(\\\\w+:`Person`\\\\) RETURN \\\\(\\\\w+\\\\.name \\\\+ ' whatever'\\\\)\");\n\t\t// end::deriving-new-properties[]\n\t}\n\n\t@Test\n\tvoid oldQueryDSLExampleRevisited() {\n\n\t\tvar person = new Person().named(\"person\");\n\t\tAssertions\n\t\t\t.assertThat(Cypher.match(person)\n\t\t\t\t.where(person.FIRST_NAME.eq(Cypher.literalOf(\"P\")).and(person.property(\"age\").gt(Cypher.literalOf(25))))\n\t\t\t\t.returning(person)\n\t\t\t\t.build()\n\t\t\t\t.getCypher())\n\t\t\t.isEqualTo(\"MATCH (person:`Person`) WHERE (person.firstName = 'P' AND person.age > 25) RETURN person\");\n\t}\n\n\t@Test\n\tvoid inheritanceMappingExampleNodes() {\n\n\t\tvar cypher = Cypher.match(Division.DIVISION).returning(Division.DIVISION.NAME).build().getCypher();\n\n\t\tAssertions.assertThat(cypher).matches(\"MATCH \\\\(\\\\w+:`DefaultNode`:`Division`\\\\) RETURN \\\\w+\\\\.name\");\n\t}\n\n\t@Test\n\tvoid namedInheritedModelShouldWork() {\n\n\t\tvar division = Division.DIVISION.named(\"d\");\n\n\t\tvar cypher = Cypher.match(division).returning(division.NAME).build().getCypher();\n\n\t\tAssertions.assertThat(cypher).matches(\"MATCH \\\\(d:`DefaultNode`:`Division`\\\\) RETURN d\\\\.name\");\n\t}\n\n\t@Test\n\tvoid inheritanceMatchOnRelationshipsShouldWork() {\n\n\t\tvar cypher = Cypher.match(Department.DEPARTMENT.BELONGS_TO)\n\t\t\t.returning(Division.DIVISION.asExpression(), Department.DEPARTMENT.BELONGS_TO.CREATED_AT)\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tAssertions.assertThat(cypher)\n\t\t\t.matches(\n\t\t\t\t\t\"MATCH \\\\(\\\\w+:`DefaultNode`:`Department`\\\\)-\\\\[\\\\w+:`COOP_REL`\\\\|`BELONGS_TO`]->\\\\(\\\\w+:`DefaultNode`:`Division`\\\\) RETURN \\\\w+, \\\\w+\\\\.createdAt\");\n\t}\n\n\t@Test\n\tvoid inheritanceMatchOnRelationshipsShouldWorkInverse() {\n\n\t\tvar inversRelationship = Department.DEPARTMENT.BELONGS_TO.inverse();\n\t\tvar cypher = Cypher.match(inversRelationship)\n\t\t\t.returning(Division.DIVISION.asExpression(),\n\t\t\t\t\tDepartment.DEPARTMENT.BELONGS_TO.CREATED_AT\n\t\t\t\t\t\t.referencedAs(inversRelationship.getRequiredSymbolicName().getValue()))\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tAssertions.assertThat(cypher)\n\t\t\t.matches(\n\t\t\t\t\t\"MATCH \\\\(\\\\w+:`DefaultNode`:`Division`\\\\)<-\\\\[\\\\w+:`COOP_REL`\\\\|`BELONGS_TO`]-\\\\(\\\\w+:`DefaultNode`:`Department`\\\\) RETURN \\\\w+, \\\\w+\\\\.createdAt\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-core/src/test/java/org/neo4j/cypherdsl/examples/model/UnboundRelation.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.model;\n\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeBase;\nimport org.neo4j.cypherdsl.core.Properties;\nimport org.neo4j.cypherdsl.core.RelationshipBase;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n/**\n * Basically only the holder of the type.\n *\n * @param <S> start node\n * @param <E> end node\n * @author Michael J. Simons\n */\npublic final class UnboundRelation<S extends NodeBase<?>, E extends NodeBase<?>>\n\t\textends RelationshipBase<S, E, UnboundRelation<S, E>> {\n\n\tpublic static final String $TYPE = \"UNBOUND\";\n\n\tprotected UnboundRelation(S start, E end) {\n\t\tsuper(start, $TYPE, end);\n\t}\n\n\tprivate UnboundRelation(SymbolicName symbolicName, Node start, Properties properties, Node end) {\n\t\tsuper(symbolicName, start, $TYPE, properties, end);\n\t}\n\n\t@Override\n\tpublic UnboundRelation<S, E> named(SymbolicName newSymbolicName) {\n\n\t\treturn new UnboundRelation<>(newSymbolicName, getLeft(), getDetails().getProperties(), getRight());\n\t}\n\n\t@Override\n\tpublic UnboundRelation<S, E> withProperties(MapExpression newProperties) {\n\n\t\treturn new UnboundRelation<>(getSymbolicName().orElse(null), getLeft(), Properties.create(newProperties),\n\t\t\t\tgetRight());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-examples</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-examples-ogm-quarkus</artifactId>\n\n\t<name>Examples (OGM Code generator)</name>\n\t<description>Example how to use the OGM code generator in a Quarkus application.</description>\n\n\t<properties>\n\t\t<!-- This is fine here, as it is only example code -->\n\t\t<covered-ratio-complexity>0.4</covered-ratio-complexity>\n\t\t<covered-ratio-instructions>0.3</covered-ratio-instructions>\n\t\t<java-module-name>org.neo4j.cypherdsl.examples.ogm_quarkus</java-module-name>\n\t\t<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>\n\t\t<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>\n\t\t<sonar.coverage.jacoco.xmlReportPaths>${basedir}/../../${aggregate.report.dir}</sonar.coverage.jacoco.xmlReportPaths>\n\t</properties>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>${quarkus.platform.group-id}</groupId>\n\t\t\t\t<artifactId>${quarkus.platform.artifact-id}</artifactId>\n\t\t\t\t<version>${quarkus.platform.version}</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-dsl-bom</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>io.quarkus</groupId>\n\t\t\t<artifactId>quarkus-arc</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.quarkus</groupId>\n\t\t\t<artifactId>quarkus-resteasy-jsonb</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-ogm-quarkus</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.quarkus</groupId>\n\t\t\t<artifactId>quarkus-junit5</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>io.rest-assured</groupId>\n\t\t\t<artifactId>rest-assured</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.assertj</groupId>\n\t\t\t<artifactId>assertj-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"override\">\n\t\t\t\t\t<annotationProcessorPaths>\n\t\t\t\t\t\t<annotationProcessorPath>\n\t\t\t\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t\t\t\t<artifactId>neo4j-cypher-dsl-codegen-ogm</artifactId>\n\t\t\t\t\t\t\t<version>${project.version}</version>\n\t\t\t\t\t\t</annotationProcessorPath>\n\t\t\t\t\t</annotationProcessorPaths>\n\t\t\t\t\t<compilerArgs>\n\t\t\t\t\t\t<arg>-Xlint:all,-options,-path,-processing,-exports,-classfile</arg>\n\t\t\t\t\t\t<arg>-Werror</arg>\n\t\t\t\t\t\t<arg>-implicit:class</arg>\n\t\t\t\t\t</compilerArgs>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>${quarkus.platform.group-id}</groupId>\n\t\t\t\t<artifactId>quarkus-maven-plugin</artifactId>\n\t\t\t\t<version>${quarkus.platform.version}</version>\n\t\t\t\t<extensions>true</extensions>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>build</goal>\n\t\t\t\t\t\t\t<goal>generate-code</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<systemPropertyVariables>\n\t\t\t\t\t\t<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>\n\t\t\t\t\t\t<maven.home>${maven.home}</maven.home>\n\t\t\t\t\t</systemPropertyVariables>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-failsafe-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<systemPropertyVariables>\n\t\t\t\t\t\t<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>\n\t\t\t\t\t\t<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>\n\t\t\t\t\t\t<maven.home>${maven.home}</maven.home>\n\t\t\t\t\t</systemPropertyVariables>\n\t\t\t\t</configuration>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>integration-test</goal>\n\t\t\t\t\t\t\t<goal>verify</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/books/Book.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.books;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Book {\n\n\t@Id\n\t@GeneratedValue\n\tString id;\n\n\tprivate String lang;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/books/BookGenre.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.books;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class BookGenre {\n\n\t@Id\n\t@GeneratedValue\n\tString id;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/books/UserDetails.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.books;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class UserDetails {\n\n\t@Id\n\t@GeneratedValue\n\tString id;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/books/UserPreferences.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.books;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class UserPreferences {\n\n\t@Id\n\t@GeneratedValue\n\tString id;\n\n\tString userId;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/books/UserSuggestionActivity.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.books;\n\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class UserSuggestionActivity {\n\n\t@Id\n\t@GeneratedValue\n\tString id;\n\n\tString userId;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/books/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * This package exists only to reproduce an issue, it is not a complete example.\n */\npackage org.neo4j.cypherdsl.examples.ogm.books;\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/misc/Example.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.misc;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@NodeEntity\npublic class Example {\n\n\t@Id\n\tprivate final long id;\n\n\t@Relationship(type = \"BELONGS_TO\")\n\tprivate Example parent;\n\n\tpublic Example(long id) {\n\t\tthis.id = id;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/misc/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * More OGM examples.\n */\npackage org.neo4j.cypherdsl.examples.ogm.misc;\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/movies/Actor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.movies;\n\nimport java.util.List;\n\nimport jakarta.json.bind.annotation.JsonbProperty;\nimport jakarta.json.bind.annotation.JsonbTransient;\nimport org.neo4j.ogm.annotation.EndNode;\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.RelationshipEntity;\nimport org.neo4j.ogm.annotation.StartNode;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@RelationshipEntity(\"ACTED_IN\")\npublic final class Actor {\n\n\t@Id\n\t@GeneratedValue\n\t@JsonbTransient\n\tprivate Long id;\n\n\tprivate List<String> roles;\n\n\t@StartNode\n\t@JsonbTransient\n\tprivate Person person;\n\n\t@EndNode\n\tprivate Movie movie;\n\n\t/**\n\t * {@return name of this actor}\n\t */\n\t@JsonbProperty\n\tpublic String getName() {\n\t\treturn this.person.getName();\n\t}\n\n\t/**\n\t * {@return read only view of all the roles this actor played}\n\t */\n\tpublic List<String> getRoles() {\n\t\treturn List.copyOf(this.roles);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/movies/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.movies;\n\nimport java.time.LocalDate;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\n\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\nimport org.neo4j.ogm.annotation.Property;\nimport org.neo4j.ogm.annotation.Relationship;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@NodeEntity\npublic final class Movie {\n\n\t@Id\n\tprivate String title;\n\n\t@Property(\"tagline\")\n\tprivate String description;\n\n\t@Relationship(value = \"ACTED_IN\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Actor> actors = new ArrayList<>();\n\n\t@Relationship(value = \"DIRECTED\", direction = Relationship.Direction.INCOMING)\n\tprivate List<Person> directors = new ArrayList<>();\n\n\tprivate LocalDate watchedOn;\n\n\tprivate Integer released;\n\n\t/**\n\t * A new movie.\n\t * @param title the unmodifiable title\n\t */\n\tpublic Movie(String title) {\n\t\tthis.title = title;\n\t}\n\n\t/**\n\t * Make OGM happy.\n\t */\n\tMovie() {\n\t}\n\n\t/**\n\t * {@return the title}\n\t */\n\tpublic String getTitle() {\n\t\treturn this.title;\n\t}\n\n\t/**\n\t * {@return the description}\n\t */\n\tpublic String getDescription() {\n\t\treturn this.description;\n\t}\n\n\t/**\n\t * {@return read only view of the actors}\n\t */\n\tpublic List<Actor> getActors() {\n\t\treturn List.copyOf(this.actors);\n\t}\n\n\t/**\n\t * {@return read only view of the directors}\n\t */\n\tpublic List<Person> getDirectors() {\n\t\treturn List.copyOf(this.directors);\n\t}\n\n\t/**\n\t * {@return release year}\n\t */\n\tpublic Integer getReleased() {\n\t\treturn this.released;\n\t}\n\n\t/**\n\t * Sets the release year.\n\t * @param released new release year\n\t */\n\tpublic void setReleased(Integer released) {\n\t\tthis.released = released;\n\t}\n\n\t/**\n\t * Adds new actors.\n\t * @param newActors list of new actors\n\t * @return this instance\n\t */\n\tpublic Movie addActors(Collection<Actor> newActors) {\n\t\tthis.actors.addAll(newActors);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds new directors.\n\t * @param newDirectors list of new actors\n\t * @return this instance\n\t */\n\tpublic Movie addDirectors(Collection<Person> newDirectors) {\n\t\tthis.directors.addAll(newDirectors);\n\t\treturn this;\n\t}\n\n\tpublic LocalDate getWatchedOn() {\n\t\treturn this.watchedOn;\n\t}\n\n\tpublic void setWatchedOn(LocalDate watchedOn) {\n\t\tthis.watchedOn = watchedOn;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/movies/MovieRepository.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.movies;\n\nimport java.util.Collection;\nimport java.util.Map;\n\nimport jakarta.enterprise.context.ApplicationScoped;\nimport org.neo4j.ogm.session.SessionFactory;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@ApplicationScoped\nclass MovieRepository {\n\n\tprivate final SessionFactory sessionFactory;\n\n\tMovieRepository(SessionFactory sessionFactory) {\n\t\tthis.sessionFactory = sessionFactory;\n\t}\n\n\tCollection<Movie> findAll() {\n\n\t\treturn this.sessionFactory.openSession().loadAll(Movie.class);\n\t}\n\n\tMovie findByTitle(String title) {\n\n\t\treturn this.sessionFactory.openSession()\n\t\t\t.queryForObject(Movie.class, \"MATCH (m:$($label)) WHERE m[$property] = $propertyValue RETURN m\", Map\n\t\t\t\t.of(\"label\", Movie_.$PRIMARY_LABEL, \"property\", Movie_.MOVIE.TITLE.getName(), \"propertyValue\", title));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/movies/MovieResource.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.movies;\n\nimport java.util.Collection;\n\nimport jakarta.enterprise.context.RequestScoped;\nimport jakarta.inject.Inject;\nimport jakarta.ws.rs.GET;\nimport jakarta.ws.rs.Path;\nimport jakarta.ws.rs.PathParam;\nimport jakarta.ws.rs.Produces;\nimport jakarta.ws.rs.core.MediaType;\n\n/**\n * Example resource.\n *\n * @author Michael J. Simons\n */\n@RequestScoped\n@Path(\"/api/movies\")\npublic class MovieResource {\n\n\tprivate final MovieRepository movieRepository;\n\n\t/**\n\t * Creates a new {@link MovieResource}.\n\t * @param movieRepository the repository to retrieve movies from\n\t */\n\t@Inject\n\tpublic MovieResource(MovieRepository movieRepository) {\n\t\tthis.movieRepository = movieRepository;\n\t}\n\n\t/**\n\t * {@return all movies}\n\t */\n\t@GET\n\t@Produces(MediaType.APPLICATION_JSON)\n\tpublic Collection<Movie> getMovies() {\n\n\t\treturn this.movieRepository.findAll();\n\t}\n\n\t@GET\n\t@Path(\"/{title}\")\n\t@Produces(MediaType.APPLICATION_JSON)\n\tpublic Movie getMovie(@PathParam(\"title\") String title) {\n\t\treturn this.movieRepository.findByTitle(title);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/movies/PeopleRepository.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.movies;\n\nimport jakarta.enterprise.context.ApplicationScoped;\nimport org.neo4j.ogm.session.SessionFactory;\n\n/**\n * Example repository.\n *\n * @author Michael J. Simons\n */\n@ApplicationScoped\nclass PeopleRepository {\n\n\tprivate final SessionFactory sessionFactory;\n\n\tPeopleRepository(SessionFactory sessionFactory) {\n\t\tthis.sessionFactory = sessionFactory;\n\t}\n\n\tPerson save(Person person) {\n\n\t\tvar session = this.sessionFactory.openSession();\n\t\tsession.save(person);\n\t\treturn person;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/movies/PeopleResource.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.movies;\n\nimport jakarta.enterprise.context.RequestScoped;\nimport jakarta.ws.rs.POST;\nimport jakarta.ws.rs.Path;\nimport jakarta.ws.rs.Produces;\nimport jakarta.ws.rs.core.MediaType;\nimport jakarta.ws.rs.core.Response;\n\n/**\n * Example resource.\n *\n * @author Michael J. Simons\n */\n@RequestScoped\n@Path(\"/api/people\")\npublic class PeopleResource {\n\n\tprivate final PeopleRepository peopleRepository;\n\n\t/**\n\t * Creates a new instance with based on the given repository.\n\t * @param peopleRepository the repository to retrieve people from\n\t */\n\tpublic PeopleResource(PeopleRepository peopleRepository) {\n\t\tthis.peopleRepository = peopleRepository;\n\t}\n\n\t/**\n\t * Creates a new person.\n\t * @param newPerson the new person\n\t * @return response containing the new person\n\t */\n\t@POST\n\t@Produces(MediaType.APPLICATION_JSON)\n\tpublic Response createNewPerson(Person newPerson) {\n\n\t\tvar savedPerson = this.peopleRepository.save(newPerson);\n\t\treturn Response.status(Response.Status.CREATED).entity(savedPerson).build();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/movies/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.movies;\n\nimport jakarta.json.bind.annotation.JsonbCreator;\nimport jakarta.json.bind.annotation.JsonbProperty;\nimport org.neo4j.ogm.annotation.GeneratedValue;\nimport org.neo4j.ogm.annotation.Id;\nimport org.neo4j.ogm.annotation.NodeEntity;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@NodeEntity\npublic final class Person {\n\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\n\tprivate String name;\n\n\tprivate Integer born;\n\n\t/**\n\t * A new person with a given name and a year of birth.\n\t * @param name given name\n\t * @param born and a year in which they have been born\n\t */\n\t@JsonbCreator\n\tpublic Person(@JsonbProperty(\"name\") String name, @JsonbProperty(\"born\") Integer born) {\n\t\tthis.name = name;\n\t\tthis.born = born;\n\t}\n\n\t/**\n\t * Make OGM happy.\n\t */\n\tPerson() {\n\t}\n\n\t/**\n\t * {@return the person id}\n\t */\n\tpublic Long getId() {\n\t\treturn this.id;\n\t}\n\n\t/**\n\t * {@return the name}\n\t */\n\tpublic String getName() {\n\t\treturn this.name;\n\t}\n\n\t/**\n\t * {@return birth year}\n\t */\n\tpublic Integer getBorn() {\n\t\treturn this.born;\n\t}\n\n\t/**\n\t * Sets the year of birth.\n\t * @param born a new birth year\n\t */\n\tpublic void setBorn(Integer born) {\n\t\tthis.born = born;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/java/org/neo4j/cypherdsl/examples/ogm/movies/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * OGM Movie example.\n */\npackage org.neo4j.cypherdsl.examples.ogm.movies;\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/main/resources/application.properties",
    "content": "#\n# Copyright (c) 2019-2026 \"Neo4j,\"\n# Neo4j Sweden AB [https://neo4j.com]\n#\n# This file is part of Neo4j.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\norg.neo4j.ogm.base-packages=org.neo4j.cypherdsl.examples.ogm.movies\norg.neo4j.ogm.use-native-types=true\nquarkus.neo4j.devservices.image-name=neo4j:2025.06\n\norg.neo4j.migrations.enabled=false\norg.neo4j.migrations.locations-to-scan=neo4j/migrations,neo4j/example-data\n\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/test/java/org/neo4j/cypherdsl/examples/ogm/Neo4jOgmResourcesIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm;\n\nimport java.io.IOException;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.time.Duration;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\n\nimport io.quarkus.test.junit.QuarkusTest;\nimport io.restassured.RestAssured;\nimport io.restassured.http.ContentType;\nimport jakarta.inject.Inject;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.TestInstance;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.driver.Driver;\nimport org.neo4j.driver.Values;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\n@QuarkusTest\n@TestInstance(TestInstance.Lifecycle.PER_CLASS)\npublic class Neo4jOgmResourcesIT {\n\n\tprivate static final int NUMBER_OF_INITIAL_MOVIES = 38;\n\n\t@Inject\n\tDriver driver;\n\n\t@BeforeAll\n\tpublic void createData() throws IOException {\n\n\t\tvar movies = Files.readString(\n\t\t\t\tPath.of(Objects.requireNonNull(Neo4jOgmResourcesIT.class.getResource(\"/movies.cypher\")).getPath()));\n\n\t\ttry (var session = this.driver.session(); var tx = session.beginTransaction()) {\n\t\t\ttx.run(\"MATCH (n) DETACH DELETE n\");\n\t\t\ttx.run(movies);\n\t\t\ttx.commit();\n\t\t}\n\t}\n\n\t/**\n\t * Test not Quarkus or Code gen builder specific, we just happen to have both a Neo4j\n\t * instance and a driver connected to it.\n\t */\n\t@Test // GH-1449\n\tvoid everlastingDurationFun() {\n\n\t\tvar theDuration = Duration.ofDays(364).plusHours(47).plusMinutes(59).plusSeconds(61).plusMillis(1001);\n\t\tvar isoOne = this.driver.executableQuery(Cypher.returning(Cypher.literalOf(theDuration)).build().getCypher())\n\t\t\t.execute()\n\t\t\t.records()\n\t\t\t.get(0)\n\t\t\t.get(0)\n\t\t\t.asIsoDuration();\n\t\tvar isoTwo = this.driver.executableQuery(\"RETURN $1\")\n\t\t\t.withParameters(Map.of(\"1\", Values.value(theDuration)))\n\t\t\t.execute()\n\t\t\t.records()\n\t\t\t.get(0)\n\t\t\t.get(0)\n\t\t\t.asIsoDuration();\n\t\tassertThat(isoOne).isEqualTo(isoTwo);\n\t}\n\n\t@Test\n\tpublic void getMoviesShouldWork() {\n\t\tvar response = RestAssured.given().when().get(\"/api/movies\").then().statusCode(200).extract().response();\n\n\t\tvar json = response.jsonPath();\n\t\tassertThat(json.<List<?>>getJsonObject(\"$\").size()).isEqualTo(NUMBER_OF_INITIAL_MOVIES);\n\t\tvar allTitles = json.<List<String>>getJsonObject(\"title\");\n\t\tassertThat(allTitles.contains(\"Cloud Atlas\")).isTrue();\n\t}\n\n\t@Test\n\tpublic void getMovieWithANativeTypeShouldWork() {\n\t\tvar response = RestAssured.given()\n\t\t\t.when()\n\t\t\t.get(\"/api/movies/The Matrix\")\n\t\t\t.then()\n\t\t\t.statusCode(200)\n\t\t\t.extract()\n\t\t\t.response();\n\n\t\tvar json = response.jsonPath();\n\t\tassertThat(json.<String>get(\"watchedOn\")).isNotNull();\n\t}\n\n\t@Test\n\tpublic void createPersonShouldWork() {\n\n\t\tvar response = RestAssured.given()\n\t\t\t.body(\"{\\\"name\\\":\\\"Lieschen Müller\\\",\\\"born\\\":2020}\")\n\t\t\t.contentType(ContentType.JSON)\n\t\t\t.when()\n\t\t\t.post(\"/api/people\")\n\t\t\t.then()\n\t\t\t.statusCode(201)\n\t\t\t.extract()\n\t\t\t.response();\n\n\t\tvar json = response.jsonPath();\n\t\tassertThat(json.getObject(\"id\", Long.class)).isNotNull();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/test/java/org/neo4j/cypherdsl/examples/ogm/UsageTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.examples.ogm.misc.Example_;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n *\n */\nclass UsageTests {\n\n\t@Test // GH-335\n\tvoid defaultUsageOfSelfReferentialNode() {\n\t\tExample_ node = Example_.EXAMPLE;\n\t\tassertThat(node).isNotNull();\n\t}\n\n\t@Test // GH-335\n\tvoid selfReferentialNodesShouldLeadToUsableCode() {\n\t\tExample_ node = Example_.EXAMPLE.named(\"example\");\n\t\tassertThat(node).isNotNull();\n\t}\n\n\t@Test // GH-335\n\tvoid ltolx() {\n\n\t\tvar left = Example_.EXAMPLE.named(\"n\");\n\t\tvar parent = left.withParent(Example_.EXAMPLE.named(\"m\"));\n\t\tassertThat(parent.getLeft().getRequiredSymbolicName().getValue()).isEqualTo(\"n\");\n\t}\n\n\t@Test // GH-335\n\tvoid rtorx() {\n\n\t\tvar parent = Example_.EXAMPLE.withParent(Example_.EXAMPLE.named(\"m\"));\n\t\tassertThat(parent.getRight().getRequiredSymbolicName().getValue()).isEqualTo(\"m\");\n\t}\n\n\t@Test // GH-335\n\tvoid renamingLRShouldWork() {\n\n\t\tvar left = Example_.EXAMPLE.named(\"n\");\n\t\tvar right = Example_.EXAMPLE.named(\"m\");\n\t\tvar rel = left.withParent(right).named(\"r\");\n\t\tvar cypher = Cypher.match(rel)\n\t\t\t.where(right.ID.isEqualTo(Cypher.literalOf(1L)))\n\t\t\t.returning(left, right)\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (n:`Example`)-[r:`BELONGS_TO`]->(m:`Example`) WHERE m.id = 1 RETURN n, m\");\n\t}\n\n\t@Test // GH-335\n\tvoid renamingShouldWork() {\n\n\t\tvar node = Example_.EXAMPLE.named(\"n\");\n\t\tvar rel = node.withParent(Example_.EXAMPLE).named(\"r\");\n\t\tvar cypher = Cypher.match(rel)\n\t\t\t.where(node.ID.isEqualTo(Cypher.literalOf(1L)))\n\t\t\t.returning(node)\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher\n\t\t\t.matches(\"MATCH \\\\(n:`Example`\\\\)-\\\\[r:`BELONGS_TO`]->\\\\(.+:`Example`\\\\) WHERE n\\\\.id = 1 RETURN n\"))\n\t\t\t.isTrue();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/test/java/org/neo4j/cypherdsl/examples/ogm/books/ScopingTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.ogm.books;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.ValueSource;\nimport org.neo4j.cypherdsl.core.Cypher;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass ScopingTests {\n\n\t@ParameterizedTest // GH-1014\n\t@ValueSource(booleans = { true, false })\n\tvoid patternExpressionMustNotIntroduceNames(boolean withIt) {\n\n\t\tvar userIdParam = Cypher.parameter(\"userId\");\n\t\tvar limitParam = Cypher.parameter(\"limit\");\n\t\tvar langParam = Cypher.parameter(\"lang\");\n\n\t\tvar book = Book_.BOOK.withProperties(Book_.BOOK.LANG, langParam).named(\"book\");\n\n\t\tvar userDetails = UserDetails_.USER_DETAILS.withProperties(UserDetails_.USER_DETAILS.ID, userIdParam)\n\t\t\t.named(\"user\");\n\t\tvar userPreferences = UserPreferences_.USER_PREFERENCES\n\t\t\t.withProperties(UserPreferences_.USER_PREFERENCES.USER_ID, userIdParam)\n\t\t\t.named(\"preferences\");\n\t\tvar genre = BookGenre_.BOOK_GENRE.named(\"genre\");\n\t\tvar userActivity = UserSuggestionActivity_.USER_SUGGESTION_ACTIVITY\n\t\t\t.withProperties(UserSuggestionActivity_.USER_SUGGESTION_ACTIVITY.USER_ID, userIdParam)\n\t\t\t.named(\"activity\");\n\n\t\tvar relationBookGenre = book.relationshipTo(genre, \"BELONGS_TO\").named(\"rel\");\n\n\t\tvar relationBookAvoidedGenre = book.relationshipTo(BookGenre_.BOOK_GENRE, \"BELONGS_TO\")\n\t\t\t.relationshipFrom(userPreferences, \"AVOIDED\");\n\n\t\tvar relationUserPreferencesGenreBook = userDetails.relationshipTo(userPreferences, \"HAS_PREFERENCES\")\n\t\t\t.relationshipTo(genre, \"PREFERRED\")\n\t\t\t.relationshipFrom(book, \"BELONGS_TO\");\n\n\t\tvar returningBooks = Cypher.call(\"distinct\").withArgs(Cypher.name(\"book\")).asFunction();\n\n\t\t// This is the correct variant, as shown in the latest code update on the issue,\n\t\t// matching the activity first, then\n\t\t// passing it on.\n\t\tif (withIt) {\n\t\t\tvar statement = Cypher.match(relationUserPreferencesGenreBook)\n\t\t\t\t.match(userDetails.relationshipTo(userActivity, \"HAS_ACTIVITY\"))\n\t\t\t\t.where(Cypher.not(Cypher.exists(relationBookAvoidedGenre)))\n\t\t\t\t.with(book, userActivity)\n\t\t\t\t.limit(limitParam)\n\t\t\t\t.match(relationBookGenre)\n\t\t\t\t.where(Cypher.not(Cypher.exists(book.relationshipBetween(userActivity))))\n\t\t\t\t.returning(returningBooks, Cypher.collect(Cypher.name(\"rel\")), Cypher.collect(genre))\n\t\t\t\t.build();\n\n\t\t\tassertThat(statement.getCypher()).isEqualTo(\n\t\t\t\t\t\"MATCH (user:`UserDetails` {id: $userId})-[:`HAS_PREFERENCES`]->(preferences:`UserPreferences` {userId: $userId})-[:`PREFERRED`]->(genre:`BookGenre`)<-[:`BELONGS_TO`]-(book:`Book` {lang: $lang}) MATCH (user)-[:`HAS_ACTIVITY`]->(activity:`UserSuggestionActivity` {userId: $userId}) WHERE NOT (exists((book)-[:`BELONGS_TO`]->(:`BookGenre`)<-[:`AVOIDED`]-(preferences))) WITH book, activity LIMIT $limit MATCH (book)-[rel:`BELONGS_TO`]->(genre:`BookGenre`) WHERE NOT (exists((book)--(activity))) RETURN distinct(book), collect(rel), collect(genre)\");\n\n\t\t}\n\t\telse {\n\t\t\t// Statement is identical, except the with clause. activity goes out of scope,\n\t\t\t// hence in the existential subquery it will be rerendered.\n\t\t\t// There however it must not include the name a new\n\t\t\tvar statement = Cypher.match(relationUserPreferencesGenreBook)\n\t\t\t\t.match(userDetails.relationshipTo(userActivity, \"HAS_ACTIVITY\"))\n\t\t\t\t.where(Cypher.not(Cypher.exists(relationBookAvoidedGenre)))\n\t\t\t\t.with(book)\n\t\t\t\t.limit(limitParam)\n\t\t\t\t.match(relationBookGenre)\n\t\t\t\t.where(Cypher.not(Cypher.exists(book.relationshipBetween(userActivity))))\n\t\t\t\t.returning(returningBooks, Cypher.collect(Cypher.name(\"rel\")), Cypher.collect(genre))\n\t\t\t\t.build();\n\t\t\tassertThat(statement.getCypher()).isEqualTo(\n\t\t\t\t\t\"MATCH (user:`UserDetails` {id: $userId})-[:`HAS_PREFERENCES`]->(preferences:`UserPreferences` {userId: $userId})-[:`PREFERRED`]->(genre:`BookGenre`)<-[:`BELONGS_TO`]-(book:`Book` {lang: $lang}) MATCH (user)-[:`HAS_ACTIVITY`]->(activity:`UserSuggestionActivity` {userId: $userId}) WHERE NOT (exists((book)-[:`BELONGS_TO`]->(:`BookGenre`)<-[:`AVOIDED`]-(preferences))) WITH book LIMIT $limit MATCH (book)-[rel:`BELONGS_TO`]->(genre:`BookGenre`) WHERE NOT (exists((book)--(:`UserSuggestionActivity` {userId: $userId}))) RETURN distinct(book), collect(rel), collect(genre)\");\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-ogm-quarkus/src/test/resources/movies.cypher",
    "content": "CREATE (TheMatrix:Movie {title:'The Matrix', released:1999, tagline:'Welcome to the Real World', watchedOn: date()})\nCREATE (Keanu:Person {name:'Keanu Reeves', born:1964})\nCREATE (Carrie:Person {name:'Carrie-Anne Moss', born:1967})\nCREATE (Laurence:Person {name:'Laurence Fishburne', born:1961})\nCREATE (Hugo:Person {name:'Hugo Weaving', born:1960})\nCREATE (LillyW:Person {name:'Lilly Wachowski', born:1967})\nCREATE (LanaW:Person {name:'Lana Wachowski', born:1965})\nCREATE (JoelS:Person {name:'Joel Silver', born:1952})\nCREATE\n(Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrix),\n(Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrix),\n(Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrix),\n(Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrix),\n(LillyW)-[:DIRECTED]->(TheMatrix),\n(LanaW)-[:DIRECTED]->(TheMatrix),\n(JoelS)-[:PRODUCED]->(TheMatrix)\n\nCREATE (Emil:Person {name:\"Emil Eifrem\", born:1978})\nCREATE (Emil)-[:ACTED_IN {roles:[\"Emil\"]}]->(TheMatrix)\n\nCREATE (TheMatrixReloaded:Movie {title:'The Matrix Reloaded', released:2003, tagline:'Free your mind'})\nCREATE\n(Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrixReloaded),\n(Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrixReloaded),\n(Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrixReloaded),\n(Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrixReloaded),\n(LillyW)-[:DIRECTED]->(TheMatrixReloaded),\n(LanaW)-[:DIRECTED]->(TheMatrixReloaded),\n(JoelS)-[:PRODUCED]->(TheMatrixReloaded)\n\nCREATE (TheMatrixRevolutions:Movie {title:'The Matrix Revolutions', released:2003, tagline:'Everything that has a beginning has an end'})\nCREATE\n(Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrixRevolutions),\n(Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrixRevolutions),\n(Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrixRevolutions),\n(Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrixRevolutions),\n(LillyW)-[:DIRECTED]->(TheMatrixRevolutions),\n(LanaW)-[:DIRECTED]->(TheMatrixRevolutions),\n(JoelS)-[:PRODUCED]->(TheMatrixRevolutions)\n\nCREATE (TheDevilsAdvocate:Movie {title:\"The Devil's Advocate\", released:1997, tagline:'Evil has its winning ways'})\nCREATE (Charlize:Person {name:'Charlize Theron', born:1975})\nCREATE (Al:Person {name:'Al Pacino', born:1940})\nCREATE (Taylor:Person {name:'Taylor Hackford', born:1944})\nCREATE\n(Keanu)-[:ACTED_IN {roles:['Kevin Lomax']}]->(TheDevilsAdvocate),\n(Charlize)-[:ACTED_IN {roles:['Mary Ann Lomax']}]->(TheDevilsAdvocate),\n(Al)-[:ACTED_IN {roles:['John Milton']}]->(TheDevilsAdvocate),\n(Taylor)-[:DIRECTED]->(TheDevilsAdvocate)\n\nCREATE (AFewGoodMen:Movie {title:\"A Few Good Men\", released:1992, tagline:\"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.\"})\nCREATE (TomC:Person {name:'Tom Cruise', born:1962})\nCREATE (JackN:Person {name:'Jack Nicholson', born:1937})\nCREATE (DemiM:Person {name:'Demi Moore', born:1962})\nCREATE (KevinB:Person {name:'Kevin Bacon', born:1958})\nCREATE (KieferS:Person {name:'Kiefer Sutherland', born:1966})\nCREATE (NoahW:Person {name:'Noah Wyle', born:1971})\nCREATE (CubaG:Person {name:'Cuba Gooding Jr.', born:1968})\nCREATE (KevinP:Person {name:'Kevin Pollak', born:1957})\nCREATE (JTW:Person {name:'J.T. Walsh', born:1943})\nCREATE (JamesM:Person {name:'James Marshall', born:1967})\nCREATE (ChristopherG:Person {name:'Christopher Guest', born:1948})\nCREATE (RobR:Person {name:'Rob Reiner', born:1947})\nCREATE (AaronS:Person {name:'Aaron Sorkin', born:1961})\nCREATE\n(TomC)-[:ACTED_IN {roles:['Lt. Daniel Kaffee']}]->(AFewGoodMen),\n(JackN)-[:ACTED_IN {roles:['Col. Nathan R. Jessup']}]->(AFewGoodMen),\n(DemiM)-[:ACTED_IN {roles:['Lt. Cdr. JoAnne Galloway']}]->(AFewGoodMen),\n(KevinB)-[:ACTED_IN {roles:['Capt. Jack Ross']}]->(AFewGoodMen),\n(KieferS)-[:ACTED_IN {roles:['Lt. Jonathan Kendrick']}]->(AFewGoodMen),\n(NoahW)-[:ACTED_IN {roles:['Cpl. Jeffrey Barnes']}]->(AFewGoodMen),\n(CubaG)-[:ACTED_IN {roles:['Cpl. Carl Hammaker']}]->(AFewGoodMen),\n(KevinP)-[:ACTED_IN {roles:['Lt. Sam Weinberg']}]->(AFewGoodMen),\n(JTW)-[:ACTED_IN {roles:['Lt. Col. Matthew Andrew Markinson']}]->(AFewGoodMen),\n(JamesM)-[:ACTED_IN {roles:['Pfc. Louden Downey']}]->(AFewGoodMen),\n(ChristopherG)-[:ACTED_IN {roles:['Dr. Stone']}]->(AFewGoodMen),\n(AaronS)-[:ACTED_IN {roles:['Man in Bar']}]->(AFewGoodMen),\n(RobR)-[:DIRECTED]->(AFewGoodMen),\n(AaronS)-[:WROTE]->(AFewGoodMen)\n\nCREATE (TopGun:Movie {title:\"Top Gun\", released:1986, tagline:'I feel the need, the need for speed.'})\nCREATE (KellyM:Person {name:'Kelly McGillis', born:1957})\nCREATE (ValK:Person {name:'Val Kilmer', born:1959})\nCREATE (AnthonyE:Person {name:'Anthony Edwards', born:1962})\nCREATE (TomS:Person {name:'Tom Skerritt', born:1933})\nCREATE (MegR:Person {name:'Meg Ryan', born:1961})\nCREATE (TonyS:Person {name:'Tony Scott', born:1944})\nCREATE (JimC:Person {name:'Jim Cash', born:1941})\nCREATE\n(TomC)-[:ACTED_IN {roles:['Maverick']}]->(TopGun),\n(KellyM)-[:ACTED_IN {roles:['Charlie']}]->(TopGun),\n(ValK)-[:ACTED_IN {roles:['Iceman']}]->(TopGun),\n(AnthonyE)-[:ACTED_IN {roles:['Goose']}]->(TopGun),\n(TomS)-[:ACTED_IN {roles:['Viper']}]->(TopGun),\n(MegR)-[:ACTED_IN {roles:['Carole']}]->(TopGun),\n(TonyS)-[:DIRECTED]->(TopGun),\n(JimC)-[:WROTE]->(TopGun)\n\nCREATE (JerryMaguire:Movie {title:'Jerry Maguire', released:2000, tagline:'The rest of his life begins now.'})\nCREATE (ReneeZ:Person {name:'Renee Zellweger', born:1969})\nCREATE (KellyP:Person {name:'Kelly Preston', born:1962})\nCREATE (JerryO:Person {name:\"Jerry O'Connell\", born:1974})\nCREATE (JayM:Person {name:'Jay Mohr', born:1970})\nCREATE (BonnieH:Person {name:'Bonnie Hunt', born:1961})\nCREATE (ReginaK:Person {name:'Regina King', born:1971})\nCREATE (JonathanL:Person {name:'Jonathan Lipnicki', born:1996})\nCREATE (CameronC:Person {name:'Cameron Crowe', born:1957})\nCREATE\n(TomC)-[:ACTED_IN {roles:['Jerry Maguire']}]->(JerryMaguire),\n(CubaG)-[:ACTED_IN {roles:['Rod Tidwell']}]->(JerryMaguire),\n(ReneeZ)-[:ACTED_IN {roles:['Dorothy Boyd']}]->(JerryMaguire),\n(KellyP)-[:ACTED_IN {roles:['Avery Bishop']}]->(JerryMaguire),\n(JerryO)-[:ACTED_IN {roles:['Frank Cushman']}]->(JerryMaguire),\n(JayM)-[:ACTED_IN {roles:['Bob Sugar']}]->(JerryMaguire),\n(BonnieH)-[:ACTED_IN {roles:['Laurel Boyd']}]->(JerryMaguire),\n(ReginaK)-[:ACTED_IN {roles:['Marcee Tidwell']}]->(JerryMaguire),\n(JonathanL)-[:ACTED_IN {roles:['Ray Boyd']}]->(JerryMaguire),\n(CameronC)-[:DIRECTED]->(JerryMaguire),\n(CameronC)-[:PRODUCED]->(JerryMaguire),\n(CameronC)-[:WROTE]->(JerryMaguire)\n\nCREATE (StandByMe:Movie {title:\"Stand By Me\", released:1986, tagline:\"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.\"})\nCREATE (RiverP:Person {name:'River Phoenix', born:1970})\nCREATE (CoreyF:Person {name:'Corey Feldman', born:1971})\nCREATE (WilW:Person {name:'Wil Wheaton', born:1972})\nCREATE (JohnC:Person {name:'John Cusack', born:1966})\nCREATE (MarshallB:Person {name:'Marshall Bell', born:1942})\nCREATE\n(WilW)-[:ACTED_IN {roles:['Gordie Lachance']}]->(StandByMe),\n(RiverP)-[:ACTED_IN {roles:['Chris Chambers']}]->(StandByMe),\n(JerryO)-[:ACTED_IN {roles:['Vern Tessio']}]->(StandByMe),\n(CoreyF)-[:ACTED_IN {roles:['Teddy Duchamp']}]->(StandByMe),\n(JohnC)-[:ACTED_IN {roles:['Denny Lachance']}]->(StandByMe),\n(KieferS)-[:ACTED_IN {roles:['Ace Merrill']}]->(StandByMe),\n(MarshallB)-[:ACTED_IN {roles:['Mr. Lachance']}]->(StandByMe),\n(RobR)-[:DIRECTED]->(StandByMe)\n\nCREATE (AsGoodAsItGets:Movie {title:'As Good as It Gets', released:1997, tagline:'A comedy from the heart that goes for the throat.'})\nCREATE (HelenH:Person {name:'Helen Hunt', born:1963})\nCREATE (GregK:Person {name:'Greg Kinnear', born:1963})\nCREATE (JamesB:Person {name:'James L. Brooks', born:1940})\nCREATE\n(JackN)-[:ACTED_IN {roles:['Melvin Udall']}]->(AsGoodAsItGets),\n(HelenH)-[:ACTED_IN {roles:['Carol Connelly']}]->(AsGoodAsItGets),\n(GregK)-[:ACTED_IN {roles:['Simon Bishop']}]->(AsGoodAsItGets),\n(CubaG)-[:ACTED_IN {roles:['Frank Sachs']}]->(AsGoodAsItGets),\n(JamesB)-[:DIRECTED]->(AsGoodAsItGets)\n\nCREATE (WhatDreamsMayCome:Movie {title:'What Dreams May Come', released:1998, tagline:'After life there is more. The end is just the beginning.'})\nCREATE (AnnabellaS:Person {name:'Annabella Sciorra', born:1960})\nCREATE (MaxS:Person {name:'Max von Sydow', born:1929})\nCREATE (WernerH:Person {name:'Werner Herzog', born:1942})\nCREATE (Robin:Person {name:'Robin Williams', born:1951})\nCREATE (VincentW:Person {name:'Vincent Ward', born:1956})\nCREATE\n(Robin)-[:ACTED_IN {roles:['Chris Nielsen']}]->(WhatDreamsMayCome),\n(CubaG)-[:ACTED_IN {roles:['Albert Lewis']}]->(WhatDreamsMayCome),\n(AnnabellaS)-[:ACTED_IN {roles:['Annie Collins-Nielsen']}]->(WhatDreamsMayCome),\n(MaxS)-[:ACTED_IN {roles:['The Tracker']}]->(WhatDreamsMayCome),\n(WernerH)-[:ACTED_IN {roles:['The Face']}]->(WhatDreamsMayCome),\n(VincentW)-[:DIRECTED]->(WhatDreamsMayCome)\n\nCREATE (SnowFallingonCedars:Movie {title:'Snow Falling on Cedars', released:1999, tagline:'First loves last. Forever.'})\nCREATE (EthanH:Person {name:'Ethan Hawke', born:1970})\nCREATE (RickY:Person {name:'Rick Yune', born:1971})\nCREATE (JamesC:Person {name:'James Cromwell', born:1940})\nCREATE (ScottH:Person {name:'Scott Hicks', born:1953})\nCREATE\n(EthanH)-[:ACTED_IN {roles:['Ishmael Chambers']}]->(SnowFallingonCedars),\n(RickY)-[:ACTED_IN {roles:['Kazuo Miyamoto']}]->(SnowFallingonCedars),\n(MaxS)-[:ACTED_IN {roles:['Nels Gudmundsson']}]->(SnowFallingonCedars),\n(JamesC)-[:ACTED_IN {roles:['Judge Fielding']}]->(SnowFallingonCedars),\n(ScottH)-[:DIRECTED]->(SnowFallingonCedars)\n\nCREATE (YouveGotMail:Movie {title:\"You've Got Mail\", released:1998, tagline:'At odds in life... in love on-line.'})\nCREATE (ParkerP:Person {name:'Parker Posey', born:1968})\nCREATE (DaveC:Person {name:'Dave Chappelle', born:1973})\nCREATE (SteveZ:Person {name:'Steve Zahn', born:1967})\nCREATE (TomH:Person {name:'Tom Hanks', born:1956})\nCREATE (NoraE:Person {name:'Nora Ephron', born:1941})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Joe Fox']}]->(YouveGotMail),\n(MegR)-[:ACTED_IN {roles:['Kathleen Kelly']}]->(YouveGotMail),\n(GregK)-[:ACTED_IN {roles:['Frank Navasky']}]->(YouveGotMail),\n(ParkerP)-[:ACTED_IN {roles:['Patricia Eden']}]->(YouveGotMail),\n(DaveC)-[:ACTED_IN {roles:['Kevin Jackson']}]->(YouveGotMail),\n(SteveZ)-[:ACTED_IN {roles:['George Pappas']}]->(YouveGotMail),\n(NoraE)-[:DIRECTED]->(YouveGotMail)\n\nCREATE (SleeplessInSeattle:Movie {title:'Sleepless in Seattle', released:1993, tagline:'What if someone you never met, someone you never saw, someone you never knew was the only someone for you?'})\nCREATE (RitaW:Person {name:'Rita Wilson', born:1956})\nCREATE (BillPull:Person {name:'Bill Pullman', born:1953})\nCREATE (VictorG:Person {name:'Victor Garber', born:1949})\nCREATE (RosieO:Person {name:\"Rosie O'Donnell\", born:1962})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Sam Baldwin']}]->(SleeplessInSeattle),\n(MegR)-[:ACTED_IN {roles:['Annie Reed']}]->(SleeplessInSeattle),\n(RitaW)-[:ACTED_IN {roles:['Suzy']}]->(SleeplessInSeattle),\n(BillPull)-[:ACTED_IN {roles:['Walter']}]->(SleeplessInSeattle),\n(VictorG)-[:ACTED_IN {roles:['Greg']}]->(SleeplessInSeattle),\n(RosieO)-[:ACTED_IN {roles:['Becky']}]->(SleeplessInSeattle),\n(NoraE)-[:DIRECTED]->(SleeplessInSeattle)\n\nCREATE (JoeVersustheVolcano:Movie {title:'Joe Versus the Volcano', released:1990, tagline:'A story of love, lava and burning desire.'})\nCREATE (JohnS:Person {name:'John Patrick Stanley', born:1950})\nCREATE (Nathan:Person {name:'Nathan Lane', born:1956})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Joe Banks']}]->(JoeVersustheVolcano),\n(MegR)-[:ACTED_IN {roles:['DeDe', 'Angelica Graynamore', 'Patricia Graynamore']}]->(JoeVersustheVolcano),\n(Nathan)-[:ACTED_IN {roles:['Baw']}]->(JoeVersustheVolcano),\n(JohnS)-[:DIRECTED]->(JoeVersustheVolcano)\n\nCREATE (WhenHarryMetSally:Movie {title:'When Harry Met Sally', released:1998, tagline:'Can two friends sleep together and still love each other in the morning?'})\nCREATE (BillyC:Person {name:'Billy Crystal', born:1948})\nCREATE (CarrieF:Person {name:'Carrie Fisher', born:1956})\nCREATE (BrunoK:Person {name:'Bruno Kirby', born:1949})\nCREATE\n(BillyC)-[:ACTED_IN {roles:['Harry Burns']}]->(WhenHarryMetSally),\n(MegR)-[:ACTED_IN {roles:['Sally Albright']}]->(WhenHarryMetSally),\n(CarrieF)-[:ACTED_IN {roles:['Marie']}]->(WhenHarryMetSally),\n(BrunoK)-[:ACTED_IN {roles:['Jess']}]->(WhenHarryMetSally),\n(RobR)-[:DIRECTED]->(WhenHarryMetSally),\n(RobR)-[:PRODUCED]->(WhenHarryMetSally),\n(NoraE)-[:PRODUCED]->(WhenHarryMetSally),\n(NoraE)-[:WROTE]->(WhenHarryMetSally)\n\nCREATE (ThatThingYouDo:Movie {title:'That Thing You Do', released:1996, tagline:'In every life there comes a time when that thing you dream becomes that thing you do'})\nCREATE (LivT:Person {name:'Liv Tyler', born:1977})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Mr. White']}]->(ThatThingYouDo),\n(LivT)-[:ACTED_IN {roles:['Faye Dolan']}]->(ThatThingYouDo),\n(Charlize)-[:ACTED_IN {roles:['Tina']}]->(ThatThingYouDo),\n(TomH)-[:DIRECTED]->(ThatThingYouDo)\n\nCREATE (TheReplacements:Movie {title:'The Replacements', released:2000, tagline:'Pain heals, Chicks dig scars... Glory lasts forever'})\nCREATE (Brooke:Person {name:'Brooke Langton', born:1970})\nCREATE (Gene:Person {name:'Gene Hackman', born:1930})\nCREATE (Orlando:Person {name:'Orlando Jones', born:1968})\nCREATE (Howard:Person {name:'Howard Deutch', born:1950})\nCREATE\n(Keanu)-[:ACTED_IN {roles:['Shane Falco']}]->(TheReplacements),\n(Brooke)-[:ACTED_IN {roles:['Annabelle Farrell']}]->(TheReplacements),\n(Gene)-[:ACTED_IN {roles:['Jimmy McGinty']}]->(TheReplacements),\n(Orlando)-[:ACTED_IN {roles:['Clifford Franklin']}]->(TheReplacements),\n(Howard)-[:DIRECTED]->(TheReplacements)\n\nCREATE (RescueDawn:Movie {title:'RescueDawn', released:2006, tagline:\"Based on the extraordinary true story of one man's fight for freedom\"})\nCREATE (ChristianB:Person {name:'Christian Bale', born:1974})\nCREATE (ZachG:Person {name:'Zach Grenier', born:1954})\nCREATE\n(MarshallB)-[:ACTED_IN {roles:['Admiral']}]->(RescueDawn),\n(ChristianB)-[:ACTED_IN {roles:['Dieter Dengler']}]->(RescueDawn),\n(ZachG)-[:ACTED_IN {roles:['Squad Leader']}]->(RescueDawn),\n(SteveZ)-[:ACTED_IN {roles:['Duane']}]->(RescueDawn),\n(WernerH)-[:DIRECTED]->(RescueDawn)\n\nCREATE (TheBirdcage:Movie {title:'The Birdcage', released:1996, tagline:'Come as you are'})\nCREATE (MikeN:Person {name:'Mike Nichols', born:1931})\nCREATE\n(Robin)-[:ACTED_IN {roles:['Armand Goldman']}]->(TheBirdcage),\n(Nathan)-[:ACTED_IN {roles:['Albert Goldman']}]->(TheBirdcage),\n(Gene)-[:ACTED_IN {roles:['Sen. Kevin Keeley']}]->(TheBirdcage),\n(MikeN)-[:DIRECTED]->(TheBirdcage)\n\nCREATE (Unforgiven:Movie {title:'Unforgiven', released:1992, tagline:\"It's a hell of a thing, killing a man\"})\nCREATE (RichardH:Person {name:'Richard Harris', born:1930})\nCREATE (ClintE:Person {name:'Clint Eastwood', born:1930})\nCREATE\n(RichardH)-[:ACTED_IN {roles:['English Bob']}]->(Unforgiven),\n(ClintE)-[:ACTED_IN {roles:['Bill Munny']}]->(Unforgiven),\n(Gene)-[:ACTED_IN {roles:['Little Bill Daggett']}]->(Unforgiven),\n(ClintE)-[:DIRECTED]->(Unforgiven)\n\nCREATE (JohnnyMnemonic:Movie {title:'Johnny Mnemonic', released:1995, tagline:'The hottest data on earth. In the coolest head in town'})\nCREATE (Takeshi:Person {name:'Takeshi Kitano', born:1947})\nCREATE (Dina:Person {name:'Dina Meyer', born:1968})\nCREATE (IceT:Person {name:'Ice-T', born:1958})\nCREATE (RobertL:Person {name:'Robert Longo', born:1953})\nCREATE\n(Keanu)-[:ACTED_IN {roles:['Johnny Mnemonic']}]->(JohnnyMnemonic),\n(Takeshi)-[:ACTED_IN {roles:['Takahashi']}]->(JohnnyMnemonic),\n(Dina)-[:ACTED_IN {roles:['Jane']}]->(JohnnyMnemonic),\n(IceT)-[:ACTED_IN {roles:['J-Bone']}]->(JohnnyMnemonic),\n(RobertL)-[:DIRECTED]->(JohnnyMnemonic)\n\nCREATE (CloudAtlas:Movie {title:'Cloud Atlas', released:2012, tagline:'Everything is connected'})\nCREATE (HalleB:Person {name:'Halle Berry', born:1966})\nCREATE (JimB:Person {name:'Jim Broadbent', born:1949})\nCREATE (TomT:Person {name:'Tom Tykwer', born:1965})\nCREATE (DavidMitchell:Person {name:'David Mitchell', born:1969})\nCREATE (StefanArndt:Person {name:'Stefan Arndt', born:1961})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Zachry', 'Dr. Henry Goose', 'Isaac Sachs', 'Dermot Hoggins']}]->(CloudAtlas),\n(Hugo)-[:ACTED_IN {roles:['Bill Smoke', 'Haskell Moore', 'Tadeusz Kesselring', 'Nurse Noakes', 'Boardman Mephi', 'Old Georgie']}]->(CloudAtlas),\n(HalleB)-[:ACTED_IN {roles:['Luisa Rey', 'Jocasta Ayrs', 'Ovid', 'Meronym']}]->(CloudAtlas),\n(JimB)-[:ACTED_IN {roles:['Vyvyan Ayrs', 'Captain Molyneux', 'Timothy Cavendish']}]->(CloudAtlas),\n(TomT)-[:DIRECTED]->(CloudAtlas),\n(LillyW)-[:DIRECTED]->(CloudAtlas),\n(LanaW)-[:DIRECTED]->(CloudAtlas),\n(DavidMitchell)-[:WROTE]->(CloudAtlas),\n(StefanArndt)-[:PRODUCED]->(CloudAtlas)\n\nCREATE (TheDaVinciCode:Movie {title:'The Da Vinci Code', released:2006, tagline:'Break The Codes'})\nCREATE (IanM:Person {name:'Ian McKellen', born:1939})\nCREATE (AudreyT:Person {name:'Audrey Tautou', born:1976})\nCREATE (PaulB:Person {name:'Paul Bettany', born:1971})\nCREATE (RonH:Person {name:'Ron Howard', born:1954})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Dr. Robert Langdon']}]->(TheDaVinciCode),\n(IanM)-[:ACTED_IN {roles:['Sir Leight Teabing']}]->(TheDaVinciCode),\n(AudreyT)-[:ACTED_IN {roles:['Sophie Neveu']}]->(TheDaVinciCode),\n(PaulB)-[:ACTED_IN {roles:['Silas']}]->(TheDaVinciCode),\n(RonH)-[:DIRECTED]->(TheDaVinciCode)\n\nCREATE (VforVendetta:Movie {title:'V for Vendetta', released:2006, tagline:'Freedom! Forever!'})\nCREATE (NatalieP:Person {name:'Natalie Portman', born:1981})\nCREATE (StephenR:Person {name:'Stephen Rea', born:1946})\nCREATE (JohnH:Person {name:'John Hurt', born:1940})\nCREATE (BenM:Person {name: 'Ben Miles', born:1967})\nCREATE\n(Hugo)-[:ACTED_IN {roles:['V']}]->(VforVendetta),\n(NatalieP)-[:ACTED_IN {roles:['Evey Hammond']}]->(VforVendetta),\n(StephenR)-[:ACTED_IN {roles:['Eric Finch']}]->(VforVendetta),\n(JohnH)-[:ACTED_IN {roles:['High Chancellor Adam Sutler']}]->(VforVendetta),\n(BenM)-[:ACTED_IN {roles:['Dascomb']}]->(VforVendetta),\n(JamesM)-[:DIRECTED]->(VforVendetta),\n(LillyW)-[:PRODUCED]->(VforVendetta),\n(LanaW)-[:PRODUCED]->(VforVendetta),\n(JoelS)-[:PRODUCED]->(VforVendetta),\n(LillyW)-[:WROTE]->(VforVendetta),\n(LanaW)-[:WROTE]->(VforVendetta)\n\nCREATE (SpeedRacer:Movie {title:'Speed Racer', released:2008, tagline:'Speed has no limits'})\nCREATE (EmileH:Person {name:'Emile Hirsch', born:1985})\nCREATE (JohnG:Person {name:'John Goodman', born:1960})\nCREATE (SusanS:Person {name:'Susan Sarandon', born:1946})\nCREATE (MatthewF:Person {name:'Matthew Fox', born:1966})\nCREATE (ChristinaR:Person {name:'Christina Ricci', born:1980})\nCREATE (Rain:Person {name:'Rain', born:1982})\nCREATE\n(EmileH)-[:ACTED_IN {roles:['Speed Racer']}]->(SpeedRacer),\n(JohnG)-[:ACTED_IN {roles:['Pops']}]->(SpeedRacer),\n(SusanS)-[:ACTED_IN {roles:['Mom']}]->(SpeedRacer),\n(MatthewF)-[:ACTED_IN {roles:['Racer X']}]->(SpeedRacer),\n(ChristinaR)-[:ACTED_IN {roles:['Trixie']}]->(SpeedRacer),\n(Rain)-[:ACTED_IN {roles:['Taejo Togokahn']}]->(SpeedRacer),\n(BenM)-[:ACTED_IN {roles:['Cass Jones']}]->(SpeedRacer),\n(LillyW)-[:DIRECTED]->(SpeedRacer),\n(LanaW)-[:DIRECTED]->(SpeedRacer),\n(LillyW)-[:WROTE]->(SpeedRacer),\n(LanaW)-[:WROTE]->(SpeedRacer),\n(JoelS)-[:PRODUCED]->(SpeedRacer)\n\nCREATE (NinjaAssassin:Movie {title:'Ninja Assassin', released:2009, tagline:'Prepare to enter a secret world of assassins'})\nCREATE (NaomieH:Person {name:'Naomie Harris'})\nCREATE\n(Rain)-[:ACTED_IN {roles:['Raizo']}]->(NinjaAssassin),\n(NaomieH)-[:ACTED_IN {roles:['Mika Coretti']}]->(NinjaAssassin),\n(RickY)-[:ACTED_IN {roles:['Takeshi']}]->(NinjaAssassin),\n(BenM)-[:ACTED_IN {roles:['Ryan Maslow']}]->(NinjaAssassin),\n(JamesM)-[:DIRECTED]->(NinjaAssassin),\n(LillyW)-[:PRODUCED]->(NinjaAssassin),\n(LanaW)-[:PRODUCED]->(NinjaAssassin),\n(JoelS)-[:PRODUCED]->(NinjaAssassin)\n\nCREATE (TheGreenMile:Movie {title:'The Green Mile', released:1999, tagline:\"Walk a mile you'll never forget.\"})\nCREATE (MichaelD:Person {name:'Michael Clarke Duncan', born:1957})\nCREATE (DavidM:Person {name:'David Morse', born:1953})\nCREATE (SamR:Person {name:'Sam Rockwell', born:1968})\nCREATE (GaryS:Person {name:'Gary Sinise', born:1955})\nCREATE (PatriciaC:Person {name:'Patricia Clarkson', born:1959})\nCREATE (FrankD:Person {name:'Frank Darabont', born:1959})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Paul Edgecomb']}]->(TheGreenMile),\n(MichaelD)-[:ACTED_IN {roles:['John Coffey']}]->(TheGreenMile),\n(DavidM)-[:ACTED_IN {roles:['Brutus \"Brutal\" Howell']}]->(TheGreenMile),\n(BonnieH)-[:ACTED_IN {roles:['Jan Edgecomb']}]->(TheGreenMile),\n(JamesC)-[:ACTED_IN {roles:['Warden Hal Moores']}]->(TheGreenMile),\n(SamR)-[:ACTED_IN {roles:['\"Wild Bill\" Wharton']}]->(TheGreenMile),\n(GaryS)-[:ACTED_IN {roles:['Burt Hammersmith']}]->(TheGreenMile),\n(PatriciaC)-[:ACTED_IN {roles:['Melinda Moores']}]->(TheGreenMile),\n(FrankD)-[:DIRECTED]->(TheGreenMile)\n\nCREATE (FrostNixon:Movie {title:'Frost/Nixon', released:2008, tagline:'400 million people were waiting for the truth.'})\nCREATE (FrankL:Person {name:'Frank Langella', born:1938})\nCREATE (MichaelS:Person {name:'Michael Sheen', born:1969})\nCREATE (OliverP:Person {name:'Oliver Platt', born:1960})\nCREATE\n(FrankL)-[:ACTED_IN {roles:['Richard Nixon']}]->(FrostNixon),\n(MichaelS)-[:ACTED_IN {roles:['David Frost']}]->(FrostNixon),\n(KevinB)-[:ACTED_IN {roles:['Jack Brennan']}]->(FrostNixon),\n(OliverP)-[:ACTED_IN {roles:['Bob Zelnick']}]->(FrostNixon),\n(SamR)-[:ACTED_IN {roles:['James Reston, Jr.']}]->(FrostNixon),\n(RonH)-[:DIRECTED]->(FrostNixon)\n\nCREATE (Hoffa:Movie {title:'Hoffa', released:1992, tagline:\"He didn't want law. He wanted justice.\"})\nCREATE (DannyD:Person {name:'Danny DeVito', born:1944})\nCREATE (JohnR:Person {name:'John C. Reilly', born:1965})\nCREATE\n(JackN)-[:ACTED_IN {roles:['Hoffa']}]->(Hoffa),\n(DannyD)-[:ACTED_IN {roles:['Robert \"Bobby\" Ciaro']}]->(Hoffa),\n(JTW)-[:ACTED_IN {roles:['Frank Fitzsimmons']}]->(Hoffa),\n(JohnR)-[:ACTED_IN {roles:['Peter \"Pete\" Connelly']}]->(Hoffa),\n(DannyD)-[:DIRECTED]->(Hoffa)\n\nCREATE (Apollo13:Movie {title:'Apollo 13', released:1995, tagline:'Houston, we have a problem.'})\nCREATE (EdH:Person {name:'Ed Harris', born:1950})\nCREATE (BillPax:Person {name:'Bill Paxton', born:1955})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Jim Lovell']}]->(Apollo13),\n(KevinB)-[:ACTED_IN {roles:['Jack Swigert']}]->(Apollo13),\n(EdH)-[:ACTED_IN {roles:['Gene Kranz']}]->(Apollo13),\n(BillPax)-[:ACTED_IN {roles:['Fred Haise']}]->(Apollo13),\n(GaryS)-[:ACTED_IN {roles:['Ken Mattingly']}]->(Apollo13),\n(RonH)-[:DIRECTED]->(Apollo13)\n\nCREATE (Twister:Movie {title:'Twister', released:1996, tagline:\"Don't Breathe. Don't Look Back.\"})\nCREATE (PhilipH:Person {name:'Philip Seymour Hoffman', born:1967})\nCREATE (JanB:Person {name:'Jan de Bont', born:1943})\nCREATE\n(BillPax)-[:ACTED_IN {roles:['Bill Harding']}]->(Twister),\n(HelenH)-[:ACTED_IN {roles:['Dr. Jo Harding']}]->(Twister),\n(ZachG)-[:ACTED_IN {roles:['Eddie']}]->(Twister),\n(PhilipH)-[:ACTED_IN {roles:['Dustin \"Dusty\" Davis']}]->(Twister),\n(JanB)-[:DIRECTED]->(Twister)\n\nCREATE (CastAway:Movie {title:'Cast Away', released:2000, tagline:'At the edge of the world, his journey begins.'})\nCREATE (RobertZ:Person {name:'Robert Zemeckis', born:1951})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Chuck Noland']}]->(CastAway),\n(HelenH)-[:ACTED_IN {roles:['Kelly Frears']}]->(CastAway),\n(RobertZ)-[:DIRECTED]->(CastAway)\n\nCREATE (OneFlewOvertheCuckoosNest:Movie {title:\"One Flew Over the Cuckoo's Nest\", released:1975, tagline:\"If he's crazy, what does that make you?\"})\nCREATE (MilosF:Person {name:'Milos Forman', born:1932})\nCREATE\n(JackN)-[:ACTED_IN {roles:['Randle McMurphy']}]->(OneFlewOvertheCuckoosNest),\n(DannyD)-[:ACTED_IN {roles:['Martini']}]->(OneFlewOvertheCuckoosNest),\n(MilosF)-[:DIRECTED]->(OneFlewOvertheCuckoosNest)\n\nCREATE (SomethingsGottaGive:Movie {title:\"Something's Gotta Give\", released:2003})\nCREATE (DianeK:Person {name:'Diane Keaton', born:1946})\nCREATE (NancyM:Person {name:'Nancy Meyers', born:1949})\nCREATE\n(JackN)-[:ACTED_IN {roles:['Harry Sanborn']}]->(SomethingsGottaGive),\n(DianeK)-[:ACTED_IN {roles:['Erica Barry']}]->(SomethingsGottaGive),\n(Keanu)-[:ACTED_IN {roles:['Julian Mercer']}]->(SomethingsGottaGive),\n(NancyM)-[:DIRECTED]->(SomethingsGottaGive),\n(NancyM)-[:PRODUCED]->(SomethingsGottaGive),\n(NancyM)-[:WROTE]->(SomethingsGottaGive)\n\nCREATE (BicentennialMan:Movie {title:'Bicentennial Man', released:1999, tagline:\"One robot's 200 year journey to become an ordinary man.\"})\nCREATE (ChrisC:Person {name:'Chris Columbus', born:1958})\nCREATE\n(Robin)-[:ACTED_IN {roles:['Andrew Marin']}]->(BicentennialMan),\n(OliverP)-[:ACTED_IN {roles:['Rupert Burns']}]->(BicentennialMan),\n(ChrisC)-[:DIRECTED]->(BicentennialMan)\n\nCREATE (CharlieWilsonsWar:Movie {title:\"Charlie Wilson's War\", released:2007, tagline:\"A stiff drink. A little mascara. A lot of nerve. Who said they couldn't bring down the Soviet empire.\"})\nCREATE (JuliaR:Person {name:'Julia Roberts', born:1967})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Rep. Charlie Wilson']}]->(CharlieWilsonsWar),\n(JuliaR)-[:ACTED_IN {roles:['Joanne Herring']}]->(CharlieWilsonsWar),\n(PhilipH)-[:ACTED_IN {roles:['Gust Avrakotos']}]->(CharlieWilsonsWar),\n(MikeN)-[:DIRECTED]->(CharlieWilsonsWar)\n\nCREATE (ThePolarExpress:Movie {title:'The Polar Express', released:2004, tagline:'This Holiday Season… Believe'})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Hero Boy', 'Father', 'Conductor', 'Hobo', 'Scrooge', 'Santa Claus']}]->(ThePolarExpress),\n(RobertZ)-[:DIRECTED]->(ThePolarExpress)\n\nCREATE (ALeagueofTheirOwn:Movie {title:'A League of Their Own', released:1992, tagline:'Once in a lifetime you get a chance to do something different.'})\nCREATE (Madonna:Person {name:'Madonna', born:1954})\nCREATE (GeenaD:Person {name:'Geena Davis', born:1956})\nCREATE (LoriP:Person {name:'Lori Petty', born:1963})\nCREATE (PennyM:Person {name:'Penny Marshall', born:1943})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Jimmy Dugan']}]->(ALeagueofTheirOwn),\n(GeenaD)-[:ACTED_IN {roles:['Dottie Hinson']}]->(ALeagueofTheirOwn),\n(LoriP)-[:ACTED_IN {roles:['Kit Keller']}]->(ALeagueofTheirOwn),\n(RosieO)-[:ACTED_IN {roles:['Doris Murphy']}]->(ALeagueofTheirOwn),\n(Madonna)-[:ACTED_IN {roles:['\"All the Way\" Mae Mordabito']}]->(ALeagueofTheirOwn),\n(BillPax)-[:ACTED_IN {roles:['Bob Hinson']}]->(ALeagueofTheirOwn),\n(PennyM)-[:DIRECTED]->(ALeagueofTheirOwn)\n\nCREATE (PaulBlythe:Person {name:'Paul Blythe'})\nCREATE (AngelaScope:Person {name:'Angela Scope'})\nCREATE (JessicaThompson:Person {name:'Jessica Thompson'})\nCREATE (JamesThompson:Person {name:'James Thompson'})\n\nCREATE\n(JamesThompson)-[:FOLLOWS]->(JessicaThompson),\n(AngelaScope)-[:FOLLOWS]->(JessicaThompson),\n(PaulBlythe)-[:FOLLOWS]->(AngelaScope)\n\nCREATE\n(JessicaThompson)-[:REVIEWED {summary:'An amazing journey', rating:95}]->(CloudAtlas),\n(JessicaThompson)-[:REVIEWED {summary:'Silly, but fun', rating:65}]->(TheReplacements),\n(JamesThompson)-[:REVIEWED {summary:'The coolest football movie ever', rating:100}]->(TheReplacements),\n(AngelaScope)-[:REVIEWED {summary:'Pretty funny at times', rating:62}]->(TheReplacements),\n(JessicaThompson)-[:REVIEWED {summary:'Dark, but compelling', rating:85}]->(Unforgiven),\n(JessicaThompson)-[:REVIEWED {summary:\"Slapstick redeemed only by the Robin Williams and Gene Hackman's stellar performances\", rating:45}]->(TheBirdcage),\n(JessicaThompson)-[:REVIEWED {summary:'A solid romp', rating:68}]->(TheDaVinciCode),\n(JamesThompson)-[:REVIEWED {summary:'Fun, but a little far fetched', rating:65}]->(TheDaVinciCode),\n(JessicaThompson)-[:REVIEWED {summary:'You had me at Jerry', rating:92}]->(JerryMaguire)\n\nWITH TomH as a\nMATCH (a)-[:ACTED_IN]->(m)<-[:DIRECTED]-(d) RETURN a,m,d LIMIT 10;"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-parser/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-examples</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-examples-parser</artifactId>\n\n\t<name>Examples (Parser)</name>\n\t<description>Examples for the Cypher-DSL parser used in the documentation.</description>\n\n\t<properties>\n\t\t<java-module-name>org.neo4j.cypherdsl.examples.parser</java-module-name>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl</artifactId>\n\t\t\t<version>${revision}${sha1}${changelist}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl-parser</artifactId>\n\t\t\t<version>${revision}${sha1}${changelist}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.assertj</groupId>\n\t\t\t<artifactId>assertj-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-checkstyle-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"override\">\n\t\t\t\t\t<suppressionsLocation>../etc/checkstyle/suppressions.xml</suppressionsLocation>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-jar-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skipIfEmpty>true</skipIfEmpty>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-install-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-failsafe-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>integration-test</goal>\n\t\t\t\t\t\t\t<goal>verify</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-parser/src/test/java/org/neo4j/cypherdsl/examples/parser/ConditionExtractingMatchFactory.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.parser;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.concurrent.atomic.AtomicReference;\nimport java.util.function.Function;\n\nimport org.neo4j.cypherdsl.core.Comparison;\nimport org.neo4j.cypherdsl.core.Condition;\nimport org.neo4j.cypherdsl.core.KeyValueMapEntry;\nimport org.neo4j.cypherdsl.core.Match;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.PropertyContainer;\nimport org.neo4j.cypherdsl.core.Relationship;\nimport org.neo4j.cypherdsl.core.SymbolicName;\nimport org.neo4j.cypherdsl.core.ast.EnterResult;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.ast.VisitorWithResult;\nimport org.neo4j.cypherdsl.parser.MatchDefinition;\n\nabstract class ConditionExtractingMatchFactory implements Function<MatchDefinition, Match> {\n\n\t/**\n\t * Conditions extracted from matching properties on nodes aka {@code (n:Movie {title:\n\t * 'WHATEVER'}) }.\n\t */\n\tprotected final Map<Node, List<Condition>> nodeConditions = new LinkedHashMap<>();\n\n\t/**\n\t * Conditions extracted from matching properties on nodes aka {@code () -[r:ACTED_IN\n\t * {as: 'WHATEVER'}] ->() }.\n\t */\n\tprotected final Map<Relationship, List<Condition>> relationshipConditions = new LinkedHashMap<>();\n\n\t@Override\n\tpublic Match apply(MatchDefinition matchDefinition) {\n\n\t\tmatchDefinition.patternElements().forEach(patternElement -> {\n\t\t\tpatternElement.accept(outer -> {\n\t\t\t\tList<Condition> extractedConditions = new ArrayList<>();\n\t\t\t\tif (outer instanceof PropertyContainer container) {\n\t\t\t\t\touter.accept(inner -> {\n\t\t\t\t\t\tif (inner instanceof KeyValueMapEntry kvm) {\n\t\t\t\t\t\t\textractedConditions.add(container.property(kvm.getKey()).eq(kvm.getValue()));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (outer instanceof Node node && node.getSymbolicName().isPresent()) {\n\t\t\t\t\tthis.nodeConditions.computeIfAbsent(node, key -> new ArrayList<>()).addAll(extractedConditions);\n\t\t\t\t}\n\t\t\t\telse if (outer instanceof Relationship relationship && relationship.getSymbolicName().isPresent()) {\n\t\t\t\t\tthis.relationshipConditions.computeIfAbsent(relationship, key -> new ArrayList<>())\n\t\t\t\t\t\t.addAll(extractedConditions);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\tOptional.ofNullable(matchDefinition.optionalWhere()).ifPresent(e -> e.accept(extractPropertyComparisons()));\n\t\treturn apply0(matchDefinition);\n\t}\n\n\tabstract Match apply0(MatchDefinition matchDefinition);\n\n\tprivate Visitor extractPropertyComparisons() {\n\t\treturn segment -> {\n\t\t\tif (segment instanceof Comparison c) {\n\t\t\t\tc.accept(inner -> {\n\t\t\t\t\tif (inner instanceof Property p) {\n\t\t\t\t\t\tvar reference = new AtomicReference<SymbolicName>();\n\t\t\t\t\t\tp.accept(new VisitorWithResult() {\n\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\tpublic EnterResult enterWithResult(Visitable propertyContent) {\n\t\t\t\t\t\t\t\tif (propertyContent instanceof SymbolicName symbolicName\n\t\t\t\t\t\t\t\t\t\t&& reference.compareAndSet(null, symbolicName)) {\n\t\t\t\t\t\t\t\t\treturn EnterResult.SKIP_CHILDREN;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn EnterResult.CONTINUE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (reference.get() != null) {\n\t\t\t\t\t\t\tthis.nodeConditions.forEach((k, v) -> {\n\t\t\t\t\t\t\t\tif (k.getSymbolicName().filter(reference.get()::equals).isPresent()) {\n\t\t\t\t\t\t\t\t\tv.add(c);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-parser/src/test/java/org/neo4j/cypherdsl/examples/parser/CypherDSLParserExamplesTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.parser;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.concurrent.atomic.AtomicReference;\nimport java.util.function.Function;\nimport java.util.function.UnaryOperator;\nimport java.util.stream.Collectors;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.AliasedExpression;\nimport org.neo4j.cypherdsl.core.Clauses;\nimport org.neo4j.cypherdsl.core.Condition;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.KeyValueMapEntry;\nimport org.neo4j.cypherdsl.core.Match;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Operation;\nimport org.neo4j.cypherdsl.core.PatternElement;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.Relationship;\nimport org.neo4j.cypherdsl.core.Return;\nimport org.neo4j.cypherdsl.core.StringLiteral;\nimport org.neo4j.cypherdsl.core.SymbolicName;\nimport org.neo4j.cypherdsl.core.Where;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.GeneralizedRenderer;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\nimport org.neo4j.cypherdsl.parser.CypherParser;\nimport org.neo4j.cypherdsl.parser.ExpressionCreatedEventType;\nimport org.neo4j.cypherdsl.parser.MatchDefinition;\nimport org.neo4j.cypherdsl.parser.Options;\nimport org.neo4j.cypherdsl.parser.PatternElementCreatedEventType;\nimport org.neo4j.cypherdsl.parser.ReturnDefinition;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatExceptionOfType;\nimport static org.assertj.core.api.Assertions.assertThatNoException;\n\n/**\n * @author Michael J. Simons\n */\nclass CypherDSLParserExamplesTests {\n\n\t@Test\n\tvoid createASubqueryCallWithUserProvidedCypher() {\n\n\t\t// tag::example-using-input[]\n\t\tvar userProvidedCypher = \"MATCH (this)-[:LINK]-(o:Other) RETURN o as result\"; // <.>\n\t\tvar userStatement = CypherParser.parse(userProvidedCypher); // <.>\n\n\t\tvar node = Cypher.node(\"Node\").named(\"node\");\n\t\tvar result = Cypher.name(\"result\");\n\t\tvar cypher = Cypher // <.>\n\t\t\t.match(node)\n\t\t\t.call(// <.>\n\t\t\t\t\tuserStatement, node.as(\"this\"))\n\t\t\t.returning(result.project(\"foo\", \"bar\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\"MATCH (node:`Node`) \" + \"CALL (node) {\" + \"WITH node AS this \" // <.>\n\t\t\t\t+ \"MATCH (this)-[:`LINK`]-(o:`Other`) RETURN o AS result\" // <.>\n\t\t\t\t+ \"} \" + \"RETURN result{.foo, .bar}\");\n\t\t// end::example-using-input[]\n\t}\n\n\t@Test\n\tvoid extractLabels() {\n\n\t\tvar cypher = \"OPTIONAL MATCH (m) SET m:Foo REMOVE m:Bar WITH m CREATE (m:Person) SET n.name = 'John' RETURN n, m\";\n\n\t\tclass LabelCollector implements Function<Expression, Operation> {\n\n\t\t\tList<String> labelsSeen = new ArrayList<>();\n\n\t\t\t@Override\n\t\t\tpublic Operation apply(Expression expression) {\n\t\t\t\tOperation op = (Operation) expression;\n\t\t\t\top.accept(segment -> {\n\t\t\t\t\tif (segment instanceof NodeLabel) {\n\t\t\t\t\t\tthis.labelsSeen.add(((NodeLabel) segment).getValue());\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn op;\n\t\t\t}\n\n\t\t}\n\n\t\tvar labelsAdded = new LabelCollector();\n\t\tvar labelsRemoved = new LabelCollector();\n\n\t\tvar options = Options.newOptions()\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_SET_LABELS, Operation.class, labelsAdded)\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_REMOVE_LABELS, Operation.class, labelsRemoved)\n\n\t\t\t.build();\n\n\t\tassertThatNoException().isThrownBy(() -> CypherParser.parse(cypher, options));\n\t\tassertThat(labelsAdded.labelsSeen).containsExactly(\"Foo\");\n\t\tassertThat(labelsRemoved.labelsSeen).containsExactly(\"Bar\");\n\t}\n\n\t@Test // GH-299\n\tvoid extractLabelsWithFilters() {\n\n\t\tvar cypher = \"OPTIONAL MATCH (m:Bazbar) SET m:Foo REMOVE m:Bar WITH m CREATE (m:Person) SET n.name = 'John' RETURN n, m\";\n\t\tvar labelsSeen = new HashSet<String>();\n\t\tvar options = Options.newOptions().withLabelFilter((labelParsedEventType, strings) -> {\n\n\t\t\t// The event type could be used to distinguish the call site at which labels\n\t\t\t// where needed\n\t\t\tswitch (labelParsedEventType) {\n\t\t\t\tcase ON_REMOVE:\n\t\t\t\t\tbreak;\n\t\t\t\tcase ON_SET:\n\t\t\t\t\tbreak;\n\t\t\t\tcase ON_NODE_PATTERN:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlabelsSeen.addAll(strings);\n\t\t\treturn strings;\n\t\t}).build();\n\n\t\tassertThatNoException().isThrownBy(() -> CypherParser.parse(cypher, options));\n\t\tassertThat(labelsSeen).containsExactlyInAnyOrder(\"Bazbar\", \"Foo\", \"Bar\", \"Person\");\n\t}\n\n\t@Test // GH-299\n\tvoid extractLabelsInMatchOrCreate() {\n\n\t\tvar cypher = \"OPTIONAL MATCH (m:Bazbar) SET m:Foo REMOVE m:Bar WITH m CREATE (m:Person) SET n.name = 'John' RETURN n, m\";\n\n\t\tclass LabelCollector implements UnaryOperator<PatternElement> {\n\n\t\t\tfinal Set<String> labelsSeen = new HashSet<>();\n\n\t\t\t@Override\n\t\t\tpublic PatternElement apply(PatternElement patternElement) {\n\t\t\t\tif (patternElement instanceof Node) {\n\t\t\t\t\t((Node) patternElement).getLabels().forEach(l -> this.labelsSeen.add(l.getValue()));\n\t\t\t\t}\n\t\t\t\treturn patternElement;\n\t\t\t}\n\n\t\t}\n\n\t\tvar labelsOnNodesCreated = new LabelCollector();\n\t\tvar labelsOnNodesMatched = new LabelCollector();\n\n\t\tvar options = Options.newOptions()\n\t\t\t.withCallback(PatternElementCreatedEventType.ON_CREATE, labelsOnNodesCreated)\n\t\t\t.withCallback(PatternElementCreatedEventType.ON_MATCH, labelsOnNodesMatched)\n\t\t\t.build();\n\n\t\tassertThatNoException().isThrownBy(() -> CypherParser.parse(cypher, options));\n\t\tassertThat(labelsOnNodesCreated.labelsSeen).containsExactly(\"Person\");\n\t\tassertThat(labelsOnNodesMatched.labelsSeen).containsExactly(\"Bazbar\");\n\t}\n\n\t@Test\n\tvoid rewriteQuery() {\n\n\t\tvar cypher = \"MATCH (n:Phone)-[:CALLED]->(o:Phone) RETURN *\";\n\n\t\tclass LabelCollector implements UnaryOperator<PatternElement> {\n\n\t\t\t@Override\n\t\t\tpublic PatternElement apply(PatternElement patternElement) {\n\n\t\t\t\tif (patternElement instanceof Relationship) {\n\t\t\t\t\tRelationship relationship = (Relationship) patternElement;\n\t\t\t\t\tif (relationship.getDetails().getTypes().contains(\"CALLED\")) {\n\n\t\t\t\t\t\tvar call = Cypher.node(\"Call\").named(\"c\");\n\t\t\t\t\t\tvar left = relationship.getLeft();\n\t\t\t\t\t\tvar right = relationship.getRight();\n\t\t\t\t\t\treturn left.relationshipTo(call, \"CALL\").relationshipFrom(right, \"CALL\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn patternElement;\n\t\t\t}\n\n\t\t}\n\n\t\tvar labelsOnNodesCreated = new LabelCollector();\n\t\tvar labelsOnNodesMatched = new LabelCollector();\n\n\t\tvar options = Options.newOptions()\n\t\t\t.withCallback(PatternElementCreatedEventType.ON_CREATE, labelsOnNodesCreated)\n\t\t\t.withCallback(PatternElementCreatedEventType.ON_MATCH, labelsOnNodesMatched)\n\t\t\t.build();\n\t\tvar statement = CypherParser.parse(cypher, options);\n\t\tvar rewritten = Renderer.getRenderer(Configuration.prettyPrinting()).render(statement);\n\t\tassertThat(rewritten).isEqualTo(\"MATCH (n:Phone)-[:CALL]->(c:Call)<-[:CALL]-(o:Phone)\\n\" + \"RETURN *\");\n\t}\n\n\t@Test // GH-299\n\tvoid allLabelsSeen() {\n\n\t\tvar cypher = \"OPTIONAL MATCH (m:Bazbar) SET m:Foo REMOVE m:Bar WITH m CREATE (m:Person) SET n.name = 'John' RETURN n, m\";\n\n\t\tSet<String> labelsSeen = new HashSet<>();\n\n\t\tclass LabelsInsideExpressions implements Function<Expression, Operation> {\n\n\t\t\t@Override\n\t\t\tpublic Operation apply(Expression expression) {\n\t\t\t\tOperation op = (Operation) expression;\n\t\t\t\top.accept(segment -> {\n\t\t\t\t\tif (segment instanceof NodeLabel) {\n\t\t\t\t\t\tlabelsSeen.add(((NodeLabel) segment).getValue());\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn op;\n\t\t\t}\n\n\t\t}\n\n\t\tclass LabelsInsidePatterns implements UnaryOperator<PatternElement> {\n\n\t\t\t@Override\n\t\t\tpublic PatternElement apply(PatternElement patternElement) {\n\t\t\t\tif (patternElement instanceof Node) {\n\t\t\t\t\t((Node) patternElement).getLabels().forEach(l -> labelsSeen.add(l.getValue()));\n\t\t\t\t}\n\t\t\t\treturn patternElement;\n\t\t\t}\n\n\t\t}\n\n\t\tvar labelsInsideExpressions = new LabelsInsideExpressions();\n\t\tvar labelsInsidePatterns = new LabelsInsidePatterns();\n\n\t\tvar options = Options.newOptions()\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_SET_LABELS, Operation.class, labelsInsideExpressions)\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_REMOVE_LABELS, Operation.class, labelsInsideExpressions)\n\t\t\t.withCallback(PatternElementCreatedEventType.ON_CREATE, labelsInsidePatterns)\n\t\t\t.withCallback(PatternElementCreatedEventType.ON_MATCH, labelsInsidePatterns)\n\t\t\t.build();\n\n\t\tassertThatNoException().isThrownBy(() -> CypherParser.parse(cypher, options));\n\t\tassertThat(labelsSeen).containsExactlyInAnyOrder(\"Foo\", \"Bar\", \"Bazbar\", \"Person\");\n\t}\n\n\t@Test // GH-302\n\tvoid trackChangedPropertiesToNodes() {\n\n\t\tvar nodes = new HashMap<String, Node>();\n\t\tUnaryOperator<PatternElement> nodesCollector = patternElement -> {\n\t\t\tpatternElement.accept(segment -> {\n\t\t\t\tif (segment instanceof Node) {\n\t\t\t\t\tNode node = (Node) segment;\n\t\t\t\t\tnode.getSymbolicName().map(SymbolicName::getValue).ifPresent(n -> nodes.put(n, node));\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn patternElement;\n\t\t};\n\n\t\tclass PropertyRecord {\n\n\t\t\tString reference;\n\n\t\t\tString name;\n\n\t\t}\n\n\t\tvar removedProperties = new HashSet<PropertyRecord>();\n\t\tFunction<Expression, Expression> removedPropertiesCollector = expression -> {\n\t\t\tvar property = (Property) expression;\n\t\t\tproperty.accept(segment -> {\n\t\t\t\tif (segment instanceof SymbolicName) {\n\t\t\t\t\tvar value = ((SymbolicName) segment).getValue();\n\t\t\t\t\tif (nodes.containsKey(value)) {\n\t\t\t\t\t\tvar propertyRecord = new PropertyRecord();\n\t\t\t\t\t\tpropertyRecord.reference = ((SymbolicName) segment).getValue();\n\t\t\t\t\t\tpropertyRecord.name = property.getName();\n\t\t\t\t\t\tremovedProperties.add(propertyRecord);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn expression;\n\t\t};\n\n\t\tvar setProperties = new HashSet<PropertyRecord>();\n\t\tFunction<Expression, Operation> setPropertiesCollector = expression -> {\n\t\t\tvar op = (Operation) expression;\n\t\t\tvar property = new AtomicReference<String>();\n\t\t\tvar name = new AtomicReference<String>();\n\t\t\top.accept(segment -> {\n\t\t\t\tif (segment instanceof SymbolicName) {\n\t\t\t\t\t// First symbolic name will be the property reference\n\t\t\t\t\tvar value = ((SymbolicName) segment).getValue();\n\t\t\t\t\tif (!property.compareAndSet(null, value)) {\n\t\t\t\t\t\t// Second will be the name\n\t\t\t\t\t\tname.compareAndSet(null, value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (nodes.containsKey(property.get())) {\n\t\t\t\tvar propertyRecord = new PropertyRecord();\n\t\t\t\tpropertyRecord.reference = property.get();\n\t\t\t\tpropertyRecord.name = name.get();\n\t\t\t\tsetProperties.add(propertyRecord);\n\t\t\t}\n\t\t\treturn op;\n\t\t};\n\n\t\tvar options = Options.newOptions()\n\t\t\t.withCallback(PatternElementCreatedEventType.ON_CREATE, nodesCollector)\n\t\t\t.withCallback(PatternElementCreatedEventType.ON_MATCH, nodesCollector)\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_REMOVE_PROPERTY, Expression.class, removedPropertiesCollector)\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_SET_PROPERTY, Operation.class, setPropertiesCollector)\n\t\t\t.build();\n\n\t\tCypherParser.parse(\"MATCH (c:Person {uuid: $uuid})-[:WORKS_AT]->(p:Company) REMOVE c.name SET c.thing = 1\",\n\t\t\t\toptions);\n\t\tassertThat(removedProperties).hasSize(1).first().satisfies(p -> {\n\t\t\tassertThat(p.name).isEqualTo(\"name\");\n\t\t\tassertThat(p.reference).isEqualTo(\"c\");\n\t\t});\n\t\tassertThat(setProperties).hasSize(1).first().satisfies(p -> {\n\t\t\tassertThat(p.name).isEqualTo(\"thing\");\n\t\t\tassertThat(p.reference).isEqualTo(\"c\");\n\t\t});\n\t\tassertThat(nodes).containsKey(\"c\").hasEntrySatisfying(\"c\", n -> {\n\t\t\tvar selectingProperty = new AtomicReference<String>();\n\t\t\tVisitor propExtractor = segment -> {\n\t\t\t\tif (segment instanceof KeyValueMapEntry) {\n\t\t\t\t\tvar entry = (KeyValueMapEntry) segment;\n\t\t\t\t\tselectingProperty.compareAndSet(null, entry.getKey());\n\t\t\t\t}\n\t\t\t};\n\t\t\tn.accept(propExtractor);\n\t\t\tassertThat(selectingProperty).hasValue(\"uuid\");\n\t\t});\n\t}\n\n\t@Test\n\tvoid ensureAReturnAlias() {\n\n\t\t// tag::example-required-alias[]\n\t\tvar userProvidedCypher = \"MATCH (this)-[:LINK]-(o:Other) RETURN o\";\n\n\t\tFunction<Expression, AliasedExpression> ensureAlias = r -> {\n\t\t\tif (!(r instanceof AliasedExpression)) {\n\t\t\t\treturn r.as(\"result\");\n\t\t\t}\n\t\t\treturn (AliasedExpression) r;\n\t\t}; // <.>\n\n\t\tvar options = Options.newOptions() // <.>\n\t\t\t.withCallback( // <.>\n\t\t\t\t\tExpressionCreatedEventType.ON_RETURN_ITEM, AliasedExpression.class, ensureAlias)\n\t\t\t.build();\n\n\t\tvar userStatement = CypherParser.parse(userProvidedCypher, options); // <.>\n\t\t// end::example-required-alias[]\n\n\t\tvar node = Cypher.node(\"Node\").named(\"node\");\n\t\tvar result = Cypher.name(\"result\");\n\t\tvar cypher = Cypher.match(node)\n\t\t\t.call(userStatement, node.as(\"this\")) // <.>\n\t\t\t.returning(result.project(\"foo\", \"bar\"))\n\t\t\t.build()\n\t\t\t.getCypher();\n\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (node:`Node`) CALL (node) {WITH node AS this MATCH (this)-[:`LINK`]-(o:`Other`) RETURN o AS result} RETURN result{.foo, .bar}\");\n\t}\n\n\t@Test\n\tvoid preventPropertyDeletion() {\n\n\t\t// tag::example-preventing-things[]\n\t\tvar userProvidedCypher = \"MATCH (this)-[:LINK]-(o:Other) REMOVE this.something RETURN o\";\n\n\t\tUnaryOperator<Expression> preventPropertyDeletion = r -> {\n\t\t\tthrow new RuntimeException(\"Not allowed to remove properties!\"); // <.>\n\t\t};\n\n\t\tvar options = Options.newOptions()\n\t\t\t.withCallback( // <.>\n\t\t\t\t\tExpressionCreatedEventType.ON_REMOVE_PROPERTY, Expression.class, preventPropertyDeletion)\n\t\t\t.build();\n\n\t\tassertThatExceptionOfType(RuntimeException.class)\n\t\t\t.isThrownBy(() -> CypherParser.parse(userProvidedCypher, options)); // <.>\n\t\t// end::example-preventing-things[]\n\t}\n\n\t@Test\n\tvoid preventDeleteClause() {\n\n\t\tvar userProvidedCypher = \"MATCH (this)-[:LINK]-(o:Other) DELETE this, o\";\n\n\t\tUnaryOperator<Expression> preventDelete = r -> {\n\t\t\tthrow new RuntimeException(\"Not allowed to delete things!\");\n\t\t};\n\n\t\tvar options = Options.newOptions()\n\t\t\t.withCallback( // <.>\n\t\t\t\t\tExpressionCreatedEventType.ON_DELETE_ITEM, Expression.class, preventDelete)\n\t\t\t.build();\n\n\t\tassertThatExceptionOfType(RuntimeException.class)\n\t\t\t.isThrownBy(() -> CypherParser.parse(userProvidedCypher, options))\n\t\t\t.havingCause()\n\t\t\t.withMessage(\"Not allowed to delete things!\");\n\t}\n\n\t@Test\n\tvoid modifyReturnClause() {\n\n\t\t// tag::example-shape-the-return-clause[]\n\t\tvar userProvidedCypher = \"MATCH (this)-[:LINK]-(o:Other) RETURN distinct this, o LIMIT 23\";\n\n\t\tFunction<ReturnDefinition, Return> returnClauseFactory = d -> { // <.>\n\t\t\tvar finalExpressionsReturned = d.getExpressions()\n\t\t\t\t.stream()\n\t\t\t\t.filter(e -> e instanceof SymbolicName && \"o\".equals(((SymbolicName) e).getValue()))\n\t\t\t\t.map(e -> e.as(\"result\"))\n\t\t\t\t.collect(Collectors.<Expression>toList());\n\n\t\t\treturn Clauses.returning(false, finalExpressionsReturned,\n\t\t\t\t\tList.of(Cypher.name(\"o\").property(\"x\").descending()), d.getOptionalSkip(), d.getOptionalLimit());\n\t\t};\n\n\t\tvar options = Options.newOptions()\n\t\t\t.withReturnClauseFactory(returnClauseFactory) // <.>\n\t\t\t.build();\n\n\t\tvar userStatement = CypherParser.parse(userProvidedCypher, options);\n\t\tvar cypher = userStatement.getCypher();\n\n\t\tassertThat(cypher) // <.>\n\t\t\t.isEqualTo(\"MATCH (this)-[:`LINK`]-(o:`Other`) RETURN o AS result ORDER BY o.x DESC LIMIT 23\");\n\t\t// end::example-shape-the-return-clause[]\n\t}\n\n\t@Test // GH-574\n\tvoid collectingPropertyReferencesShouldWork() {\n\n\t\tvar query = \"MATCH (m:Movie {title: 'The Matrix'}) <-[r:ACTED_IN] - (p:Person {born: 1964}) WHERE m.releaseYear IS NOT NULL AND p.name = 'Keanu Reeves' RETURN m\";\n\t\tvar collectingPropertyReferences = new ConditionExtractingMatchFactory() {\n\t\t\t@Override\n\t\t\tMatch apply0(MatchDefinition matchDefinition) {\n\t\t\t\tvar newConditions = Cypher.noCondition();\n\t\t\t\tfor (Condition value : this.nodeConditions.values().stream().flatMap(Collection::stream).toList()) {\n\t\t\t\t\tnewConditions = newConditions.and(value);\n\t\t\t\t}\n\t\t\t\treturn (Match) Clauses.match(matchDefinition.optional(), List\n\t\t\t\t\t.of(Cypher.node(\"Movie\").named(\"m\").relationshipFrom(Cypher.node(\"Person\").named(\"p\"), \"ACTED_IN\")),\n\t\t\t\t\t\tWhere.from(newConditions), matchDefinition.optionalHints());\n\t\t\t}\n\t\t};\n\t\tvar options = Options.newOptions().withMatchClauseFactory(collectingPropertyReferences).build();\n\n\t\tvar cypher = CypherParser.parse(query, options).getCypher();\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (m:`Movie`)<-[:`ACTED_IN`]-(p:`Person`) WHERE (m.title = 'The Matrix' AND m.releaseYear IS NOT NULL AND p.born = 1964 AND p.name = 'Keanu Reeves') RETURN m\");\n\t}\n\n\t@Test // GH-739\n\tvoid rewritingStringLiterals() {\n\n\t\tvar query = \"MATCH (m:Movie {title: 'The Matrix'}) <-[r:ACTED_IN] - (p:Person {born: 1964}) WHERE m.releaseYear IS NOT NULL AND p.name = 'Keanu Reeves' RETURN m\";\n\t\tvar options = Options.newOptions()\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_NEW_LITERAL, Expression.class, l -> {\n\t\t\t\tif (l instanceof StringLiteral sl) {\n\t\t\t\t\treturn Cypher.anonParameter(sl.getContent());\n\t\t\t\t}\n\t\t\t\treturn l;\n\t\t\t})\n\t\t\t.build();\n\t\tvar stmt = CypherParser.parse(query, options);\n\t\tassertThat(stmt.getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (m:`Movie` {title: $pcdsl01})<-[r:`ACTED_IN`]-(p:`Person` {born: 1964}) WHERE (m.releaseYear IS NOT NULL AND p.name = $pcdsl02) RETURN m\");\n\t\tassertThat(stmt.getCatalog().getParameters()).containsValues(\"The Matrix\", \"Keanu Reeves\");\n\t}\n\n\t@Test // GH-1060\n\tvoid buildingWhereClauseShouldWork() {\n\n\t\tvar node = Cypher.node(\"Product\").named(\"Product\");\n\t\tvar where = Where.from(node.property(\"product_id\").eq(Cypher.literalOf(\"BG2\")));\n\t\tassertThat(where).hasToString(\"Where{cypher=WHERE Product.product_id = 'BG2'}\");\n\n\t\tvar cypher = Renderer.getRenderer(Configuration.defaultConfig(), GeneralizedRenderer.class).render(where);\n\t\tassertThat(cypher).isEqualTo(\"WHERE Product.product_id = 'BG2'\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-parser/src/test/java/org/neo4j/cypherdsl/examples/parser/StatementCatalogBuildingVisitorViaParserTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.parser;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.Literal;\nimport org.neo4j.cypherdsl.core.StatementCatalog;\nimport org.neo4j.cypherdsl.parser.CypherParser;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass StatementCatalogBuildingVisitorViaParserTests {\n\n\t@Test\n\tvoid simpleShowCase() {\n\n\t\t// tag::catalog-example[]\n\t\tvar input = \"\"\"\n\t\t\t\tMATCH (m:`Movie` {title: 'The Matrix'})<-[a:`ACTED_IN`]-(p:`Person`)\n\t\t\t\tWHERE p.born >= $born\n\t\t\t\tRETURN p\n\t\t\t\t\"\"\";\n\t\tvar statement = CypherParser.parse(input);\n\n\t\tvar catalog = statement.getCatalog();\n\n\t\tassertThat(catalog.getNodeLabels()).extracting(StatementCatalog.Token::value)\n\t\t\t.containsExactlyInAnyOrder(\"Person\", \"Movie\");\n\t\tassertThat(catalog.getProperties()).containsExactlyInAnyOrder(\n\t\t\t\tStatementCatalog.property(Set.of(StatementCatalog.label(\"Movie\")), \"title\"),\n\t\t\t\tStatementCatalog.property(Set.of(StatementCatalog.label(\"Person\")), \"born\"));\n\t\t// end::catalog-example[]\n\n\t\tvar cypher = statement.getCypher();\n\t\tassertThat(cypher).isEqualTo(\n\t\t\t\t\"MATCH (m:`Movie` {title: 'The Matrix'})<-[a:`ACTED_IN`]-(p:`Person`) WHERE p.born >= $born RETURN p\");\n\t}\n\n\t@Test\n\tvoid mapOfLabelsAndProperties() {\n\t\tvar input = \"\"\"\n\t\t\t\tMATCH (m:`Movie` {title: 'The Matrix'})<-[a:`ACTED_IN`]-(p:`Person`|Actor {b:true})\n\t\t\t\tWHERE p.born >= $born\n\t\t\t\t  AND a.starring = true\n\t\t\t\tRETURN p\n\t\t\t\t\"\"\";\n\t\tvar statement = CypherParser.parse(input);\n\n\t\tvar catalog = statement.getCatalog();\n\n\t\tassertThat(catalog.getProperties()).anyMatch(\n\t\t\t\tp -> p.owningToken().equals(Set.of(StatementCatalog.label(\"Person\"), StatementCatalog.label(\"Actor\"))));\n\t\tMap<String, List<String>> labelsAndProperties = catalog.getProperties()\n\t\t\t.stream()\n\t\t\t.filter(p -> p.owningToken().stream().allMatch(t -> t.type() == StatementCatalog.Token.Type.NODE_LABEL))\n\t\t\t.collect(Collectors.toMap(\n\t\t\t\t\tp -> p.owningToken().stream().map(StatementCatalog.Token::value).collect(Collectors.joining(\",\")),\n\t\t\t\t\tp -> List.of(p.name()), (l1, l2) -> {\n\t\t\t\t\t\tvar mergedList = new ArrayList<>(l1);\n\t\t\t\t\t\tmergedList.addAll(l2);\n\t\t\t\t\t\tCollections.sort(mergedList);\n\t\t\t\t\t\treturn mergedList;\n\t\t\t\t\t}));\n\n\t\tassertThat(labelsAndProperties).containsExactly(Map.entry(\"Movie\", List.of(\"title\")),\n\t\t\t\tMap.entry(\"Actor,Person\", List.of(\"b\", \"born\")));\n\t}\n\n\t@Test // GH-674\n\tvoid retrievalOfRelationshipsAndTargetSourcesShouldWork() {\n\t\tvar input = \"\"\"\n\t\t\t\tMATCH (m:`Movie` {title: 'The Matrix'})<-[a:`ACTED_IN`]-(p:`Person`|Actor {b:true})\n\t\t\t\tMATCH () -[:WHATEVER]-> (m)\n\t\t\t\tMATCH (x:X) -[:UNDIRECTED]- (y:Y)\n\t\t\t\tMATCH (m) -[:UNDIRECTED]- (y)\n\t\t\t\tWHERE p.born >= $born\n\t\t\t\t  AND a.starring = true\n\t\t\t\tWITH m\n\t\t\t\tMATCH (m) -[:FOO]->(f:FooNode)\n\t\t\t\tCALL {\n\t\t\t\t\tMATCH (:LabelA) -[:A_REL]-> (n:X)\n\t\t\t\t}\n\t\t\t\tRETURN p\n\t\t\t\t\"\"\";\n\t\tvar statement = CypherParser.parse(input);\n\n\t\tvar catalog = statement.getCatalog();\n\n\t\tassertThat(catalog.getOutgoingRelations(StatementCatalog.label(\"Person\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.type(\"ACTED_IN\"));\n\t\tassertThat(catalog.getOutgoingRelations(StatementCatalog.label(\"Movie\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.type(\"FOO\"));\n\t\tassertThat(catalog.getOutgoingRelations(StatementCatalog.label(\"Actor\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.type(\"ACTED_IN\"));\n\t\tassertThat(catalog.getOutgoingRelations(StatementCatalog.label(\"LabelA\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.type(\"A_REL\"));\n\n\t\tassertThat(catalog.getIncomingRelations(StatementCatalog.label(\"Movie\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.type(\"ACTED_IN\"), StatementCatalog.type(\"WHATEVER\"));\n\t\tassertThat(catalog.getIncomingRelations(StatementCatalog.label(\"FooNode\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.type(\"FOO\"));\n\t\tassertThat(catalog.getIncomingRelations(StatementCatalog.label(\"X\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.type(\"A_REL\"));\n\n\t\tassertThat(catalog.getUndirectedRelations(StatementCatalog.label(\"X\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.type(\"UNDIRECTED\"));\n\n\t\tassertThat(catalog.getTargetNodes(StatementCatalog.type(\"ACTED_IN\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.label(\"Movie\"));\n\t\tassertThat(catalog.getTargetNodes(StatementCatalog.type(\"FOO\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.label(\"FooNode\"));\n\t\tassertThat(catalog.getTargetNodes(StatementCatalog.type(\"A_REL\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.label(\"X\"));\n\t\tassertThat(catalog.getTargetNodes(StatementCatalog.type(\"WHATEVER\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.label(\"Movie\"));\n\t\tassertThat(catalog.getTargetNodes(StatementCatalog.type(\"UNDIRECTED\"))).isEmpty();\n\n\t\tassertThat(catalog.getSourceNodes(StatementCatalog.type(\"ACTED_IN\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.label(\"Person\"), StatementCatalog.label(\"Actor\"));\n\t\tassertThat(catalog.getSourceNodes(StatementCatalog.type(\"FOO\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.label(\"Movie\"));\n\t\tassertThat(catalog.getSourceNodes(StatementCatalog.type(\"A_REL\")))\n\t\t\t.containsExactlyInAnyOrder(StatementCatalog.label(\"LabelA\"));\n\t\tassertThat(catalog.getSourceNodes(StatementCatalog.type(\"WHATEVER\"))).isEmpty();\n\t\tassertThat(catalog.getSourceNodes(StatementCatalog.type(\"UNDIRECTED\"))).isEmpty();\n\t}\n\n\t@Test // GH-738\n\tvoid literalsOnParsedStatement() {\n\n\t\tvar stmt = CypherParser.parse(\n\t\t\t\t\"LOAD CSV FROM 'https://test.com/test.csv' AS x WITH x MERGE (n {x: x}) ON CREATE SET x.y = NULL, x.a = 'Hallo' ON CREATE SET x.b = [true][1..2] RETURN x\");\n\t\tassertThat(stmt.getCatalog().getLiterals()).map(Literal::asString)\n\t\t\t.containsExactlyInAnyOrder(\"1\", \"2\", \"NULL\", \"true\", \"'Hallo'\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>4.0.6</version>\n\t\t<relativePath></relativePath>\n\t\t<!-- lookup parent from repository -->\n\t</parent>\n\n\t<groupId>org.neo4j</groupId>\n\t<artifactId>neo4j-cypher-dsl-examples-sdn6</artifactId>\n\t<version>${revision}${sha1}${changelist}</version>\n\n\t<name>Examples (SDN 6 Code generator)</name>\n\t<description>Example how to use the SDN 6 code generator.</description>\n\n\t<properties>\n\t\t<checkstyle.version>13.4.2</checkstyle.version>\n\t\t<java-module-name>org.neo4j.cypherdsl.examples.sdn6</java-module-name>\n\t\t<java.version>17</java.version>\n\t\t<license-maven-plugin.version>5.0.0</license-maven-plugin.version>\n\t\t<maven-checkstyle-plugin.version>3.6.0</maven-checkstyle-plugin.version>\n\t\t<sortpom-maven-plugin.version>4.0.0</sortpom-maven-plugin.version>\n\t\t<spring-javaformat.version>0.0.47</spring-javaformat.version>\n\t</properties>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-dsl-bom</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl</artifactId>\n\t\t</dependency>\n\n\t\t<!-- Only needed when using the parser feature -->\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl-parser</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-resttestclient</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-data-neo4j</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-test</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-testcontainers</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.testcontainers</groupId>\n\t\t\t<artifactId>testcontainers-junit-jupiter</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.testcontainers</groupId>\n\t\t\t<artifactId>testcontainers-neo4j</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t</dependencies>\n\n\t<!-- tag::sdn-processor[] -->\n\t<build>\n\t\t<plugins>\n\t\t\t<!-- end::sdn-processor[] -->\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t\t<!-- tag::sdn-processor[] -->\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<version>${maven-compiler-plugin.version}</version>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<annotationProcessorPaths>\n\t\t\t\t\t\t<annotationProcessorPath>\n\t\t\t\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t\t\t\t<artifactId>neo4j-cypher-dsl-codegen-sdn6</artifactId>\n\t\t\t\t\t\t\t<version>${project.version}</version>\n\t\t\t\t\t\t</annotationProcessorPath>\n\t\t\t\t\t</annotationProcessorPaths>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<!-- end::sdn-processor[] -->\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.mycila</groupId>\n\t\t\t\t<artifactId>license-maven-plugin</artifactId>\n\t\t\t\t<version>${license-maven-plugin.version}</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<strictCheck>true</strictCheck>\n\t\t\t\t\t<mapping>\n\t\t\t\t\t\t<factories>SCRIPT_STYLE</factories>\n\t\t\t\t\t</mapping>\n\t\t\t\t\t<properties>\n\t\t\t\t\t\t<year>2026</year>\n\t\t\t\t\t</properties>\n\t\t\t\t\t<licenseSets>\n\t\t\t\t\t\t<licenseSet>\n\t\t\t\t\t\t\t<header>etc/license.tpl</header>\n\t\t\t\t\t\t\t<includes>\n\t\t\t\t\t\t\t\t<include>**</include>\n\t\t\t\t\t\t\t</includes>\n\t\t\t\t\t\t\t<excludes>\n\t\t\t\t\t\t\t\t<exclude>**/.flattened-pom.xml</exclude>\n\t\t\t\t\t\t\t\t<exclude>**/*.cypher</exclude>\n\t\t\t\t\t\t\t</excludes>\n\t\t\t\t\t\t</licenseSet>\n\t\t\t\t\t</licenseSets>\n\t\t\t\t\t<dependencyEnforce>true</dependencyEnforce>\n\t\t\t\t\t<dependencyExceptionMessage>One or more dependencies are licensed under a non-approved license.</dependencyExceptionMessage>\n\t\t\t\t\t<dependencyPolicies>\n\t\t\t\t\t\t<!-- Apache 2 -->\n\t\t\t\t\t\t<dependencyPolicy>\n\t\t\t\t\t\t\t<type>LICENSE_URL</type>\n\t\t\t\t\t\t\t<rule>APPROVE</rule>\n\t\t\t\t\t\t\t<value>https://www.apache.org/licenses/LICENSE-2.0</value>\n\t\t\t\t\t\t</dependencyPolicy>\n\t\t\t\t\t\t<dependencyPolicy>\n\t\t\t\t\t\t\t<type>LICENSE_NAME</type>\n\t\t\t\t\t\t\t<rule>APPROVE</rule>\n\t\t\t\t\t\t\t<value>The Apache Software License, Version 2.0</value>\n\t\t\t\t\t\t</dependencyPolicy>\n\t\t\t\t\t\t<!-- This is ourselves.  -->\n\t\t\t\t\t\t<dependencyPolicy>\n\t\t\t\t\t\t\t<type>ARTIFACT_PATTERN</type>\n\t\t\t\t\t\t\t<rule>APPROVE</rule>\n\t\t\t\t\t\t\t<value>org.neo4j:neo4j-cypher-dsl-parser*</value>\n\t\t\t\t\t\t</dependencyPolicy>\n\t\t\t\t\t</dependencyPolicies>\n\t\t\t\t</configuration>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>validate</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>check</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.github.ekryd.sortpom</groupId>\n\t\t\t\t<artifactId>sortpom-maven-plugin</artifactId>\n\t\t\t\t<version>${sortpom-maven-plugin.version}</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<encoding>${project.build.sourceEncoding}</encoding>\n\t\t\t\t\t<keepBlankLines>true</keepBlankLines>\n\t\t\t\t\t<nrOfIndentSpace>-1</nrOfIndentSpace>\n\t\t\t\t\t<sortProperties>true</sortProperties>\n\t\t\t\t\t<sortDependencies>groupId,artifactId</sortDependencies>\n\t\t\t\t\t<createBackupFile>false</createBackupFile>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<!-- tag::sdn-processor[] -->\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-failsafe-plugin</artifactId>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-jar-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skipIfEmpty>true</skipIfEmpty>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-install-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\t<!-- end::sdn-processor[] -->\n\n\t<!-- This is not relevant to the example, only for our project structure and build chain. -->\n\t<profiles>\n\t\t<profile>\n\t\t\t<id>with_checkstyle</id>\n\t\t\t<activation>\n\t\t\t\t<jdk>[21,)</jdk>\n\t\t\t</activation>\n\t\t\t<build>\n\t\t\t\t<plugins>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<groupId>io.spring.javaformat</groupId>\n\t\t\t\t\t\t<artifactId>spring-javaformat-maven-plugin</artifactId>\n\t\t\t\t\t\t<version>${spring-javaformat.version}</version>\n\t\t\t\t\t\t<executions>\n\t\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t\t<goal>validate</goal>\n\t\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t\t\t<inherited>true</inherited>\n\t\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t</executions>\n\t\t\t\t\t</plugin>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t\t<artifactId>maven-checkstyle-plugin</artifactId>\n\t\t\t\t\t\t<version>${maven-checkstyle-plugin.version}</version>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<excludes>**/module-info.java</excludes>\n\t\t\t\t\t\t\t<includeTestSourceDirectory>true</includeTestSourceDirectory>\n\t\t\t\t\t\t\t<configLocation>../../etc/checkstyle/config.xml</configLocation>\n\t\t\t\t\t\t\t<suppressionsLocation>../../etc/checkstyle/suppressions.xml</suppressionsLocation>\n\t\t\t\t\t\t\t<inputEncoding>${project.build.sourceEncoding}</inputEncoding>\n\t\t\t\t\t\t\t<consoleOutput>true</consoleOutput>\n\t\t\t\t\t\t\t<failsOnError>true</failsOnError>\n\t\t\t\t\t\t\t<includeTestSourceDirectory>true</includeTestSourceDirectory>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t\t<dependencies>\n\t\t\t\t\t\t\t<dependency>\n\t\t\t\t\t\t\t\t<groupId>com.puppycrawl.tools</groupId>\n\t\t\t\t\t\t\t\t<artifactId>checkstyle</artifactId>\n\t\t\t\t\t\t\t\t<version>${checkstyle.version}</version>\n\t\t\t\t\t\t\t</dependency>\n\t\t\t\t\t\t\t<dependency>\n\t\t\t\t\t\t\t\t<groupId>io.spring.javaformat</groupId>\n\t\t\t\t\t\t\t\t<artifactId>spring-javaformat-checkstyle</artifactId>\n\t\t\t\t\t\t\t\t<version>${spring-javaformat.version}</version>\n\t\t\t\t\t\t\t</dependency>\n\t\t\t\t\t\t</dependencies>\n\t\t\t\t\t\t<executions>\n\t\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t\t<id>validate</id>\n\t\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t\t<goal>check</goal>\n\t\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t</executions>\n\t\t\t\t\t</plugin>\n\t\t\t\t</plugins>\n\t\t\t</build>\n\t\t</profile>\n\n\t\t<profile>\n\t\t\t<id>revisionMissing</id>\n\t\t\t<activation>\n\t\t\t\t<property>\n\t\t\t\t\t<name>!revision</name>\n\t\t\t\t</property>\n\t\t\t</activation>\n\t\t\t<properties>\n\t\t\t\t<revision>9999</revision>\n\t\t\t</properties>\n\t\t</profile>\n\t\t<profile>\n\t\t\t<id>sha1Missing</id>\n\t\t\t<activation>\n\t\t\t\t<property>\n\t\t\t\t\t<name>!sha</name>\n\t\t\t\t</property>\n\t\t\t</activation>\n\t\t\t<properties>\n\t\t\t\t<sha1></sha1>\n\t\t\t</properties>\n\t\t</profile>\n\t\t<profile>\n\t\t\t<id>changelistMissing</id>\n\t\t\t<activation>\n\t\t\t\t<property>\n\t\t\t\t\t<name>!changelist</name>\n\t\t\t\t</property>\n\t\t\t</activation>\n\t\t\t<properties>\n\t\t\t\t<changelist>-SNAPSHOT</changelist>\n\t\t\t</properties>\n\t\t</profile>\n\t\t<profile>\n\t\t\t<id>fast</id>\n\t\t\t<activation>\n\t\t\t\t<property>\n\t\t\t\t\t<name>fast</name>\n\t\t\t\t</property>\n\t\t\t</activation>\n\t\t\t<properties>\n\t\t\t\t<asciidoctor.skip>true</asciidoctor.skip>\n\t\t\t\t<checkstyle.skip>true</checkstyle.skip>\n\t\t\t\t<jacoco.skip>true</jacoco.skip>\n\t\t\t\t<maven.javadoc.skip>true</maven.javadoc.skip>\n\t\t\t\t<skipITs>true</skipITs>\n\t\t\t\t<skipNativeBuild>true</skipNativeBuild>\n\t\t\t\t<skipTests>true</skipTests>\n\t\t\t</properties>\n\t\t</profile>\n\t</profiles>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/Application.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * Main entry for a Spring application.\n *\n * @author Michael J. Simons\n */\n@SpringBootApplication\npublic class Application {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(Application.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/books/Book.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.books;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@Node\npublic class Book {\n\n\t@Id\n\t@GeneratedValue\n\tString id;\n\n\tprivate String lang;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/books/BookGenre.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.books;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@Node\npublic class BookGenre {\n\n\t@Id\n\t@GeneratedValue\n\tString id;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/books/UserDetails.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.books;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@Node\npublic class UserDetails {\n\n\t@Id\n\t@GeneratedValue\n\tString id;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/books/UserPreferences.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.books;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@Node\npublic class UserPreferences {\n\n\t@Id\n\t@GeneratedValue\n\tString id;\n\n\tString userId;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/books/UserSuggestionActivity.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.books;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@Node\npublic class UserSuggestionActivity {\n\n\t@Id\n\t@GeneratedValue\n\tString id;\n\n\tString userId;\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/books/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * This package exists only to reproduce an issue, it is not a complete example.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.books;\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/misc/Example.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.misc;\n\nimport org.springframework.data.annotation.PersistenceCreator;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Relationship;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@Node\npublic class Example {\n\n\t@Id\n\tprivate final long id;\n\n\t@Relationship(type = \"BELONGS_TO\")\n\tprivate Example parent;\n\n\t@PersistenceCreator\n\tpublic Example(long id) {\n\t\tthis.id = id;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/misc/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * More SDN examples.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.misc;\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/Actor.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n\nimport java.util.Collections;\nimport java.util.List;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.fasterxml.jackson.annotation.JsonProperty;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.RelationshipProperties;\nimport org.springframework.data.neo4j.core.schema.TargetNode;\n\n/**\n * Demo class.\n *\n * @author Michael J. Simons\n */\n@RelationshipProperties\npublic final class Actor {\n\n\t@TargetNode\n\t@JsonIgnore\n\tprivate final Person person;\n\n\tprivate final List<String> roles;\n\n\t@Id\n\t@GeneratedValue\n\tLong id;\n\n\tpublic Actor(Person person, List<String> roles) {\n\t\tthis.person = person;\n\t\tthis.roles = roles;\n\t}\n\n\tpublic Person getPerson() {\n\t\treturn this.person;\n\t}\n\n\t@JsonProperty\n\tpublic String getName() {\n\t\treturn this.person.getName();\n\t}\n\n\tpublic List<String> getRoles() {\n\t\treturn Collections.unmodifiableList(this.roles);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/Genre.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n\nimport java.util.UUID;\n\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@Node\npublic final class Genre {\n\n\t@Id\n\t@GeneratedValue\n\tprivate final UUID id;\n\n\tprivate final String name;\n\n\tpublic Genre(UUID id, String name) {\n\t\tthis.id = id;\n\t\tthis.name = name;\n\t}\n\n\tpublic UUID getId() {\n\t\treturn this.id;\n\t}\n\n\tpublic String getName() {\n\t\treturn this.name;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/GenreRepository.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n\nimport java.util.UUID;\n\nimport org.springframework.data.neo4j.repository.Neo4jRepository;\nimport org.springframework.data.neo4j.repository.support.CypherdslStatementExecutor;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\npublic interface GenreRepository extends Neo4jRepository<Genre, UUID>, CypherdslStatementExecutor<Genre> {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/Movie.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\n\nimport com.fasterxml.jackson.annotation.JsonCreator;\nimport com.fasterxml.jackson.annotation.JsonProperty;\n\nimport org.springframework.data.annotation.PersistenceCreator;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\nimport org.springframework.data.neo4j.core.schema.Property;\nimport org.springframework.data.neo4j.core.schema.Relationship;\nimport org.springframework.data.neo4j.core.schema.Relationship.Direction;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\n@Node\npublic final class Movie {\n\n\t@Id\n\tprivate final String title;\n\n\t@Property(\"tagline\")\n\tprivate final String description;\n\n\t@Relationship(value = \"ACTED_IN\", direction = Direction.INCOMING)\n\tprivate final List<Actor> actors;\n\n\t@Relationship(value = \"DIRECTED\", direction = Direction.INCOMING)\n\tprivate final List<Person> directors;\n\n\tprivate Integer released;\n\n\tpublic Movie(String title, String description) {\n\t\tthis.title = title;\n\t\tthis.description = description;\n\t\tthis.actors = new ArrayList<>();\n\t\tthis.directors = new ArrayList<>();\n\t}\n\n\t@JsonCreator\n\t@PersistenceCreator\n\tpublic Movie(@JsonProperty(\"title\") String title, @JsonProperty(\"description\") String description,\n\t\t\t@JsonProperty(\"actors\") List<Actor> actors, @JsonProperty(\"directors\") List<Person> directors) {\n\t\tthis.title = title;\n\t\tthis.description = description;\n\t\tthis.actors = (actors != null) ? new ArrayList<>(actors) : List.of();\n\t\tthis.directors = (directors != null) ? new ArrayList<>(directors) : List.of();\n\t}\n\n\tpublic String getTitle() {\n\t\treturn this.title;\n\t}\n\n\tpublic String getDescription() {\n\t\treturn this.description;\n\t}\n\n\tpublic List<Actor> getActors() {\n\t\treturn Collections.unmodifiableList(this.actors);\n\t}\n\n\tpublic List<Person> getDirectors() {\n\t\treturn Collections.unmodifiableList(this.directors);\n\t}\n\n\tpublic Integer getReleased() {\n\t\treturn this.released;\n\t}\n\n\tpublic void setReleased(Integer released) {\n\t\tthis.released = released;\n\t}\n\n\tpublic Movie addActors(Collection<Actor> newActors) {\n\t\tthis.actors.addAll(newActors);\n\t\treturn this;\n\t}\n\n\tpublic Movie addDirectors(Collection<Person> newDirectors) {\n\t\tthis.directors.addAll(newDirectors);\n\t\treturn this;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/MovieRepository.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n\nimport org.springframework.data.neo4j.repository.Neo4jRepository;\nimport org.springframework.data.neo4j.repository.support.CypherdslStatementExecutor;\n\n/**\n * Example type.\n *\n * @author Michael J. Simons\n */\ninterface MovieRepository extends Neo4jRepository<Movie, String>, CypherdslStatementExecutor<Movie> {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/MovieService.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n\n// tag::as-property[]\n\nimport java.util.Collection;\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.Cypher;\n\nimport org.springframework.data.domain.Sort;\nimport org.springframework.stereotype.Service;\n\n// end::as-property[]\n\n/**\n * Example service.\n *\n * @author Michael J. Simons\n */\n// tag::as-property[]\n@Service\nfinal class MovieService {\n\n\tprivate final MovieRepository movieRepository;\n\n\tMovieService(MovieRepository movieRepository) {\n\t\tthis.movieRepository = movieRepository;\n\t}\n\n\tList<Movie> findAll() {\n\n\t\treturn this.movieRepository.findAll(Sort.by(Movie_.MOVIE.TITLE.getName()).ascending()); // <.>\n\t}\n\t// end::as-property[]\n\n\t// tag::more-examples[]\n\tCollection<Movie> findAllRelatedTo(Person person) {\n\n\t\tvar p = Person_.PERSON.named(\"p\");\n\t\tvar a = Movie_.MOVIE.named(\"a\");\n\t\tvar d = Movie_.MOVIE.named(\"d\");\n\t\tvar m = Cypher.name(\"m\");\n\n\t\tvar statement = Cypher.match(p)\n\t\t\t.where(p.NAME.isEqualTo(Cypher.anonParameter(person.getName()))) // <.>\n\t\t\t.with(p)\n\t\t\t.optionalMatch(new ActedIn_(p, a))\n\t\t\t.optionalMatch(new Directed_(p, d))\n\t\t\t.with(Cypher.collect(a).add(Cypher.collect(d)).as(\"movies\"))\n\t\t\t.unwind(\"movies\")\n\t\t\t.as(m)\n\t\t\t.returningDistinct(m)\n\t\t\t.orderBy(Movie_.MOVIE.named(m).TITLE)\n\t\t\t.ascending()\n\t\t\t.build();\n\n\t\treturn this.movieRepository.findAll(statement);\n\t}\n\t// end::more-examples[]\n\t// tag::as-property[]\n\n}\n// end::as-property[]\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/MoviesController.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport org.springframework.data.domain.Example;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Example controller.\n *\n * @author Michael J. Simons\n */\n@RestController\n@RequestMapping(\"/api/movies\")\npublic final class MoviesController {\n\n\tprivate final PeopleService peopleService;\n\n\tprivate final MovieService movieService;\n\n\tpublic MoviesController(PeopleService peopleService, MovieService movieService) {\n\t\tthis.peopleService = peopleService;\n\t\tthis.movieService = movieService;\n\t}\n\n\t@GetMapping({ \"\", \"/\" })\n\tpublic List<Movie> get() {\n\t\treturn this.movieService.findAll();\n\t}\n\n\t@GetMapping({ \"/relatedTo/{name}\" })\n\tpublic List<Movie> relatedTo(@PathVariable String name) {\n\n\t\treturn this.peopleService.findOne(Example.of(new Person(name, null)))\n\t\t\t.stream()\n\t\t\t.flatMap(p -> this.movieService.findAllRelatedTo(p).stream())\n\t\t\t.collect(Collectors.toList());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/NewPersonCmd.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n\nimport java.time.ZonedDateTime;\n\n/**\n * DTO for creating new people.\n *\n * @author Michael J. Simons\n */\npublic final class NewPersonCmd {\n\n\tprivate final String name;\n\n\tprivate final ZonedDateTime dob;\n\n\tpublic NewPersonCmd(String name, ZonedDateTime dob) {\n\t\tthis.name = name;\n\t\tthis.dob = dob;\n\t}\n\n\tpublic String getName() {\n\t\treturn this.name;\n\t}\n\n\tpublic ZonedDateTime getDob() {\n\t\treturn this.dob;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/PeopleController.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n\nimport java.util.Optional;\n\nimport org.springframework.http.HttpStatus;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.server.ResponseStatusException;\n\n/**\n * Example controller.\n *\n * @author Michael J. Simons\n */\n@RestController\n@RequestMapping(\"/api/people\")\npublic class PeopleController {\n\n\tprivate final PeopleService peopleService;\n\n\tpublic PeopleController(PeopleService peopleService) {\n\t\tthis.peopleService = peopleService;\n\t}\n\n\t@GetMapping(\"/details/{name}\")\n\tpublic PersonDetails getDetails(@PathVariable String name) {\n\n\t\treturn this.peopleService.findDetails(name)\n\t\t\t.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));\n\t}\n\n\t@GetMapping(\"/findPeopleBornInThe70tiesOr\")\n\tpublic Iterable<Person> findPeopleBornInThe70tiesOr(@RequestParam(name = \"name\") Optional<String> optionalName) {\n\n\t\treturn this.peopleService.findPeopleBornInThe70tiesOr(optionalName);\n\t}\n\n\t@GetMapping(\"/v1/findPeopleBornAfterThe70ties\")\n\tpublic Iterable<Person> findPeopleBornAfterThe70ties(\n\t\t\t@RequestParam(name = \"conditions\") String additionalConditions) {\n\n\t\treturn this.peopleService.findPeopleBornAfterThe70tiesAnd(additionalConditions);\n\t}\n\n\t@GetMapping(\"/v2/findPeopleBornAfterThe70ties\")\n\tpublic Iterable<Person> findPeopleBornAfterThe70tiesV2(\n\t\t\t@RequestParam(name = \"conditions\") String additionalConditions) {\n\n\t\treturn this.peopleService.findPeopleBornAfterThe70tiesAndV2(additionalConditions);\n\t}\n\n\t@PostMapping(\"/createNewPerson\")\n\tpublic Person createNewPerson(@RequestBody NewPersonCmd newPersonCmd) {\n\n\t\treturn this.peopleService.createNewPerson(newPersonCmd)\n\t\t\t.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/PeopleRepository.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n\n// tag::additional-fragments[]\nimport org.springframework.data.neo4j.repository.Neo4jRepository;\nimport org.springframework.data.neo4j.repository.support.CypherdslConditionExecutor;\nimport org.springframework.data.neo4j.repository.support.CypherdslStatementExecutor;\n\n// end::additional-fragments[]\n\n/**\n * Example repository.\n *\n * @author Michael J. Simons\n */\n// tag::additional-fragments[]\npublic interface PeopleRepository extends Neo4jRepository<Person, Long>, CypherdslConditionExecutor<Person>, // <.>\n\t\tCypherdslStatementExecutor<Person> {\n\n\t// <.>\n\n}\n// end::additional-fragments[]\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/PeopleService.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n\n// tag::using-person-repo[]\n\nimport java.util.Optional;\nimport java.util.function.Function;\n\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.SymbolicName;\nimport org.neo4j.cypherdsl.parser.CypherParser;\nimport org.neo4j.cypherdsl.parser.ExpressionCreatedEventType;\nimport org.neo4j.cypherdsl.parser.Options;\n\nimport org.springframework.data.domain.Example;\nimport org.springframework.data.neo4j.core.mapping.Constants;\nimport org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;\nimport org.springframework.stereotype.Service;\n\n// end::using-person-repo[]\n\n/**\n * Example service.\n *\n * @author Michael J. Simons\n */\n// tag::using-person-repo[]\n@Service\nfinal class PeopleService {\n\n\tprivate final Person_ person;\n\n\tprivate final SymbolicName personRootName;\n\n\tprivate final PeopleRepository peopleRepository;\n\n\tPeopleService(PeopleRepository peopleRepository, Neo4jMappingContext mappingContext) {\n\t\tthis.peopleRepository = peopleRepository;\n\t\tthis.personRootName = Constants.NAME_OF_TYPED_ROOT_NODE\n\t\t\t.apply(mappingContext.getRequiredPersistentEntity(Person.class));\n\t\tthis.person = Person_.PERSON.named(this.personRootName);\n\t}\n\n\t// end::using-person-repo[]\n\tOptional<Person> findOne(Example<Person> example) {\n\t\treturn this.peopleRepository.findOne(example);\n\t}\n\n\t// tag::using-parser-with-spring[]\n\tIterable<Person> findPeopleBornAfterThe70tiesAnd(String additionalConditions) {\n\n\t\treturn this.peopleRepository.findAll(this.person.BORN.gte(Cypher.literalOf(1980))\n\t\t\t.and(CypherParser.parseExpression(additionalConditions).asCondition()) // <.>\n\t\t);\n\t}\n\t// end::using-parser-with-spring[]\n\n\t// tag::using-parser-with-spring2[]\n\tIterable<Person> findPeopleBornAfterThe70tiesAndV2(String additionalConditions) {\n\n\t\tFunction<Expression, Expression> enforceReference = e -> this.personRootName\n\t\t\t.property(((SymbolicName) e).getValue()); // <.>\n\t\tvar parserOptions = Options.newOptions()\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_NEW_VARIABLE, Expression.class, enforceReference) // <.>\n\t\t\t.build();\n\n\t\treturn this.peopleRepository.findAll(this.person.BORN.gte(Cypher.literalOf(1980))\n\t\t\t.and(CypherParser.parseExpression(additionalConditions, parserOptions // <.>\n\t\t\t).asCondition()));\n\t}\n\t// end::using-parser-with-spring2[]\n\n\t// tag::using-person-repo[]\n\tIterable<Person> findPeopleBornInThe70tiesOr(Optional<String> optionalName) {\n\n\t\treturn this.peopleRepository.findAll(this.person.BORN.gte(Cypher.literalOf(1970))\n\t\t\t.and(this.person.BORN.lt(Cypher.literalOf(1980))) // <.>\n\t\t\t.or(optionalName.map(name -> this.person.NAME.isEqualTo(Cypher.anonParameter(name))) // <.>\n\t\t\t\t.orElseGet(Cypher::noCondition)) // <.>\n\t\t);\n\t}\n\n\tOptional<PersonDetails> findDetails(String name) {\n\n\t\tvar d = Movie_.MOVIE.named(\"d\");\n\t\tvar a = Movie_.MOVIE.named(\"a\");\n\t\tvar m = Movie_.MOVIE.named(\"movies\");\n\t\tvar r = Cypher.anyNode(\"relatedPerson\");\n\t\tvar statement = Cypher.match(Person_.PERSON.withProperties(\"name\", Cypher.anonParameter(name)))\n\t\t\t.optionalMatch(d.DIRECTORS)\n\t\t\t.optionalMatch(a.ACTORS)\n\t\t\t.optionalMatch(Person_.PERSON.relationshipTo(m).relationshipFrom(r, ActedIn_.$TYPE))\n\t\t\t.returningDistinct(Person_.PERSON.getRequiredSymbolicName(), Cypher.collectDistinct(d).as(\"directed\"),\n\t\t\t\t\tCypher.collectDistinct(a).as(\"actedIn\"), Cypher.collectDistinct(r).as(\"related\"))\n\t\t\t.build();\n\n\t\treturn this.peopleRepository.findOne(statement, PersonDetails.class); // <.>\n\t}\n\t// end::using-person-repo[]\n\n\t// tag::using-temporals[]\n\tOptional<Person> createNewPerson(NewPersonCmd newPersonCmd) {\n\t\tvar p = Person_.PERSON.withProperties(Person_.PERSON.NAME, Cypher.anonParameter(newPersonCmd.getName()) // <.>\n\t\t).named(\"p\");\n\n\t\tvar statement = Cypher.merge(p)\n\t\t\t.onCreate()\n\t\t\t.set(p.BORN, Cypher.parameter(\"arbitraryName\").withValue(newPersonCmd.getDob().getYear()), // <.>\n\t\t\t\t\tp.DOB, Cypher.anonParameter(newPersonCmd.getDob()) // <.>\n\t\t\t)\n\t\t\t.returning(p)\n\t\t\t.build();\n\t\treturn this.peopleRepository.findOne(statement);\n\t}\n\t// end::using-temporals[]\n\n\t// tag::using-person-repo[]\n\n}\n// end::using-person-repo[]\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/Person.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n\nimport java.time.ZonedDateTime;\n\nimport com.fasterxml.jackson.annotation.JsonCreator;\nimport com.fasterxml.jackson.annotation.JsonProperty;\n\nimport org.springframework.data.annotation.PersistenceCreator;\nimport org.springframework.data.neo4j.core.schema.GeneratedValue;\nimport org.springframework.data.neo4j.core.schema.Id;\nimport org.springframework.data.neo4j.core.schema.Node;\n\n/**\n * OGM example type.\n *\n * @author Michael J. Simons\n */\n@Node\npublic final class Person {\n\n\t@Id\n\t@GeneratedValue\n\tprivate final Long id;\n\n\tprivate final String name;\n\n\tprivate Integer born;\n\n\tprivate ZonedDateTime dob;\n\n\t@PersistenceCreator\n\tprivate Person(Long id, String name, Integer born) {\n\t\tthis.id = id;\n\t\tthis.born = born;\n\t\tthis.name = name;\n\t}\n\n\t@JsonCreator\n\tpublic Person(@JsonProperty(\"name\") String name, @JsonProperty(\"born\") Integer born) {\n\t\tthis(null, name, born);\n\t}\n\n\tpublic Long getId() {\n\t\treturn this.id;\n\t}\n\n\tpublic String getName() {\n\t\treturn this.name;\n\t}\n\n\tpublic Integer getBorn() {\n\t\treturn this.born;\n\t}\n\n\tpublic void setBorn(Integer born) {\n\t\tthis.born = born;\n\t}\n\n\tpublic ZonedDateTime getDob() {\n\t\treturn this.dob;\n\t}\n\n\tpublic void setDob(ZonedDateTime dob) {\n\t\tthis.dob = dob;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/PersonDetails.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nimport com.fasterxml.jackson.annotation.JsonCreator;\nimport com.fasterxml.jackson.annotation.JsonProperty;\n\n/**\n * This is a DTO based projection, containing a couple of additional details, like the\n * list of movies a person acted in, the movies they direct and which other people they\n * acted with.\n *\n * @author Michael J. Simons\n */\npublic final class PersonDetails {\n\n\tprivate final String name;\n\n\tprivate final Integer born;\n\n\tprivate final List<Movie> actedIn;\n\n\tprivate final List<Movie> directed;\n\n\tprivate final List<Person> related;\n\n\t@JsonCreator\n\tpublic PersonDetails(@JsonProperty(\"name\") String name, @JsonProperty(\"born\") Integer born,\n\t\t\t@JsonProperty(\"actedIn\") List<Movie> actedIn, @JsonProperty(\"directed\") List<Movie> directed,\n\t\t\t@JsonProperty(\"related\") List<Person> related) {\n\t\tthis.name = name;\n\t\tthis.born = born;\n\t\tthis.actedIn = new ArrayList<>(actedIn);\n\t\tthis.directed = new ArrayList<>(directed);\n\t\tthis.related = new ArrayList<>(related);\n\t}\n\n\tpublic String getName() {\n\t\treturn this.name;\n\t}\n\n\tpublic Integer getBorn() {\n\t\treturn this.born;\n\t}\n\n\tpublic List<Movie> getActedIn() {\n\t\treturn Collections.unmodifiableList(this.actedIn);\n\t}\n\n\tpublic List<Movie> getDirected() {\n\t\treturn Collections.unmodifiableList(this.directed);\n\t}\n\n\tpublic List<Person> getRelated() {\n\t\treturn Collections.unmodifiableList(this.related);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/movies/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Domain for testing / educational purpose.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.movies;\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/java/org/neo4j/cypherdsl/examples/sdn6/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * A demo application for Spring Data Neo4j 6 with Cypher-DSL integration as well as the\n * static metamodel.\n */\npackage org.neo4j.cypherdsl.examples.sdn6;\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/main/resources/application.properties",
    "content": "#\n# Copyright (c) 2019-2026 \"Neo4j,\"\n# Neo4j Sweden AB [https://neo4j.com]\n#\n# This file is part of Neo4j.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nlogging.level.org.springframework.data.neo4j.cypher = trace\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/test/java/org/neo4j/cypherdsl/examples/sdn6/ApplicationIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6;\n\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.time.ZoneId;\nimport java.time.ZonedDateTime;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.regex.Pattern;\n\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.DisplayName;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.condition.EnabledIf;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.examples.sdn6.movies.GenreRepository;\nimport org.neo4j.cypherdsl.examples.sdn6.movies.Genre_;\nimport org.neo4j.cypherdsl.examples.sdn6.movies.Movie;\nimport org.neo4j.cypherdsl.examples.sdn6.movies.NewPersonCmd;\nimport org.neo4j.cypherdsl.examples.sdn6.movies.Person;\nimport org.neo4j.cypherdsl.examples.sdn6.movies.PersonDetails;\nimport org.neo4j.driver.AuthTokens;\nimport org.neo4j.driver.GraphDatabase;\nimport org.testcontainers.junit.jupiter.Container;\nimport org.testcontainers.junit.jupiter.Testcontainers;\nimport org.testcontainers.neo4j.Neo4jContainer;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.resttestclient.TestRestTemplate;\nimport org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.core.ParameterizedTypeReference;\nimport org.springframework.core.io.DefaultResourceLoader;\nimport org.springframework.core.io.ResourceLoader;\nimport org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.test.context.DynamicPropertyRegistry;\nimport org.springframework.test.context.DynamicPropertySource;\nimport org.springframework.util.FileCopyUtils;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\n@EnabledIf(\"is606OrHigher\")\n@Testcontainers(disabledWithoutDocker = true)\n@AutoConfigureTestRestTemplate\nclass ApplicationIT {\n\n\t@Container\n\tprivate static final Neo4jContainer neo4j = new Neo4jContainer(\"neo4j:2025.06\").withReuse(true);\n\n\t@SuppressWarnings(\"unused\") // It is used via {@code @EnableIf}\n\tstatic boolean is606OrHigher() {\n\t\tString version = Optional.of(EnableNeo4jRepositories.class)\n\t\t\t.map(Class::getPackage)\n\t\t\t.map(Package::getImplementationVersion)\n\t\t\t.map(String::trim)\n\t\t\t.filter(v -> !v.isEmpty())\n\t\t\t.orElse(\"0\");\n\t\tvar matcher = Pattern.compile(\"(\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+)(?:.*)\").matcher(version);\n\t\treturn matcher.matches() && Integer.parseInt(matcher.group(1)) >= 6\n\t\t\t\t&& (Integer.parseInt(matcher.group(2)) == 0 && Integer.parseInt(matcher.group(3)) >= 6\n\t\t\t\t\t\t|| Integer.parseInt(matcher.group(2)) >= 1);\n\t}\n\n\t@BeforeAll\n\tstatic void loadMovies() throws IOException {\n\t\tResourceLoader r = new DefaultResourceLoader();\n\t\ttry (var in = new InputStreamReader(r.getResource(\"classpath:movies.cypher\").getInputStream());\n\t\t\t\tvar driver = GraphDatabase.driver(neo4j.getBoltUrl(),\n\t\t\t\t\t\tAuthTokens.basic(\"neo4j\", neo4j.getAdminPassword()));\n\t\t\t\tvar session = driver.session()) {\n\t\t\tvar movies = FileCopyUtils.copyToString(in);\n\t\t\tsession.run(movies);\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"unused\") // Used via Spring magic\n\t@DynamicPropertySource\n\tstatic void neo4jProperties(DynamicPropertyRegistry registry) {\n\t\tregistry.add(\"spring.neo4j.uri=\", neo4j::getBoltUrl);\n\t\tregistry.add(\"spring.neo4j.authentication.username\", () -> \"neo4j\");\n\t\tregistry.add(\"spring.neo4j.authentication.password\", () -> neo4j.getAdminPassword());\n\t}\n\n\t@Test\n\t@DisplayName(\"Retrieving mapped objects sorted by a static field.\")\n\tvoid getMoviesShouldWork(@Autowired TestRestTemplate restTemplate) {\n\n\t\tvar exchange = restTemplate.exchange(\"/api/movies\", HttpMethod.GET, null,\n\t\t\t\tnew ParameterizedTypeReference<List<Movie>>() {\n\t\t\t\t});\n\t\tassertThat(exchange.getStatusCode()).isEqualTo(HttpStatus.OK);\n\t\tassertThat(exchange.getBody()).hasSize(38).element(0).extracting(Movie::getTitle).isEqualTo(\"A Few Good Men\");\n\t\tassertThat(exchange.getBody()).last().extracting(Movie::getTitle).isEqualTo(\"You've Got Mail\");\n\t}\n\n\t@Test\n\t@DisplayName(\"Running a complex query via the Neo4j template itself.\")\n\tvoid getRelatedToShouldWork(@Autowired TestRestTemplate restTemplate) {\n\n\t\tvar exchange = restTemplate.exchange(\"/api/movies/relatedTo/{name}\", HttpMethod.GET, null,\n\t\t\t\tnew ParameterizedTypeReference<List<Movie>>() {\n\t\t\t\t}, \"Tom Hanks\");\n\t\tassertThat(exchange.getStatusCode()).isEqualTo(HttpStatus.OK);\n\t\tassertThat(exchange.getBody()).extracting(Movie::getTitle)\n\t\t\t.containsAll(List.of(\"A League of Their Own\", \"Apollo 13\", \"Cast Away\", \"Charlie Wilson's War\",\n\t\t\t\t\t\"Cloud Atlas\", \"Joe Versus the Volcano\", \"Sleepless in Seattle\", \"That Thing You Do\",\n\t\t\t\t\t\"The Da Vinci Code\", \"The Green Mile\", \"The Polar Express\", \"You've Got Mail\"));\n\t}\n\n\t@Test\n\t@DisplayName(\"Running a complex query for a projection via the Cypher DSL executor\")\n\tvoid getDetailsShouldWork(@Autowired TestRestTemplate restTemplate) {\n\n\t\tvar exchange = restTemplate.exchange(\"/api/people/details/{name}\", HttpMethod.GET, null, PersonDetails.class,\n\t\t\t\t\"Tom Hanks\");\n\t\tassertThat(exchange.getStatusCode()).isEqualTo(HttpStatus.OK);\n\t\tvar details = exchange.getBody();\n\n\t\tassertThat(details).isNotNull();\n\t\tassertThat(details.getName()).isEqualTo(\"Tom Hanks\");\n\t\tassertThat(details.getActedIn()).hasSize(12);\n\t\tassertThat(details.getDirected()).extracting(Movie::getTitle).containsExactly(\"That Thing You Do\");\n\t\tassertThat(details.getRelated()).hasSize(35);\n\t\tassertThat(details.getBorn()).isEqualTo(1956);\n\t}\n\n\t@Test\n\t@DisplayName(\"Using conditions pt1.\")\n\tvoid findPeopleBornInThe70tiesOrShouldWork1(@Autowired TestRestTemplate restTemplate) {\n\n\t\tvar exchange = restTemplate.exchange(\"/api/people/findPeopleBornInThe70tiesOr\", HttpMethod.GET, null,\n\t\t\t\tnew ParameterizedTypeReference<List<Person>>() {\n\t\t\t\t});\n\t\tassertThat(exchange.getStatusCode()).isEqualTo(HttpStatus.OK);\n\t\tvar people = exchange.getBody();\n\t\tassertThat(people).hasSize(17);\n\t}\n\n\t@Test\n\t@DisplayName(\"Using conditions pt2.\")\n\tvoid findPeopleBornInThe70tiesOrShouldWork2(@Autowired TestRestTemplate restTemplate) {\n\n\t\tvar exchange = restTemplate.exchange(\"/api/people/findPeopleBornInThe70tiesOr?name={name}\", HttpMethod.GET,\n\t\t\t\tnull, new ParameterizedTypeReference<List<Person>>() {\n\t\t\t\t}, \"Natalie Portman\");\n\t\tassertThat(exchange.getStatusCode()).isEqualTo(HttpStatus.OK);\n\t\tvar people = exchange.getBody();\n\t\tassertThat(people).hasSize(18);\n\t}\n\n\t@Test\n\t@DisplayName(\"Using conditions pt3.\")\n\tvoid findPeopleBornAfterThe70tiesShouldWork(@Autowired TestRestTemplate restTemplate) {\n\n\t\t// tag::exchange1[]\n\t\tvar exchange = restTemplate.exchange(\"/api/people/v1/findPeopleBornAfterThe70ties?conditions={conditions}\",\n\t\t\t\tHttpMethod.GET, null, new ParameterizedTypeReference<List<Person>>() {\n\t\t\t\t}, \"person.name contains \\\"Ricci\\\" OR person.name ends with 'Hirsch'\");\n\t\t// end::exchange1[]\n\t\tassertThat(exchange.getStatusCode()).isEqualTo(HttpStatus.OK);\n\t\tvar people = exchange.getBody();\n\t\tassertThat(people).hasSize(2);\n\t}\n\n\t@Test\n\t@DisplayName(\"Using conditions pt4.\")\n\tvoid findPeopleBornAfterThe70tiesV2ShouldWork(@Autowired TestRestTemplate restTemplate) {\n\n\t\tvar exchange = restTemplate.exchange(\"/api/people/v2/findPeopleBornAfterThe70ties?conditions={conditions}\",\n\t\t\t\tHttpMethod.GET, null, new ParameterizedTypeReference<List<Person>>() {\n\t\t\t\t}, \"name contains \\\"Ricci\\\" OR name ends with 'Hirsch'\");\n\t\tassertThat(exchange.getStatusCode()).isEqualTo(HttpStatus.OK);\n\t\tvar people = exchange.getBody();\n\t\tassertThat(people).hasSize(2);\n\t}\n\n\t@Test\n\t@DisplayName(\"Using parameters\")\n\tvoid usingTemporalsAsParameterShouldWork(@Autowired TestRestTemplate restTemplate) {\n\n\t\tvar dob = ZonedDateTime.of(1990, 10, 31, 23, 42, 0, 0, ZoneId.of(\"Europe/Berlin\"));\n\t\tvar result = restTemplate.postForObject(\"/api/people/createNewPerson\", new NewPersonCmd(\"Liv Lisa Fries\", dob),\n\t\t\t\tPerson.class);\n\n\t\tassertThat(result.getBorn()).isEqualTo(1990);\n\t\tassertThat(result.getDob()).isEqualTo(dob);\n\t}\n\n\t@Test // GH-315\n\tvoid usingCypherDSLExecutor(@Autowired GenreRepository genreRepository) {\n\n\t\tvar genreModel = Genre_.GENRE.withProperties(Genre_.GENRE.NAME, Cypher.literalOf(\"Comedy\"));\n\t\tvar byStatment = Cypher.merge(genreModel)\n\t\t\t.onCreate()\n\t\t\t.set(genreModel.ID.to(Cypher.randomUUID()))\n\t\t\t.returning(genreModel)\n\t\t\t.build();\n\t\tvar newGenre = genreRepository.findOne(byStatment);\n\t\tassertThat(newGenre).hasValueSatisfying(genre -> {\n\t\t\tassertThat(genre.getId()).isNotNull();\n\t\t\tassertThat(genre.getName()).isEqualTo(\"Comedy\");\n\t\t});\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/test/java/org/neo4j/cypherdsl/examples/sdn6/UsageTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.examples.sdn6.misc.Example_;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n *\n */\nclass UsageTests {\n\n\t@Test // GH-335\n\tvoid defaultUsageOfSelfReferentialNode() {\n\t\tExample_ node = Example_.EXAMPLE;\n\t\tassertThat(node).isNotNull();\n\t}\n\n\t@Test // GH-335\n\tvoid selfReferentialNodesShouldLeadToUsableCode() {\n\t\tExample_ node = Example_.EXAMPLE.named(\"example\");\n\t\tassertThat(node).isNotNull();\n\t}\n\n\t@Test // GH-335\n\tvoid ltolx() {\n\n\t\tvar left = Example_.EXAMPLE.named(\"n\");\n\t\tvar parent = left.withParent(Example_.EXAMPLE.named(\"m\"));\n\t\tassertThat(parent.getLeft().getRequiredSymbolicName().getValue()).isEqualTo(\"n\");\n\t}\n\n\t@Test // GH-335\n\tvoid rtorx() {\n\n\t\tvar parent = Example_.EXAMPLE.withParent(Example_.EXAMPLE.named(\"m\"));\n\t\tassertThat(parent.getRight().getRequiredSymbolicName().getValue()).isEqualTo(\"m\");\n\t}\n\n\t@Test // GH-335\n\tvoid renamingLRShouldWork() {\n\n\t\tvar left = Example_.EXAMPLE.named(\"n\");\n\t\tvar right = Example_.EXAMPLE.named(\"m\");\n\t\tvar rel = left.withParent(right).named(\"r\");\n\t\tvar cypher = Cypher.match(rel)\n\t\t\t.where(right.ID.isEqualTo(Cypher.literalOf(1L)))\n\t\t\t.returning(left, right)\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (n:`Example`)-[r:`BELONGS_TO`]->(m:`Example`) WHERE m.id = 1 RETURN n, m\");\n\t}\n\n\t@Test // GH-335\n\tvoid renamingShouldWork() {\n\n\t\tvar node = Example_.EXAMPLE.named(\"n\");\n\t\tvar rel = node.withParent(Example_.EXAMPLE).named(\"r\");\n\t\tvar cypher = Cypher.match(rel)\n\t\t\t.where(node.ID.isEqualTo(Cypher.literalOf(1L)))\n\t\t\t.returning(node)\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(cypher)\n\t\t\t.matches(\"MATCH \\\\(n:`Example`\\\\)-\\\\[r:`BELONGS_TO`]->\\\\(.+:`Example`\\\\) WHERE n\\\\.id = 1 RETURN n\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/test/java/org/neo4j/cypherdsl/examples/sdn6/books/ScopingTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.examples.sdn6.books;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.ValueSource;\nimport org.neo4j.cypherdsl.core.Cypher;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass ScopingTests {\n\n\t@ParameterizedTest // GH-1014\n\t@ValueSource(booleans = { true, false })\n\tvoid patternExpressionMustNotIntroduceNames(boolean withIt) {\n\n\t\tvar userIdParam = Cypher.parameter(\"userId\");\n\t\tvar limitParam = Cypher.parameter(\"limit\");\n\t\tvar langParam = Cypher.parameter(\"lang\");\n\n\t\tvar book = Book_.BOOK.withProperties(Book_.BOOK.LANG, langParam).named(\"book\");\n\n\t\tvar userDetails = UserDetails_.USER_DETAILS.withProperties(UserDetails_.USER_DETAILS.ID, userIdParam)\n\t\t\t.named(\"user\");\n\t\tvar userPreferences = UserPreferences_.USER_PREFERENCES\n\t\t\t.withProperties(UserPreferences_.USER_PREFERENCES.USER_ID, userIdParam)\n\t\t\t.named(\"preferences\");\n\t\tvar genre = BookGenre_.BOOK_GENRE.named(\"genre\");\n\t\tvar userActivity = UserSuggestionActivity_.USER_SUGGESTION_ACTIVITY\n\t\t\t.withProperties(UserSuggestionActivity_.USER_SUGGESTION_ACTIVITY.USER_ID, userIdParam)\n\t\t\t.named(\"activity\");\n\n\t\tvar relationBookGenre = book.relationshipTo(genre, \"BELONGS_TO\").named(\"rel\");\n\n\t\tvar relationBookAvoidedGenre = book.relationshipTo(BookGenre_.BOOK_GENRE, \"BELONGS_TO\")\n\t\t\t.relationshipFrom(userPreferences, \"AVOIDED\");\n\n\t\tvar relationUserPreferencesGenreBook = userDetails.relationshipTo(userPreferences, \"HAS_PREFERENCES\")\n\t\t\t.relationshipTo(genre, \"PREFERRED\")\n\t\t\t.relationshipFrom(book, \"BELONGS_TO\");\n\n\t\tvar returningBooks = Cypher.call(\"distinct\").withArgs(Cypher.name(\"book\")).asFunction();\n\n\t\t// This is the correct variant, as shown in the latest code update on the issue,\n\t\t// matching the activity first, then\n\t\t// passing it on.\n\t\tif (withIt) {\n\t\t\tvar statement = Cypher.match(relationUserPreferencesGenreBook)\n\t\t\t\t.match(userDetails.relationshipTo(userActivity, \"HAS_ACTIVITY\"))\n\t\t\t\t.where(Cypher.not(Cypher.exists(relationBookAvoidedGenre)))\n\t\t\t\t.with(book, userActivity)\n\t\t\t\t.limit(limitParam)\n\t\t\t\t.match(relationBookGenre)\n\t\t\t\t.where(Cypher.not(Cypher.exists(book.relationshipBetween(userActivity))))\n\t\t\t\t.returning(returningBooks, Cypher.collect(Cypher.name(\"rel\")), Cypher.collect(genre))\n\t\t\t\t.build();\n\n\t\t\tassertThat(statement.getCypher()).isEqualTo(\n\t\t\t\t\t\"MATCH (user:`UserDetails` {id: $userId})-[:`HAS_PREFERENCES`]->(preferences:`UserPreferences` {userId: $userId})-[:`PREFERRED`]->(genre:`BookGenre`)<-[:`BELONGS_TO`]-(book:`Book` {lang: $lang}) MATCH (user)-[:`HAS_ACTIVITY`]->(activity:`UserSuggestionActivity` {userId: $userId}) WHERE NOT (exists((book)-[:`BELONGS_TO`]->(:`BookGenre`)<-[:`AVOIDED`]-(preferences))) WITH book, activity LIMIT $limit MATCH (book)-[rel:`BELONGS_TO`]->(genre:`BookGenre`) WHERE NOT (exists((book)--(activity))) RETURN distinct(book), collect(rel), collect(genre)\");\n\n\t\t}\n\t\telse {\n\t\t\t// Statement is identical, except the with clause. activity goes out of scope,\n\t\t\t// hence in the existential subquery it will be rerendered.\n\t\t\t// There however it must not include the name a new\n\t\t\tvar statement = Cypher.match(relationUserPreferencesGenreBook)\n\t\t\t\t.match(userDetails.relationshipTo(userActivity, \"HAS_ACTIVITY\"))\n\t\t\t\t.where(Cypher.not(Cypher.exists(relationBookAvoidedGenre)))\n\t\t\t\t.with(book)\n\t\t\t\t.limit(limitParam)\n\t\t\t\t.match(relationBookGenre)\n\t\t\t\t.where(Cypher.not(Cypher.exists(book.relationshipBetween(userActivity))))\n\t\t\t\t.returning(returningBooks, Cypher.collect(Cypher.name(\"rel\")), Cypher.collect(genre))\n\t\t\t\t.build();\n\t\t\tassertThat(statement.getCypher()).isEqualTo(\n\t\t\t\t\t\"MATCH (user:`UserDetails` {id: $userId})-[:`HAS_PREFERENCES`]->(preferences:`UserPreferences` {userId: $userId})-[:`PREFERRED`]->(genre:`BookGenre`)<-[:`BELONGS_TO`]-(book:`Book` {lang: $lang}) MATCH (user)-[:`HAS_ACTIVITY`]->(activity:`UserSuggestionActivity` {userId: $userId}) WHERE NOT (exists((book)-[:`BELONGS_TO`]->(:`BookGenre`)<-[:`AVOIDED`]-(preferences))) WITH book LIMIT $limit MATCH (book)-[rel:`BELONGS_TO`]->(genre:`BookGenre`) WHERE NOT (exists((book)--(:`UserSuggestionActivity` {userId: $userId}))) RETURN distinct(book), collect(rel), collect(genre)\");\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/test/resources/logback-test.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<configuration>\n\n\t<appender name=\"console\" class=\"ch.qos.logback.core.ConsoleAppender\">\n\t\t<encoder>\n\t\t\t<pattern>[%t] %d %5p %40.40c:%4L - %m%n</pattern>\n\t\t</encoder>\n\t</appender>\n\n\t<logger name=\"org.neo4j.cypherdsl.examples.sdn6\" level=\"info\"/>\n\n\t<root level=\"warn\">\n\t\t<appender-ref ref=\"console\"/>\n\t</root>\n</configuration>"
  },
  {
    "path": "neo4j-cypher-dsl-examples/neo4j-cypher-dsl-examples-sdn6/src/test/resources/movies.cypher",
    "content": "CREATE (TheMatrix:Movie {title:'The Matrix', released:1999, tagline:'Welcome to the Real World'})\nCREATE (Keanu:Person {name:'Keanu Reeves', born:1964})\nCREATE (Carrie:Person {name:'Carrie-Anne Moss', born:1967})\nCREATE (Laurence:Person {name:'Laurence Fishburne', born:1961})\nCREATE (Hugo:Person {name:'Hugo Weaving', born:1960})\nCREATE (LillyW:Person {name:'Lilly Wachowski', born:1967})\nCREATE (LanaW:Person {name:'Lana Wachowski', born:1965})\nCREATE (JoelS:Person {name:'Joel Silver', born:1952})\nCREATE\n(Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrix),\n(Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrix),\n(Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrix),\n(Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrix),\n(LillyW)-[:DIRECTED]->(TheMatrix),\n(LanaW)-[:DIRECTED]->(TheMatrix),\n(JoelS)-[:PRODUCED]->(TheMatrix)\n\nCREATE (Emil:Person {name:\"Emil Eifrem\", born:1978})\nCREATE (Emil)-[:ACTED_IN {roles:[\"Emil\"]}]->(TheMatrix)\n\nCREATE (TheMatrixReloaded:Movie {title:'The Matrix Reloaded', released:2003, tagline:'Free your mind'})\nCREATE\n(Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrixReloaded),\n(Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrixReloaded),\n(Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrixReloaded),\n(Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrixReloaded),\n(LillyW)-[:DIRECTED]->(TheMatrixReloaded),\n(LanaW)-[:DIRECTED]->(TheMatrixReloaded),\n(JoelS)-[:PRODUCED]->(TheMatrixReloaded)\n\nCREATE (TheMatrixRevolutions:Movie {title:'The Matrix Revolutions', released:2003, tagline:'Everything that has a beginning has an end'})\nCREATE\n(Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrixRevolutions),\n(Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrixRevolutions),\n(Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrixRevolutions),\n(Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrixRevolutions),\n(LillyW)-[:DIRECTED]->(TheMatrixRevolutions),\n(LanaW)-[:DIRECTED]->(TheMatrixRevolutions),\n(JoelS)-[:PRODUCED]->(TheMatrixRevolutions)\n\nCREATE (TheDevilsAdvocate:Movie {title:\"The Devil's Advocate\", released:1997, tagline:'Evil has its winning ways'})\nCREATE (Charlize:Person {name:'Charlize Theron', born:1975})\nCREATE (Al:Person {name:'Al Pacino', born:1940})\nCREATE (Taylor:Person {name:'Taylor Hackford', born:1944})\nCREATE\n(Keanu)-[:ACTED_IN {roles:['Kevin Lomax']}]->(TheDevilsAdvocate),\n(Charlize)-[:ACTED_IN {roles:['Mary Ann Lomax']}]->(TheDevilsAdvocate),\n(Al)-[:ACTED_IN {roles:['John Milton']}]->(TheDevilsAdvocate),\n(Taylor)-[:DIRECTED]->(TheDevilsAdvocate)\n\nCREATE (AFewGoodMen:Movie {title:\"A Few Good Men\", released:1992, tagline:\"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.\"})\nCREATE (TomC:Person {name:'Tom Cruise', born:1962})\nCREATE (JackN:Person {name:'Jack Nicholson', born:1937})\nCREATE (DemiM:Person {name:'Demi Moore', born:1962})\nCREATE (KevinB:Person {name:'Kevin Bacon', born:1958})\nCREATE (KieferS:Person {name:'Kiefer Sutherland', born:1966})\nCREATE (NoahW:Person {name:'Noah Wyle', born:1971})\nCREATE (CubaG:Person {name:'Cuba Gooding Jr.', born:1968})\nCREATE (KevinP:Person {name:'Kevin Pollak', born:1957})\nCREATE (JTW:Person {name:'J.T. Walsh', born:1943})\nCREATE (JamesM:Person {name:'James Marshall', born:1967})\nCREATE (ChristopherG:Person {name:'Christopher Guest', born:1948})\nCREATE (RobR:Person {name:'Rob Reiner', born:1947})\nCREATE (AaronS:Person {name:'Aaron Sorkin', born:1961})\nCREATE\n(TomC)-[:ACTED_IN {roles:['Lt. Daniel Kaffee']}]->(AFewGoodMen),\n(JackN)-[:ACTED_IN {roles:['Col. Nathan R. Jessup']}]->(AFewGoodMen),\n(DemiM)-[:ACTED_IN {roles:['Lt. Cdr. JoAnne Galloway']}]->(AFewGoodMen),\n(KevinB)-[:ACTED_IN {roles:['Capt. Jack Ross']}]->(AFewGoodMen),\n(KieferS)-[:ACTED_IN {roles:['Lt. Jonathan Kendrick']}]->(AFewGoodMen),\n(NoahW)-[:ACTED_IN {roles:['Cpl. Jeffrey Barnes']}]->(AFewGoodMen),\n(CubaG)-[:ACTED_IN {roles:['Cpl. Carl Hammaker']}]->(AFewGoodMen),\n(KevinP)-[:ACTED_IN {roles:['Lt. Sam Weinberg']}]->(AFewGoodMen),\n(JTW)-[:ACTED_IN {roles:['Lt. Col. Matthew Andrew Markinson']}]->(AFewGoodMen),\n(JamesM)-[:ACTED_IN {roles:['Pfc. Louden Downey']}]->(AFewGoodMen),\n(ChristopherG)-[:ACTED_IN {roles:['Dr. Stone']}]->(AFewGoodMen),\n(AaronS)-[:ACTED_IN {roles:['Man in Bar']}]->(AFewGoodMen),\n(RobR)-[:DIRECTED]->(AFewGoodMen),\n(AaronS)-[:WROTE]->(AFewGoodMen)\n\nCREATE (TopGun:Movie {title:\"Top Gun\", released:1986, tagline:'I feel the need, the need for speed.'})\nCREATE (KellyM:Person {name:'Kelly McGillis', born:1957})\nCREATE (ValK:Person {name:'Val Kilmer', born:1959})\nCREATE (AnthonyE:Person {name:'Anthony Edwards', born:1962})\nCREATE (TomS:Person {name:'Tom Skerritt', born:1933})\nCREATE (MegR:Person {name:'Meg Ryan', born:1961})\nCREATE (TonyS:Person {name:'Tony Scott', born:1944})\nCREATE (JimC:Person {name:'Jim Cash', born:1941})\nCREATE\n(TomC)-[:ACTED_IN {roles:['Maverick']}]->(TopGun),\n(KellyM)-[:ACTED_IN {roles:['Charlie']}]->(TopGun),\n(ValK)-[:ACTED_IN {roles:['Iceman']}]->(TopGun),\n(AnthonyE)-[:ACTED_IN {roles:['Goose']}]->(TopGun),\n(TomS)-[:ACTED_IN {roles:['Viper']}]->(TopGun),\n(MegR)-[:ACTED_IN {roles:['Carole']}]->(TopGun),\n(TonyS)-[:DIRECTED]->(TopGun),\n(JimC)-[:WROTE]->(TopGun)\n\nCREATE (JerryMaguire:Movie {title:'Jerry Maguire', released:2000, tagline:'The rest of his life begins now.'})\nCREATE (ReneeZ:Person {name:'Renee Zellweger', born:1969})\nCREATE (KellyP:Person {name:'Kelly Preston', born:1962})\nCREATE (JerryO:Person {name:\"Jerry O'Connell\", born:1974})\nCREATE (JayM:Person {name:'Jay Mohr', born:1970})\nCREATE (BonnieH:Person {name:'Bonnie Hunt', born:1961})\nCREATE (ReginaK:Person {name:'Regina King', born:1971})\nCREATE (JonathanL:Person {name:'Jonathan Lipnicki', born:1996})\nCREATE (CameronC:Person {name:'Cameron Crowe', born:1957})\nCREATE\n(TomC)-[:ACTED_IN {roles:['Jerry Maguire']}]->(JerryMaguire),\n(CubaG)-[:ACTED_IN {roles:['Rod Tidwell']}]->(JerryMaguire),\n(ReneeZ)-[:ACTED_IN {roles:['Dorothy Boyd']}]->(JerryMaguire),\n(KellyP)-[:ACTED_IN {roles:['Avery Bishop']}]->(JerryMaguire),\n(JerryO)-[:ACTED_IN {roles:['Frank Cushman']}]->(JerryMaguire),\n(JayM)-[:ACTED_IN {roles:['Bob Sugar']}]->(JerryMaguire),\n(BonnieH)-[:ACTED_IN {roles:['Laurel Boyd']}]->(JerryMaguire),\n(ReginaK)-[:ACTED_IN {roles:['Marcee Tidwell']}]->(JerryMaguire),\n(JonathanL)-[:ACTED_IN {roles:['Ray Boyd']}]->(JerryMaguire),\n(CameronC)-[:DIRECTED]->(JerryMaguire),\n(CameronC)-[:PRODUCED]->(JerryMaguire),\n(CameronC)-[:WROTE]->(JerryMaguire)\n\nCREATE (StandByMe:Movie {title:\"Stand By Me\", released:1986, tagline:\"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.\"})\nCREATE (RiverP:Person {name:'River Phoenix', born:1970})\nCREATE (CoreyF:Person {name:'Corey Feldman', born:1971})\nCREATE (WilW:Person {name:'Wil Wheaton', born:1972})\nCREATE (JohnC:Person {name:'John Cusack', born:1966})\nCREATE (MarshallB:Person {name:'Marshall Bell', born:1942})\nCREATE\n(WilW)-[:ACTED_IN {roles:['Gordie Lachance']}]->(StandByMe),\n(RiverP)-[:ACTED_IN {roles:['Chris Chambers']}]->(StandByMe),\n(JerryO)-[:ACTED_IN {roles:['Vern Tessio']}]->(StandByMe),\n(CoreyF)-[:ACTED_IN {roles:['Teddy Duchamp']}]->(StandByMe),\n(JohnC)-[:ACTED_IN {roles:['Denny Lachance']}]->(StandByMe),\n(KieferS)-[:ACTED_IN {roles:['Ace Merrill']}]->(StandByMe),\n(MarshallB)-[:ACTED_IN {roles:['Mr. Lachance']}]->(StandByMe),\n(RobR)-[:DIRECTED]->(StandByMe)\n\nCREATE (AsGoodAsItGets:Movie {title:'As Good as It Gets', released:1997, tagline:'A comedy from the heart that goes for the throat.'})\nCREATE (HelenH:Person {name:'Helen Hunt', born:1963})\nCREATE (GregK:Person {name:'Greg Kinnear', born:1963})\nCREATE (JamesB:Person {name:'James L. Brooks', born:1940})\nCREATE\n(JackN)-[:ACTED_IN {roles:['Melvin Udall']}]->(AsGoodAsItGets),\n(HelenH)-[:ACTED_IN {roles:['Carol Connelly']}]->(AsGoodAsItGets),\n(GregK)-[:ACTED_IN {roles:['Simon Bishop']}]->(AsGoodAsItGets),\n(CubaG)-[:ACTED_IN {roles:['Frank Sachs']}]->(AsGoodAsItGets),\n(JamesB)-[:DIRECTED]->(AsGoodAsItGets)\n\nCREATE (WhatDreamsMayCome:Movie {title:'What Dreams May Come', released:1998, tagline:'After life there is more. The end is just the beginning.'})\nCREATE (AnnabellaS:Person {name:'Annabella Sciorra', born:1960})\nCREATE (MaxS:Person {name:'Max von Sydow', born:1929})\nCREATE (WernerH:Person {name:'Werner Herzog', born:1942})\nCREATE (Robin:Person {name:'Robin Williams', born:1951})\nCREATE (VincentW:Person {name:'Vincent Ward', born:1956})\nCREATE\n(Robin)-[:ACTED_IN {roles:['Chris Nielsen']}]->(WhatDreamsMayCome),\n(CubaG)-[:ACTED_IN {roles:['Albert Lewis']}]->(WhatDreamsMayCome),\n(AnnabellaS)-[:ACTED_IN {roles:['Annie Collins-Nielsen']}]->(WhatDreamsMayCome),\n(MaxS)-[:ACTED_IN {roles:['The Tracker']}]->(WhatDreamsMayCome),\n(WernerH)-[:ACTED_IN {roles:['The Face']}]->(WhatDreamsMayCome),\n(VincentW)-[:DIRECTED]->(WhatDreamsMayCome)\n\nCREATE (SnowFallingonCedars:Movie {title:'Snow Falling on Cedars', released:1999, tagline:'First loves last. Forever.'})\nCREATE (EthanH:Person {name:'Ethan Hawke', born:1970})\nCREATE (RickY:Person {name:'Rick Yune', born:1971})\nCREATE (JamesC:Person {name:'James Cromwell', born:1940})\nCREATE (ScottH:Person {name:'Scott Hicks', born:1953})\nCREATE\n(EthanH)-[:ACTED_IN {roles:['Ishmael Chambers']}]->(SnowFallingonCedars),\n(RickY)-[:ACTED_IN {roles:['Kazuo Miyamoto']}]->(SnowFallingonCedars),\n(MaxS)-[:ACTED_IN {roles:['Nels Gudmundsson']}]->(SnowFallingonCedars),\n(JamesC)-[:ACTED_IN {roles:['Judge Fielding']}]->(SnowFallingonCedars),\n(ScottH)-[:DIRECTED]->(SnowFallingonCedars)\n\nCREATE (YouveGotMail:Movie {title:\"You've Got Mail\", released:1998, tagline:'At odds in life... in love on-line.'})\nCREATE (ParkerP:Person {name:'Parker Posey', born:1968})\nCREATE (DaveC:Person {name:'Dave Chappelle', born:1973})\nCREATE (SteveZ:Person {name:'Steve Zahn', born:1967})\nCREATE (TomH:Person {name:'Tom Hanks', born:1956})\nCREATE (NoraE:Person {name:'Nora Ephron', born:1941})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Joe Fox']}]->(YouveGotMail),\n(MegR)-[:ACTED_IN {roles:['Kathleen Kelly']}]->(YouveGotMail),\n(GregK)-[:ACTED_IN {roles:['Frank Navasky']}]->(YouveGotMail),\n(ParkerP)-[:ACTED_IN {roles:['Patricia Eden']}]->(YouveGotMail),\n(DaveC)-[:ACTED_IN {roles:['Kevin Jackson']}]->(YouveGotMail),\n(SteveZ)-[:ACTED_IN {roles:['George Pappas']}]->(YouveGotMail),\n(NoraE)-[:DIRECTED]->(YouveGotMail)\n\nCREATE (SleeplessInSeattle:Movie {title:'Sleepless in Seattle', released:1993, tagline:'What if someone you never met, someone you never saw, someone you never knew was the only someone for you?'})\nCREATE (RitaW:Person {name:'Rita Wilson', born:1956})\nCREATE (BillPull:Person {name:'Bill Pullman', born:1953})\nCREATE (VictorG:Person {name:'Victor Garber', born:1949})\nCREATE (RosieO:Person {name:\"Rosie O'Donnell\", born:1962})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Sam Baldwin']}]->(SleeplessInSeattle),\n(MegR)-[:ACTED_IN {roles:['Annie Reed']}]->(SleeplessInSeattle),\n(RitaW)-[:ACTED_IN {roles:['Suzy']}]->(SleeplessInSeattle),\n(BillPull)-[:ACTED_IN {roles:['Walter']}]->(SleeplessInSeattle),\n(VictorG)-[:ACTED_IN {roles:['Greg']}]->(SleeplessInSeattle),\n(RosieO)-[:ACTED_IN {roles:['Becky']}]->(SleeplessInSeattle),\n(NoraE)-[:DIRECTED]->(SleeplessInSeattle)\n\nCREATE (JoeVersustheVolcano:Movie {title:'Joe Versus the Volcano', released:1990, tagline:'A story of love, lava and burning desire.'})\nCREATE (JohnS:Person {name:'John Patrick Stanley', born:1950})\nCREATE (Nathan:Person {name:'Nathan Lane', born:1956})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Joe Banks']}]->(JoeVersustheVolcano),\n(MegR)-[:ACTED_IN {roles:['DeDe', 'Angelica Graynamore', 'Patricia Graynamore']}]->(JoeVersustheVolcano),\n(Nathan)-[:ACTED_IN {roles:['Baw']}]->(JoeVersustheVolcano),\n(JohnS)-[:DIRECTED]->(JoeVersustheVolcano)\n\nCREATE (WhenHarryMetSally:Movie {title:'When Harry Met Sally', released:1998, tagline:'Can two friends sleep together and still love each other in the morning?'})\nCREATE (BillyC:Person {name:'Billy Crystal', born:1948})\nCREATE (CarrieF:Person {name:'Carrie Fisher', born:1956})\nCREATE (BrunoK:Person {name:'Bruno Kirby', born:1949})\nCREATE\n(BillyC)-[:ACTED_IN {roles:['Harry Burns']}]->(WhenHarryMetSally),\n(MegR)-[:ACTED_IN {roles:['Sally Albright']}]->(WhenHarryMetSally),\n(CarrieF)-[:ACTED_IN {roles:['Marie']}]->(WhenHarryMetSally),\n(BrunoK)-[:ACTED_IN {roles:['Jess']}]->(WhenHarryMetSally),\n(RobR)-[:DIRECTED]->(WhenHarryMetSally),\n(RobR)-[:PRODUCED]->(WhenHarryMetSally),\n(NoraE)-[:PRODUCED]->(WhenHarryMetSally),\n(NoraE)-[:WROTE]->(WhenHarryMetSally)\n\nCREATE (ThatThingYouDo:Movie {title:'That Thing You Do', released:1996, tagline:'In every life there comes a time when that thing you dream becomes that thing you do'})\nCREATE (LivT:Person {name:'Liv Tyler', born:1977})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Mr. White']}]->(ThatThingYouDo),\n(LivT)-[:ACTED_IN {roles:['Faye Dolan']}]->(ThatThingYouDo),\n(Charlize)-[:ACTED_IN {roles:['Tina']}]->(ThatThingYouDo),\n(TomH)-[:DIRECTED]->(ThatThingYouDo)\n\nCREATE (TheReplacements:Movie {title:'The Replacements', released:2000, tagline:'Pain heals, Chicks dig scars... Glory lasts forever'})\nCREATE (Brooke:Person {name:'Brooke Langton', born:1970})\nCREATE (Gene:Person {name:'Gene Hackman', born:1930})\nCREATE (Orlando:Person {name:'Orlando Jones', born:1968})\nCREATE (Howard:Person {name:'Howard Deutch', born:1950})\nCREATE\n(Keanu)-[:ACTED_IN {roles:['Shane Falco']}]->(TheReplacements),\n(Brooke)-[:ACTED_IN {roles:['Annabelle Farrell']}]->(TheReplacements),\n(Gene)-[:ACTED_IN {roles:['Jimmy McGinty']}]->(TheReplacements),\n(Orlando)-[:ACTED_IN {roles:['Clifford Franklin']}]->(TheReplacements),\n(Howard)-[:DIRECTED]->(TheReplacements)\n\nCREATE (RescueDawn:Movie {title:'RescueDawn', released:2006, tagline:\"Based on the extraordinary true story of one man's fight for freedom\"})\nCREATE (ChristianB:Person {name:'Christian Bale', born:1974})\nCREATE (ZachG:Person {name:'Zach Grenier', born:1954})\nCREATE\n(MarshallB)-[:ACTED_IN {roles:['Admiral']}]->(RescueDawn),\n(ChristianB)-[:ACTED_IN {roles:['Dieter Dengler']}]->(RescueDawn),\n(ZachG)-[:ACTED_IN {roles:['Squad Leader']}]->(RescueDawn),\n(SteveZ)-[:ACTED_IN {roles:['Duane']}]->(RescueDawn),\n(WernerH)-[:DIRECTED]->(RescueDawn)\n\nCREATE (TheBirdcage:Movie {title:'The Birdcage', released:1996, tagline:'Come as you are'})\nCREATE (MikeN:Person {name:'Mike Nichols', born:1931})\nCREATE\n(Robin)-[:ACTED_IN {roles:['Armand Goldman']}]->(TheBirdcage),\n(Nathan)-[:ACTED_IN {roles:['Albert Goldman']}]->(TheBirdcage),\n(Gene)-[:ACTED_IN {roles:['Sen. Kevin Keeley']}]->(TheBirdcage),\n(MikeN)-[:DIRECTED]->(TheBirdcage)\n\nCREATE (Unforgiven:Movie {title:'Unforgiven', released:1992, tagline:\"It's a hell of a thing, killing a man\"})\nCREATE (RichardH:Person {name:'Richard Harris', born:1930})\nCREATE (ClintE:Person {name:'Clint Eastwood', born:1930})\nCREATE\n(RichardH)-[:ACTED_IN {roles:['English Bob']}]->(Unforgiven),\n(ClintE)-[:ACTED_IN {roles:['Bill Munny']}]->(Unforgiven),\n(Gene)-[:ACTED_IN {roles:['Little Bill Daggett']}]->(Unforgiven),\n(ClintE)-[:DIRECTED]->(Unforgiven)\n\nCREATE (JohnnyMnemonic:Movie {title:'Johnny Mnemonic', released:1995, tagline:'The hottest data on earth. In the coolest head in town'})\nCREATE (Takeshi:Person {name:'Takeshi Kitano', born:1947})\nCREATE (Dina:Person {name:'Dina Meyer', born:1968})\nCREATE (IceT:Person {name:'Ice-T', born:1958})\nCREATE (RobertL:Person {name:'Robert Longo', born:1953})\nCREATE\n(Keanu)-[:ACTED_IN {roles:['Johnny Mnemonic']}]->(JohnnyMnemonic),\n(Takeshi)-[:ACTED_IN {roles:['Takahashi']}]->(JohnnyMnemonic),\n(Dina)-[:ACTED_IN {roles:['Jane']}]->(JohnnyMnemonic),\n(IceT)-[:ACTED_IN {roles:['J-Bone']}]->(JohnnyMnemonic),\n(RobertL)-[:DIRECTED]->(JohnnyMnemonic)\n\nCREATE (CloudAtlas:Movie {title:'Cloud Atlas', released:2012, tagline:'Everything is connected'})\nCREATE (HalleB:Person {name:'Halle Berry', born:1966})\nCREATE (JimB:Person {name:'Jim Broadbent', born:1949})\nCREATE (TomT:Person {name:'Tom Tykwer', born:1965})\nCREATE (DavidMitchell:Person {name:'David Mitchell', born:1969})\nCREATE (StefanArndt:Person {name:'Stefan Arndt', born:1961})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Zachry', 'Dr. Henry Goose', 'Isaac Sachs', 'Dermot Hoggins']}]->(CloudAtlas),\n(Hugo)-[:ACTED_IN {roles:['Bill Smoke', 'Haskell Moore', 'Tadeusz Kesselring', 'Nurse Noakes', 'Boardman Mephi', 'Old Georgie']}]->(CloudAtlas),\n(HalleB)-[:ACTED_IN {roles:['Luisa Rey', 'Jocasta Ayrs', 'Ovid', 'Meronym']}]->(CloudAtlas),\n(JimB)-[:ACTED_IN {roles:['Vyvyan Ayrs', 'Captain Molyneux', 'Timothy Cavendish']}]->(CloudAtlas),\n(TomT)-[:DIRECTED]->(CloudAtlas),\n(LillyW)-[:DIRECTED]->(CloudAtlas),\n(LanaW)-[:DIRECTED]->(CloudAtlas),\n(DavidMitchell)-[:WROTE]->(CloudAtlas),\n(StefanArndt)-[:PRODUCED]->(CloudAtlas)\n\nCREATE (TheDaVinciCode:Movie {title:'The Da Vinci Code', released:2006, tagline:'Break The Codes'})\nCREATE (IanM:Person {name:'Ian McKellen', born:1939})\nCREATE (AudreyT:Person {name:'Audrey Tautou', born:1976})\nCREATE (PaulB:Person {name:'Paul Bettany', born:1971})\nCREATE (RonH:Person {name:'Ron Howard', born:1954})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Dr. Robert Langdon']}]->(TheDaVinciCode),\n(IanM)-[:ACTED_IN {roles:['Sir Leight Teabing']}]->(TheDaVinciCode),\n(AudreyT)-[:ACTED_IN {roles:['Sophie Neveu']}]->(TheDaVinciCode),\n(PaulB)-[:ACTED_IN {roles:['Silas']}]->(TheDaVinciCode),\n(RonH)-[:DIRECTED]->(TheDaVinciCode)\n\nCREATE (VforVendetta:Movie {title:'V for Vendetta', released:2006, tagline:'Freedom! Forever!'})\nCREATE (NatalieP:Person {name:'Natalie Portman', born:1981})\nCREATE (StephenR:Person {name:'Stephen Rea', born:1946})\nCREATE (JohnH:Person {name:'John Hurt', born:1940})\nCREATE (BenM:Person {name: 'Ben Miles', born:1967})\nCREATE\n(Hugo)-[:ACTED_IN {roles:['V']}]->(VforVendetta),\n(NatalieP)-[:ACTED_IN {roles:['Evey Hammond']}]->(VforVendetta),\n(StephenR)-[:ACTED_IN {roles:['Eric Finch']}]->(VforVendetta),\n(JohnH)-[:ACTED_IN {roles:['High Chancellor Adam Sutler']}]->(VforVendetta),\n(BenM)-[:ACTED_IN {roles:['Dascomb']}]->(VforVendetta),\n(JamesM)-[:DIRECTED]->(VforVendetta),\n(LillyW)-[:PRODUCED]->(VforVendetta),\n(LanaW)-[:PRODUCED]->(VforVendetta),\n(JoelS)-[:PRODUCED]->(VforVendetta),\n(LillyW)-[:WROTE]->(VforVendetta),\n(LanaW)-[:WROTE]->(VforVendetta)\n\nCREATE (SpeedRacer:Movie {title:'Speed Racer', released:2008, tagline:'Speed has no limits'})\nCREATE (EmileH:Person {name:'Emile Hirsch', born:1985})\nCREATE (JohnG:Person {name:'John Goodman', born:1960})\nCREATE (SusanS:Person {name:'Susan Sarandon', born:1946})\nCREATE (MatthewF:Person {name:'Matthew Fox', born:1966})\nCREATE (ChristinaR:Person {name:'Christina Ricci', born:1980})\nCREATE (Rain:Person {name:'Rain', born:1982})\nCREATE\n(EmileH)-[:ACTED_IN {roles:['Speed Racer']}]->(SpeedRacer),\n(JohnG)-[:ACTED_IN {roles:['Pops']}]->(SpeedRacer),\n(SusanS)-[:ACTED_IN {roles:['Mom']}]->(SpeedRacer),\n(MatthewF)-[:ACTED_IN {roles:['Racer X']}]->(SpeedRacer),\n(ChristinaR)-[:ACTED_IN {roles:['Trixie']}]->(SpeedRacer),\n(Rain)-[:ACTED_IN {roles:['Taejo Togokahn']}]->(SpeedRacer),\n(BenM)-[:ACTED_IN {roles:['Cass Jones']}]->(SpeedRacer),\n(LillyW)-[:DIRECTED]->(SpeedRacer),\n(LanaW)-[:DIRECTED]->(SpeedRacer),\n(LillyW)-[:WROTE]->(SpeedRacer),\n(LanaW)-[:WROTE]->(SpeedRacer),\n(JoelS)-[:PRODUCED]->(SpeedRacer)\n\nCREATE (NinjaAssassin:Movie {title:'Ninja Assassin', released:2009, tagline:'Prepare to enter a secret world of assassins'})\nCREATE (NaomieH:Person {name:'Naomie Harris'})\nCREATE\n(Rain)-[:ACTED_IN {roles:['Raizo']}]->(NinjaAssassin),\n(NaomieH)-[:ACTED_IN {roles:['Mika Coretti']}]->(NinjaAssassin),\n(RickY)-[:ACTED_IN {roles:['Takeshi']}]->(NinjaAssassin),\n(BenM)-[:ACTED_IN {roles:['Ryan Maslow']}]->(NinjaAssassin),\n(JamesM)-[:DIRECTED]->(NinjaAssassin),\n(LillyW)-[:PRODUCED]->(NinjaAssassin),\n(LanaW)-[:PRODUCED]->(NinjaAssassin),\n(JoelS)-[:PRODUCED]->(NinjaAssassin)\n\nCREATE (TheGreenMile:Movie {title:'The Green Mile', released:1999, tagline:\"Walk a mile you'll never forget.\"})\nCREATE (MichaelD:Person {name:'Michael Clarke Duncan', born:1957})\nCREATE (DavidM:Person {name:'David Morse', born:1953})\nCREATE (SamR:Person {name:'Sam Rockwell', born:1968})\nCREATE (GaryS:Person {name:'Gary Sinise', born:1955})\nCREATE (PatriciaC:Person {name:'Patricia Clarkson', born:1959})\nCREATE (FrankD:Person {name:'Frank Darabont', born:1959})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Paul Edgecomb']}]->(TheGreenMile),\n(MichaelD)-[:ACTED_IN {roles:['John Coffey']}]->(TheGreenMile),\n(DavidM)-[:ACTED_IN {roles:['Brutus \"Brutal\" Howell']}]->(TheGreenMile),\n(BonnieH)-[:ACTED_IN {roles:['Jan Edgecomb']}]->(TheGreenMile),\n(JamesC)-[:ACTED_IN {roles:['Warden Hal Moores']}]->(TheGreenMile),\n(SamR)-[:ACTED_IN {roles:['\"Wild Bill\" Wharton']}]->(TheGreenMile),\n(GaryS)-[:ACTED_IN {roles:['Burt Hammersmith']}]->(TheGreenMile),\n(PatriciaC)-[:ACTED_IN {roles:['Melinda Moores']}]->(TheGreenMile),\n(FrankD)-[:DIRECTED]->(TheGreenMile)\n\nCREATE (FrostNixon:Movie {title:'Frost/Nixon', released:2008, tagline:'400 million people were waiting for the truth.'})\nCREATE (FrankL:Person {name:'Frank Langella', born:1938})\nCREATE (MichaelS:Person {name:'Michael Sheen', born:1969})\nCREATE (OliverP:Person {name:'Oliver Platt', born:1960})\nCREATE\n(FrankL)-[:ACTED_IN {roles:['Richard Nixon']}]->(FrostNixon),\n(MichaelS)-[:ACTED_IN {roles:['David Frost']}]->(FrostNixon),\n(KevinB)-[:ACTED_IN {roles:['Jack Brennan']}]->(FrostNixon),\n(OliverP)-[:ACTED_IN {roles:['Bob Zelnick']}]->(FrostNixon),\n(SamR)-[:ACTED_IN {roles:['James Reston, Jr.']}]->(FrostNixon),\n(RonH)-[:DIRECTED]->(FrostNixon)\n\nCREATE (Hoffa:Movie {title:'Hoffa', released:1992, tagline:\"He didn't want law. He wanted justice.\"})\nCREATE (DannyD:Person {name:'Danny DeVito', born:1944})\nCREATE (JohnR:Person {name:'John C. Reilly', born:1965})\nCREATE\n(JackN)-[:ACTED_IN {roles:['Hoffa']}]->(Hoffa),\n(DannyD)-[:ACTED_IN {roles:['Robert \"Bobby\" Ciaro']}]->(Hoffa),\n(JTW)-[:ACTED_IN {roles:['Frank Fitzsimmons']}]->(Hoffa),\n(JohnR)-[:ACTED_IN {roles:['Peter \"Pete\" Connelly']}]->(Hoffa),\n(DannyD)-[:DIRECTED]->(Hoffa)\n\nCREATE (Apollo13:Movie {title:'Apollo 13', released:1995, tagline:'Houston, we have a problem.'})\nCREATE (EdH:Person {name:'Ed Harris', born:1950})\nCREATE (BillPax:Person {name:'Bill Paxton', born:1955})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Jim Lovell']}]->(Apollo13),\n(KevinB)-[:ACTED_IN {roles:['Jack Swigert']}]->(Apollo13),\n(EdH)-[:ACTED_IN {roles:['Gene Kranz']}]->(Apollo13),\n(BillPax)-[:ACTED_IN {roles:['Fred Haise']}]->(Apollo13),\n(GaryS)-[:ACTED_IN {roles:['Ken Mattingly']}]->(Apollo13),\n(RonH)-[:DIRECTED]->(Apollo13)\n\nCREATE (Twister:Movie {title:'Twister', released:1996, tagline:\"Don't Breathe. Don't Look Back.\"})\nCREATE (PhilipH:Person {name:'Philip Seymour Hoffman', born:1967})\nCREATE (JanB:Person {name:'Jan de Bont', born:1943})\nCREATE\n(BillPax)-[:ACTED_IN {roles:['Bill Harding']}]->(Twister),\n(HelenH)-[:ACTED_IN {roles:['Dr. Jo Harding']}]->(Twister),\n(ZachG)-[:ACTED_IN {roles:['Eddie']}]->(Twister),\n(PhilipH)-[:ACTED_IN {roles:['Dustin \"Dusty\" Davis']}]->(Twister),\n(JanB)-[:DIRECTED]->(Twister)\n\nCREATE (CastAway:Movie {title:'Cast Away', released:2000, tagline:'At the edge of the world, his journey begins.'})\nCREATE (RobertZ:Person {name:'Robert Zemeckis', born:1951})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Chuck Noland']}]->(CastAway),\n(HelenH)-[:ACTED_IN {roles:['Kelly Frears']}]->(CastAway),\n(RobertZ)-[:DIRECTED]->(CastAway)\n\nCREATE (OneFlewOvertheCuckoosNest:Movie {title:\"One Flew Over the Cuckoo's Nest\", released:1975, tagline:\"If he's crazy, what does that make you?\"})\nCREATE (MilosF:Person {name:'Milos Forman', born:1932})\nCREATE\n(JackN)-[:ACTED_IN {roles:['Randle McMurphy']}]->(OneFlewOvertheCuckoosNest),\n(DannyD)-[:ACTED_IN {roles:['Martini']}]->(OneFlewOvertheCuckoosNest),\n(MilosF)-[:DIRECTED]->(OneFlewOvertheCuckoosNest)\n\nCREATE (SomethingsGottaGive:Movie {title:\"Something's Gotta Give\", released:2003})\nCREATE (DianeK:Person {name:'Diane Keaton', born:1946})\nCREATE (NancyM:Person {name:'Nancy Meyers', born:1949})\nCREATE\n(JackN)-[:ACTED_IN {roles:['Harry Sanborn']}]->(SomethingsGottaGive),\n(DianeK)-[:ACTED_IN {roles:['Erica Barry']}]->(SomethingsGottaGive),\n(Keanu)-[:ACTED_IN {roles:['Julian Mercer']}]->(SomethingsGottaGive),\n(NancyM)-[:DIRECTED]->(SomethingsGottaGive),\n(NancyM)-[:PRODUCED]->(SomethingsGottaGive),\n(NancyM)-[:WROTE]->(SomethingsGottaGive)\n\nCREATE (BicentennialMan:Movie {title:'Bicentennial Man', released:1999, tagline:\"One robot's 200 year journey to become an ordinary man.\"})\nCREATE (ChrisC:Person {name:'Chris Columbus', born:1958})\nCREATE\n(Robin)-[:ACTED_IN {roles:['Andrew Marin']}]->(BicentennialMan),\n(OliverP)-[:ACTED_IN {roles:['Rupert Burns']}]->(BicentennialMan),\n(ChrisC)-[:DIRECTED]->(BicentennialMan)\n\nCREATE (CharlieWilsonsWar:Movie {title:\"Charlie Wilson's War\", released:2007, tagline:\"A stiff drink. A little mascara. A lot of nerve. Who said they couldn't bring down the Soviet empire.\"})\nCREATE (JuliaR:Person {name:'Julia Roberts', born:1967})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Rep. Charlie Wilson']}]->(CharlieWilsonsWar),\n(JuliaR)-[:ACTED_IN {roles:['Joanne Herring']}]->(CharlieWilsonsWar),\n(PhilipH)-[:ACTED_IN {roles:['Gust Avrakotos']}]->(CharlieWilsonsWar),\n(MikeN)-[:DIRECTED]->(CharlieWilsonsWar)\n\nCREATE (ThePolarExpress:Movie {title:'The Polar Express', released:2004, tagline:'This Holiday Season... Believe'})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Hero Boy', 'Father', 'Conductor', 'Hobo', 'Scrooge', 'Santa Claus']}]->(ThePolarExpress),\n(RobertZ)-[:DIRECTED]->(ThePolarExpress)\n\nCREATE (ALeagueofTheirOwn:Movie {title:'A League of Their Own', released:1992, tagline:'Once in a lifetime you get a chance to do something different.'})\nCREATE (Madonna:Person {name:'Madonna', born:1954})\nCREATE (GeenaD:Person {name:'Geena Davis', born:1956})\nCREATE (LoriP:Person {name:'Lori Petty', born:1963})\nCREATE (PennyM:Person {name:'Penny Marshall', born:1943})\nCREATE\n(TomH)-[:ACTED_IN {roles:['Jimmy Dugan']}]->(ALeagueofTheirOwn),\n(GeenaD)-[:ACTED_IN {roles:['Dottie Hinson']}]->(ALeagueofTheirOwn),\n(LoriP)-[:ACTED_IN {roles:['Kit Keller']}]->(ALeagueofTheirOwn),\n(RosieO)-[:ACTED_IN {roles:['Doris Murphy']}]->(ALeagueofTheirOwn),\n(Madonna)-[:ACTED_IN {roles:['\"All the Way\" Mae Mordabito']}]->(ALeagueofTheirOwn),\n(BillPax)-[:ACTED_IN {roles:['Bob Hinson']}]->(ALeagueofTheirOwn),\n(PennyM)-[:DIRECTED]->(ALeagueofTheirOwn)\n\nCREATE (PaulBlythe:Person {name:'Paul Blythe'})\nCREATE (AngelaScope:Person {name:'Angela Scope'})\nCREATE (JessicaThompson:Person {name:'Jessica Thompson'})\nCREATE (JamesThompson:Person {name:'James Thompson'})\n\nCREATE\n(JamesThompson)-[:FOLLOWS]->(JessicaThompson),\n(AngelaScope)-[:FOLLOWS]->(JessicaThompson),\n(PaulBlythe)-[:FOLLOWS]->(AngelaScope)\n\nCREATE\n(JessicaThompson)-[:REVIEWED {summary:'An amazing journey', rating:95}]->(CloudAtlas),\n(JessicaThompson)-[:REVIEWED {summary:'Silly, but fun', rating:65}]->(TheReplacements),\n(JamesThompson)-[:REVIEWED {summary:'The coolest football movie ever', rating:100}]->(TheReplacements),\n(AngelaScope)-[:REVIEWED {summary:'Pretty funny at times', rating:62}]->(TheReplacements),\n(JessicaThompson)-[:REVIEWED {summary:'Dark, but compelling', rating:85}]->(Unforgiven),\n(JessicaThompson)-[:REVIEWED {summary:\"Slapstick redeemed only by the Robin Williams and Gene Hackman's stellar performances\", rating:45}]->(TheBirdcage),\n(JessicaThompson)-[:REVIEWED {summary:'A solid romp', rating:68}]->(TheDaVinciCode),\n(JamesThompson)-[:REVIEWED {summary:'Fun, but a little far fetched', rating:65}]->(TheDaVinciCode),\n(JessicaThompson)-[:REVIEWED {summary:'You had me at Jerry', rating:92}]->(JerryMaguire)\n\nWITH TomH as a\nMATCH (a)-[:ACTED_IN]->(m)<-[:DIRECTED]-(d) RETURN a,m,d LIMIT 10;\n"
  },
  {
    "path": "neo4j-cypher-dsl-examples/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-parent</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-examples</artifactId>\n\t<packaging>pom</packaging>\n\t<name>Neo4j Cypher DSL (Examples)</name>\n\n\t<modules>\n\t\t<module>neo4j-cypher-dsl-examples-core</module>\n\t\t<module>neo4j-cypher-dsl-examples-parser</module>\n\t\t<module>neo4j-cypher-dsl-examples-ogm-quarkus</module>\n\t\t<module>neo4j-cypher-dsl-examples-sdn6</module>\n\t</modules>\n\n\t<properties>\n\t\t<java-module-name>org.neo4j.cypherdsl.examples</java-module-name>\n\t</properties>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-enforcer-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>enforce</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>enforce</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t<configuration combine.self=\"override\">\n\t\t\t\t\t\t\t<rules>\n\t\t\t\t\t\t\t\t<requireJavaVersion>\n\t\t\t\t\t\t\t\t\t<version>${maven.compiler.release}</version>\n\t\t\t\t\t\t\t\t</requireJavaVersion>\n\t\t\t\t\t\t\t\t<requireMavenVersion>\n\t\t\t\t\t\t\t\t\t<version>${maven.version}</version>\n\t\t\t\t\t\t\t\t</requireMavenVersion>\n\t\t\t\t\t\t\t\t<DependencyConvergence/>\n\t\t\t\t\t\t\t</rules>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-jar-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skipIfEmpty>true</skipIfEmpty>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-install-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-native-tests/README.adoc",
    "content": "== Native tests.\n\nThis is a sample project to ensure that the Cypher-DSL works with GraalVM native.\n"
  },
  {
    "path": "neo4j-cypher-dsl-native-tests/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-parent</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-native-tests</artifactId>\n\n\t<name>Neo4j Cypher DSL (Native Tests)</name>\n\t<description>Ensures Cypher DSL can be compiled and used natively.</description>\n\n\t<properties>\n\t\t<java-module-name>org.neo4j.cypherdsl.graalvm</java-module-name>\n\t\t<native-maven-plugin.version>1.1.0</native-maven-plugin.version>\n\t</properties>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-dsl-bom</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>com.querydsl</groupId>\n\t\t\t<artifactId>querydsl-core</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl-parser</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.assertj</groupId>\n\t\t\t<artifactId>assertj-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.jacoco</groupId>\n\t\t\t\t<artifactId>jacoco-maven-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.graalvm.buildtools</groupId>\n\t\t\t\t<artifactId>native-maven-plugin</artifactId>\n\t\t\t\t<version>${native-maven-plugin.version}</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>compile-no-fork</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<mainClass>org.neo4j.cypherdsl.graalvm.Application</mainClass>\n\t\t\t\t\t\t\t<imageName>application</imageName>\n\t\t\t\t\t\t\t<buildArgs>--no-fallback -H:+ReportExceptionStackTraces</buildArgs>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-jar-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skipIfEmpty>true</skipIfEmpty>\n\t\t\t\t\t<archive>\n\t\t\t\t\t\t<manifestEntries>\n\t\t\t\t\t\t\t<Automatic-Module-Name>${java-module-name}</Automatic-Module-Name>\n\t\t\t\t\t\t</manifestEntries>\n\t\t\t\t\t</archive>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-install-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-failsafe-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>integration-test</goal>\n\t\t\t\t\t\t\t<goal>verify</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-native-tests/src/main/java/org/neo4j/cypherdsl/graalvm/Application.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.graalvm;\n\nimport java.util.Comparator;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport com.querydsl.core.types.dsl.Expressions;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Statement;\nimport org.neo4j.cypherdsl.core.SymbolicName;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Dialect;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\nimport org.neo4j.cypherdsl.parser.CypherParser;\nimport org.neo4j.cypherdsl.parser.Options;\n\n/**\n * A random application which will be complied into a native binary. The testing will\n * check the expected output.\n *\n * @author Michael J. Simons\n */\npublic final class Application {\n\n\tprivate static final Renderer cypherRenderer = Renderer.getDefaultRenderer();\n\n\tprivate Application() {\n\t}\n\n\t@SuppressWarnings(\"checkstyle:regexp\")\n\tpublic static void main(String... a) {\n\n\t\tSystem.out.println(cypherRenderer.render(findAllMovies()));\n\t\tvar statement = generateQueryWithParams();\n\t\tvar catalog = statement.getCatalog();\n\t\tcatalog.getParameters().forEach((k, v) -> System.out.println(k + \"=\" + v));\n\t\tcatalog.getParameterNames().forEach(System.out::println);\n\t\tSystem.out.println(cypherRenderer.render(statement));\n\t\tSystem.out.println(cypherRenderer.render(generateComplexQuery()));\n\t\tSystem.out.println(CypherParser.parse(\"MATCH (p:Parser) RETURN p\").getCypher());\n\t\ttry {\n\t\t\t// noinspection ResultOfMethodCallIgnored\n\t\t\tCypher.returning((Expression) null);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tSystem.out.println(ex.getMessage());\n\t\t}\n\t\tSystem.out.println(useParserForRewrite());\n\t\tSystem.out.println(generateDialectBasedQuery());\n\t\tstatement = CypherParser.parseStatement(\n\t\t\t\t\"MATCH (m:Movie {title: 'The Matrix'}) <- [a:ACTED_IN] - (p:Person) WHERE p.born >= 1979 RETURN m, a, p\");\n\t\tcatalog = statement.getCatalog();\n\t\tcatalog.getIdentifiableExpressions()\n\t\t\t.stream()\n\t\t\t.filter(SymbolicName.class::isInstance)\n\t\t\t.map(SymbolicName.class::cast)\n\t\t\t.map(SymbolicName::getValue)\n\t\t\t.sorted()\n\t\t\t.forEach(System.out::println);\n\t\tcatalog.getAllPropertyFilters()\n\t\t\t.entrySet()\n\t\t\t.stream()\n\t\t\t.sorted(Comparator.comparing(o -> o.getKey().name()))\n\t\t\t.forEach(e -> System.out.println(e.getKey().name() + \": \"\n\t\t\t\t\t+ e.getValue().stream().limit(1).map(cc -> cc.right().toString()).collect(Collectors.joining())));\n\t\tSystem.out.println(\n\t\t\t\tCypher.returning(Cypher.adapt(Expressions.TRUE.isTrue().and(Expressions.FALSE.isTrue())).asExpression())\n\t\t\t\t\t.build()\n\t\t\t\t\t.getCypher());\n\t}\n\n\tprivate static Statement findAllMovies() {\n\n\t\tvar m = Cypher.node(\"Movie\").named(\"m\");\n\t\treturn Cypher.match(m).returning(m).build();\n\t}\n\n\tprivate static Statement generateQueryWithParams() {\n\n\t\tvar m = Cypher.node(\"Movie\").named(\"m\");\n\t\treturn Cypher.match(m)\n\t\t\t.where(m.property(\"title\").isEqualTo(Cypher.parameter(\"title\")))\n\t\t\t.or(m.property(\"title\").isEqualTo(Cypher.parameter(\"pTitle\", \"someTitle\")))\n\t\t\t.or(m.property(\"title\").isEqualTo(Cypher.anonParameter(\"someOtherTitle\")))\n\t\t\t.returning(m)\n\t\t\t.build();\n\t}\n\n\tprivate static Statement generateComplexQuery() {\n\n\t\tvar person = Cypher.node(\"Person\").named(\"person\");\n\t\tvar location = Cypher.node(\"Location\").named(\"personLivesIn\");\n\t\treturn Cypher.match(person)\n\t\t\t.returning(person.project(\"livesIn\",\n\t\t\t\t\tCypher.subList(\n\t\t\t\t\t\t\tCypher.listBasedOn(person.relationshipTo(location, \"LIVES_IN\"))\n\t\t\t\t\t\t\t\t.returning(location.project(\"name\")),\n\t\t\t\t\t\t\tCypher.parameter(\"personLivedInOffset\"),\n\t\t\t\t\t\t\tCypher.parameter(\"personLivedInOffset\").add(Cypher.parameter(\"personLivedInFirst\")))))\n\t\t\t.build();\n\t}\n\n\tprivate static String useParserForRewrite() {\n\n\t\treturn CypherParser\n\t\t\t.parseStatement(\"MATCH (p:Person) -[:HAT_GESPIELT_IN] -> (n:Movie) RETURN n\",\n\t\t\t\t\tOptions.newOptions()\n\t\t\t\t\t\t.withTypeFilter(\n\t\t\t\t\t\t\t\t(e, t) -> ((t.size() == 1) && t.contains(\"HAT_GESPIELT_IN\")) ? Set.of(\"ACTED_IN\") : t)\n\t\t\t\t\t\t.build())\n\t\t\t.getCypher();\n\t}\n\n\tprivate static String generateDialectBasedQuery() {\n\n\t\tNode n = Cypher.anyNode(\"n\");\n\t\tRenderer renderer = Renderer.getRenderer(Configuration.newConfig().withDialect(Dialect.NEO4J_5).build());\n\t\treturn renderer.render(Cypher.match(n).returning(Cypher.distance(n.property(\"a\"), n.property(\"b\"))).build());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-native-tests/src/main/java/org/neo4j/cypherdsl/graalvm/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * GraalVM native image testing.\n */\npackage org.neo4j.cypherdsl.graalvm;\n"
  },
  {
    "path": "neo4j-cypher-dsl-native-tests/src/test/java/org/neo4j/cypherdsl/graalvm/NativeApplicationIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.graalvm;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.io.UncheckedIOException;\nimport java.nio.file.Paths;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.concurrent.ExecutionException;\nimport java.util.stream.Collectors;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * This test is run via failsafe after GraalVM native image has build the application.\n *\n * @author Michael J. Simons\n *\n */\nclass NativeApplicationIT {\n\n\t@Test\n\tvoid outputOfNativeBinaryShouldMatchExpectations() throws IOException, ExecutionException, InterruptedException {\n\n\t\tvar statements = List.of(\"MATCH (m:`Movie`) RETURN m\", \"pTitle=someTitle\", \"pcdsl01=someOtherTitle\", \"pTitle\",\n\t\t\t\t\"pcdsl01\", \"title\",\n\t\t\t\t\"MATCH (m:`Movie`) WHERE (m.title = $title OR m.title = $pTitle OR m.title = $pcdsl01) RETURN m\",\n\t\t\t\t\"MATCH (person:`Person`) RETURN person{livesIn: [(person)-[:`LIVES_IN`]->(personLivesIn:`Location`) | personLivesIn{.name}][$personLivedInOffset..($personLivedInOffset + $personLivedInFirst)]}\",\n\t\t\t\t\"MATCH (p:`Parser`) RETURN p\", \"At least one expressions to return is required.\",\n\t\t\t\t\"MATCH (p:`Person`)-[:`ACTED_IN`]->(n:`Movie`) RETURN n\", \"MATCH (n) RETURN point.distance(n.a, n.b)\",\n\t\t\t\t\"a\", \"m\", \"p\", \"born: NumberLiteral{cypher=1979}\", \"title: StringLiteral{cypher='The Matrix'}\",\n\t\t\t\t\"RETURN true = true AND false = true\");\n\n\t\tvar p = new ProcessBuilder(Paths.get(\".\", \"target\", \"application\").toAbsolutePath().normalize().toString())\n\t\t\t.start();\n\n\t\tp.onExit().thenAccept(done -> {\n\t\t\ttry (var in = new BufferedReader(new InputStreamReader(done.getInputStream()))) {\n\t\t\t\tvar generatedStatements = in.lines().collect(Collectors.toCollection(LinkedHashSet::new));\n\t\t\t\tassertThat(generatedStatements).containsExactlyElementsOf(statements);\n\t\t\t}\n\t\t\tcatch (IOException ex) {\n\t\t\t\tthrow new UncheckedIOException(ex);\n\t\t\t}\n\t\t}).get();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/NOTICE.txt",
    "content": "Copyright (c) \"Neo4j\"\nNeo4j Sweden AB [http://neo4j.com]\n\nNeo4j is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nFull license texts are found in LICENSES.txt.\n\n\nThird-party licenses\n--------------------\n\nApache Software License, Version 2.0\n  Scala Library\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/README.adoc",
    "content": "= TCK for Cypher-DSL Parser\n\nMost of the examples / test cases here use the default renderer that always escapes all names.\nThis is unrelated to the actual parsing and can be turned of when rendering the Cypher-DSL-AST.\n\n== Nodes\n\nNodes can be parsed and used in constructions of queries for example.\nThey are probably one of the most useful elements.\n\nParse them via:\n\n[source,java,indent=0,tabsize=4]\n----\nimport org.neo4j.cypherdsl.parser.CypherParser;\n\npublic class Demo {\n\tpublic static void main(String...a) {\n\t\tvar node = CypherParser.parseNode(\"(m:Movie)\");\n\t}\n}\n----\n\n[[nodes-input]]\n.Input\n[source,cypher]\n----\n()\n(:`A`)\n(:A)\n(:A:B)\n(:A:`B`:C)\n(m)\n(m:Movie)\n(m {a:'b'})\n(m {a:'b', c: 'd'})\n----\n\nThey will look like this when rendered with the default renderer:\n\n[[nodes-output]]\n.Output\n[source,cypher]\n----\n()\n(:`A`)\n(:`A`)\n(:`A`:`B`)\n(:`A`:`B`:`C`)\n(m)\n(m:`Movie`)\n(m {a: 'b'})\n(m {a: 'b', c: 'd'})\n----\n\n== Clauses\n\nClauses can be parsed like this:\n\n[source,java,indent=0,tabsize=4]\n----\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.Statement;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport org.neo4j.cypherdsl.parser.CypherParser;\n\npublic class Demo {\n\tpublic static void main(String... a) {\n\t\tvar clause = CypherParser.parseClause(\"MATCH (tom:Person {name: \\\"Tom Hanks\\\"})-[:ACTED_IN]->(tomHanksMovies)\");\n\t\tvar cypher = Renderer.getDefaultRenderer().render(Statement.of(List.of(clause)));\n\t\tSystem.out.println(cypher);\n\t}\n}\n----\n\nThese are the supported clauses:\n\n[[clauses-input]]\n.Input\n[source,cypher]\n----\nMATCH (tom {name: \"Tom Hanks\"})\nMATCH (tom:Person {name: \"Tom Hanks\"})-[:ACTED_IN]->(tomHanksMovies)\nMATCH (n:Movie), (m:Person)\nDELETE n\nDETACH DELETE n\nRETURN n\nRETURN n ORDER by n.name\nRETURN n ORDER by n.name desc\nRETURN n ORDER by n.name SKIP 5\nRETURN n ORDER by n.name SKIP 5 LIMIT 10\nRETURN n ORDER by n.name, n.firstName SKIP 5 LIMIT 10\nRETURN n.name AS name, n.firstName as vorname ORDER by n.name, n.firstName SKIP 5 LIMIT 10\nRETURN distinct n\nRETURN collect(n)\nCREATE (m:Movie)\nCREATE (m:Movie {title: \"A title\"})\nCREATE (a:Person) -[:ACTED_IN] -> (m:Movie {title: \"A title\"})\nMERGE (m:Movie)\nMERGE (m:Movie {title: \"A title\"})\nMERGE (a:Person) -[:ACTED_IN] -> (m:Movie {title: \"A title\"})\nWITH a\nWITH a WHERE a.name = 'Michael'\nWITH a ORDER by n.name, n.firstName desc SKIP 5 LIMIT 10 WHERE a.name = 'Michael'\n----\n\n[[clauses-output]]\n.Rendered output\n[source,cypher]\n----\nMATCH (tom {name: 'Tom Hanks'})\nMATCH (tom:`Person` {name: 'Tom Hanks'})-[:`ACTED_IN`]->(tomHanksMovies)\nMATCH (n:`Movie`), (m:`Person`)\nDELETE n\nDETACH DELETE n\nRETURN n\nRETURN n ORDER BY n.name ASC\nRETURN n ORDER BY n.name DESC\nRETURN n ORDER BY n.name ASC SKIP 5\nRETURN n ORDER BY n.name ASC SKIP 5 LIMIT 10\nRETURN n ORDER BY n.name ASC, n.firstName ASC SKIP 5 LIMIT 10\nRETURN n.name AS name, n.firstName AS vorname ORDER BY n.name ASC, n.firstName ASC SKIP 5 LIMIT 10\nRETURN DISTINCT n\nRETURN collect(n)\nCREATE (m:`Movie`)\nCREATE (m:`Movie` {title: 'A title'})\nCREATE (a:`Person`)-[:`ACTED_IN`]->(m:`Movie` {title: 'A title'})\nMERGE (m:`Movie`)\nMERGE (m:`Movie` {title: 'A title'})\nMERGE (a:`Person`)-[:`ACTED_IN`]->(m:`Movie` {title: 'A title'})\nWITH a\nWITH a WHERE a.name = 'Michael'\nWITH a ORDER BY n.name ASC, n.firstName DESC SKIP 5 LIMIT 10 WHERE a.name = 'Michael'\n----\n\n== Whole queries\n\nOf course, you can parse a query into a Cypher-DSL statement.\nSuch a statement could be combined with another statement into `UNION` query or be used as a subquery.\n\nStatements can be parsed using `parse` or `parseStatement`.\nLike any other `parseXXX` method in the parser, additional `Options` might be supplied as well.\n\n[source,java,indent=0,tabsize=4]\n----\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.Statement;\n\nimport org.neo4j.cypherdsl.parser.CypherParser;\n\npublic class Demo {\n\tpublic static void main(String... a) {\n\t\tvar statement = CypherParser.parse(\"MATCH (movie:Movie) RETURN movie.title\");\n\t\tvar cypher = statement.getCypher();\n\t\tSystem.out.println(cypher);\n\t}\n}\n----\n\n[[statements-input]]\n.Input\n[source,cypher,separated=true]\n----\nMATCH (n)\nRETURN n;\nMATCH (movie:Movie)\nRETURN movie.title;\nMATCH (director {name: 'Oliver Stone'})--(movie)\nRETURN movie.title;\nMATCH (wallstreet {title: 'Wall Street'})<-[:ACTED_IN|:DIRECTED]-(person)\nRETURN person.name;\nMATCH\n  (charlie:Person {name: 'Charlie Sheen'}),\n  (rob:Person {name: 'Rob Reiner'})\nCREATE (rob)-[:`TYPE INCLUDING A SPACE`]->(charlie);\nMATCH (n {name: 'Andy'})\nSET n.surname = 'Taylor'\nRETURN n.name, n.surname;\nMATCH (n {name: 'Andy'})\nSET (CASE WHEN n.age = 36 THEN n END).worksIn = 'Malmo'\nRETURN n.name, n.worksIn;\nMATCH\n  (at {name: 'Andy'}),\n  (pn {name: 'Peter'})\nSET at = pn\nRETURN at.name, at.age, at.hungry, pn.name, pn.age;\nMATCH (n)\nRETURN\nCASE\n  WHEN n.eyes = 'blue' THEN 1\n  WHEN n.age < 40      THEN 2\n  ELSE 3\nEND AS result;\nMATCH (actor:Person {name: 'Charlie Sheen'})-[:ACTED_IN]->(movie:Movie)\nRETURN actor{.name, .realName, movies: collect(movie{.title, .year})};\nMATCH (actor:Person)-[:ACTED_IN]->(movie:Movie)\nWITH actor, count(movie) AS nbrOfMovies\nRETURN actor{.name, nbrOfMovies};\nMATCH (actor:Person {name: 'Charlie Sheen'})\nRETURN actor{.*, .age};\nMATCH (p {name: 'Peter'})\nSET p = {name: 'Peter Smith', position: 'Entrepreneur'}\nRETURN p.name, p.age, p.position;\nMATCH (p {name: 'Peter'})\nSET p += {age: 38, hungry: true, position: 'Entrepreneur'}\nRETURN p.name, p.age, p.hungry, p.position;\nMATCH (p {name: 'Peter'})\nSET p += {}\nRETURN p.name, p.age;\nMATCH (n {name: 'Andy'})\nSET n.position = 'Developer', n.surname = 'Taylor';\nMATCH (n {name: 'Andy'})\nSET n.surname = $surname\nRETURN n.name, n.surname;\nMATCH (n {name: 'Stefan'})\nSET n:German\nRETURN n.name, labels(n) AS labels;\nMATCH (n {name: 'George'})\nSET n:Swedish:Bossman\nRETURN n.name, labels(n) AS labels;\nMATCH (a {name: 'Andy'})\nREMOVE a.age\nRETURN a.name, a.age;\nMATCH (n {name: 'Peter'})\nREMOVE n:German\nRETURN n.name, labels(n);\nMATCH (n {name: 'Peter'})\nREMOVE n:German:Swedish\nRETURN n.name, labels(n);\nMATCH (n:Actor)\nRETURN n.name AS name\nUNION ALL\nMATCH (n:Movie)\nRETURN n.title AS name;\nMATCH (n:Actor)\nRETURN n.name AS name\nUNION\nMATCH (n:Movie)\nRETURN n.title AS name;\nUNWIND [1, 2, 3, null] AS x\nRETURN x, 'val' AS y;\nWITH [1, 1, 2, 2] AS coll\nUNWIND coll AS x\nWITH DISTINCT x\nRETURN collect(x) AS setOfVals;\nWITH\n  [1, 2] AS a,\n  [3, 4] AS b\nUNWIND (a + b) AS x\nRETURN x;\nWITH [[1, 2], [3, 4], 5] AS nested\nUNWIND nested AS x\nUNWIND x AS y\nRETURN y;\nUNWIND [] AS empty\nRETURN empty, 'literal_that_is_not_returned';\nMATCH p=(start)-[*]->(finish)\nWHERE start.name = 'A' AND finish.name = 'D'\nRETURN p;\nMATCH (person:Person) WHERE person.firstname STARTS WITH 'And' RETURN person;\nCALL db.labels();\nCALL db.labels;\nCALL dbms.procedures() YIELD name, signature\nWHERE name='dbms.listConfig'\nRETURN signature;\nCALL `db`.`labels`();\nCALL dbms.security.createUser('example_username', 'example_password', false);\nCALL dbms.security.createUser($username, $password, $requirePasswordChange);\nCALL db.labels() YIELD *;\nCALL db.labels() YIELD label\nRETURN count(label) AS numLabels;\nCALL db.labels() YIELD label\nWHERE label CONTAINS 'User'\nRETURN count(label) AS numLabels;\nCALL db.propertyKeys() YIELD propertyKey AS prop\nMATCH (n)\nWHERE n[prop] IS NOT NULL\nRETURN prop, count(n) AS numNodes;\nMERGE (keanu:Person {name: 'Keanu Reeves'})\nON CREATE\n  SET keanu.created = timestamp()\nRETURN keanu.name, keanu.created;\nMERGE (person:Person)\nON MATCH\n  SET person.found = true\nRETURN person.name, person.found;\nMERGE (keanu:Person {name: 'Keanu Reeves'})\nON CREATE\n  SET keanu.created = timestamp()\nON MATCH\n  SET keanu.lastSeen = timestamp()\nRETURN keanu.name, keanu.created, keanu.lastSeen;\nMERGE (person:Person)\nON MATCH\n  SET\n    person.found = true,\n    person.lastAccessed = timestamp()\nRETURN person.name, person.found, person.lastAccessed;\nMERGE (person:Person)\nON CREATE\n  SET person.created = timestamp()\nON MATCH\n  SET\n    person.found = true,\n    person.lastAccessed = timestamp()\nRETURN person.name, person.found, person.lastAccessed;\nMATCH\n  (charlie:Person {name: 'Charlie Sheen'}),\n  (wallStreet:Movie {title: 'Wall Street'})\nMERGE (charlie)-[r:ACTED_IN]->(wallStreet)\nRETURN charlie.name, type(r), wallStreet.title;\nMATCH\n  (oliver:Person {name: 'Oliver Stone'}),\n  (reiner:Person {name: 'Rob Reiner'})\nMERGE (oliver)-[:DIRECTED]->(movie:Movie)<-[:ACTED_IN]-(reiner)\nRETURN movie;\nMATCH\n  (charlie:Person {name: 'Charlie Sheen'}),\n  (oliver:Person {name: 'Oliver Stone'})\nMERGE (charlie)-[r:KNOWS]-(oliver)\nRETURN r;\nMATCH (person:Person)\nMERGE (city:City {name: person.bornIn})\nMERGE (person)-[r:BORN_IN]->(city)\nRETURN person.name, person.bornIn, city;\nMATCH (person:Person)\nMERGE (person)-[r:HAS_CHAUFFEUR]->(chauffeur:Chauffeur {name: person.chauffeurName})\nRETURN person.name, person.chauffeurName, chauffeur;\nMATCH p = (a)-->(b)-->(c)\nWHERE a.name = 'Alice' AND b.name = 'Bob' AND c.name = 'Daniel'\nRETURN reduce(totalAge = 0, n IN nodes(p) | totalAge + n.age) AS reduction;\nMATCH (p:Person)-[r:IS_FRIENDS_WITH]->(friend:Person)\nWHERE exists((p)-[:WORKS_FOR]->(:Company {name: 'Neo4j'}))\nRETURN p, r, friend;\nMATCH (p:Person)-[r:IS_FRIENDS_WITH]->(friend:Person)\nWHERE EXISTS {\n  MATCH (p)-[:WORKS_FOR]->(:Company {name: 'Neo4j'})\n}\nRETURN p, r, friend;\nMATCH (person:Person)-[:WORKS_FOR]->(company)\nWHERE company.name STARTS WITH \"Company\"\nAND EXISTS {\n  MATCH (person)-[:LIKES]->(t:Technology)\n  WHERE size((t)<-[:LIKES]-()) >= 3\n}\nRETURN person.name as person, company.name AS company;\nCALL {\n\tMATCH (p:Person)-[:LIKES]->(:Technology {type: \"Java\"})\n\tRETURN p\n\n\tUNION\n\n\tMATCH (p:Person)\n\tWHERE size((p)-[:IS_FRIENDS_WITH]->()) > 1\n\tRETURN p\n}\nRETURN p.name AS person, p.birthdate AS dob\nORDER BY dob DESC;\nMATCH p=(start)-[*]->(finish)\nWHERE start.name = 'A' AND finish.name = 'D'\nFOREACH (n IN nodes(p) | SET n.marked = true);\nMATCH (a)\nWHERE a.name = 'Eskil'\nRETURN a.array, [x IN a.array WHERE size(x)= 3];\nMATCH p =(a)-->(b)-->(c)\nWHERE a.name = 'Alice' AND b.name = 'Bob' AND c.name = 'Daniel'\nRETURN [n IN nodes(p) | n.age] AS extracted;\ncall apoc.cypher.run(\"CALL apoc.cypher.run('CALL apoc.cypher.run(\\\"CALL apoc.cypher.run(\\\\'CALL apoc.cypher.run(\\\\\\\\\\\"RETURN true\\\\\\\\\\\", {}) YIELD value RETURN value\\\\', {}) YIELD value RETURN value\\\", {}) YIELD value RETURN value', {}) YIELD value RETURN value\", {}) YIELD value RETURN value;\nWITH 1 as year WHERE 2010 <= year <= 2020 RETURN *;\nMATCH (person:Person) WHERE COUNT { (person)-[:HAS_DOG]->(:Dog) } > 1 RETURN person.name AS name;\nMATCH (person:Person) WHERE COUNT { (person)-[:HAS_DOG]->(d:Dog) WHERE d.name = 'Lassie' } > 1 RETURN person.name AS name;\nMATCH (person:Person)\nRETURN person.name, COUNT { (person)-[:HAS_DOG]->(:Dog) } as howManyDogs;\n----\n\n[[statements-output]]\n.Output\n[source,cypher]\n----\nMATCH (n) RETURN n\nMATCH (movie:`Movie`) RETURN movie.title\nMATCH (director {name: 'Oliver Stone'})--(movie) RETURN movie.title\nMATCH (wallstreet {title: 'Wall Street'})<-[:`ACTED_IN`|`DIRECTED`]-(person) RETURN person.name\nMATCH (charlie:`Person` {name: 'Charlie Sheen'}), (rob:`Person` {name: 'Rob Reiner'}) CREATE (rob)-[:`TYPE INCLUDING A SPACE`]->(charlie)\nMATCH (n {name: 'Andy'}) SET n.surname = 'Taylor' RETURN n.name, n.surname\nMATCH (n {name: 'Andy'}) SET (CASE WHEN n.age = 36 THEN n END).worksIn = 'Malmo' RETURN n.name, n.worksIn\nMATCH (at {name: 'Andy'}), (pn {name: 'Peter'}) SET at = pn RETURN at.name, at.age, at.hungry, pn.name, pn.age\nMATCH (n) RETURN CASE WHEN n.eyes = 'blue' THEN 1 WHEN n.age < 40 THEN 2 ELSE 3 END AS result\nMATCH (actor:`Person` {name: 'Charlie Sheen'})-[:`ACTED_IN`]->(movie:`Movie`) RETURN actor{.name, .realName, movies: collect(movie{.title, .year})}\nMATCH (actor:`Person`)-[:`ACTED_IN`]->(movie:`Movie`) WITH actor, count(movie) AS nbrOfMovies RETURN actor{.name, nbrOfMovies}\nMATCH (actor:`Person` {name: 'Charlie Sheen'}) RETURN actor{.*, .age}\nMATCH (p {name: 'Peter'}) SET p = {name: 'Peter Smith', position: 'Entrepreneur'} RETURN p.name, p.age, p.position\nMATCH (p {name: 'Peter'}) SET p += {age: 38, hungry: true, position: 'Entrepreneur'} RETURN p.name, p.age, p.hungry, p.position\nMATCH (p {name: 'Peter'}) SET p += {} RETURN p.name, p.age\nMATCH (n {name: 'Andy'}) SET n.position = 'Developer', n.surname = 'Taylor'\nMATCH (n {name: 'Andy'}) SET n.surname = $surname RETURN n.name, n.surname\nMATCH (n {name: 'Stefan'}) SET n:`German` RETURN n.name, labels(n) AS labels\nMATCH (n {name: 'George'}) SET n:`Swedish`:`Bossman` RETURN n.name, labels(n) AS labels\nMATCH (a {name: 'Andy'}) REMOVE a.age RETURN a.name, a.age\nMATCH (n {name: 'Peter'}) REMOVE n:`German` RETURN n.name, labels(n)\nMATCH (n {name: 'Peter'}) REMOVE n:`German`:`Swedish` RETURN n.name, labels(n)\nMATCH (n:`Actor`) RETURN n.name AS name UNION ALL MATCH (n:`Movie`) RETURN n.title AS name\nMATCH (n:`Actor`) RETURN n.name AS name UNION MATCH (n:`Movie`) RETURN n.title AS name\nUNWIND [1, 2, 3, NULL] AS x RETURN x, 'val' AS y\nWITH [1, 1, 2, 2] AS coll UNWIND coll AS x WITH DISTINCT x RETURN collect(x) AS setOfVals\nWITH [1, 2] AS a, [3, 4] AS b UNWIND (a + b) AS x RETURN x\nWITH [[1, 2], [3, 4], 5] AS nested UNWIND nested AS x UNWIND x AS y RETURN y\nUNWIND [] AS empty RETURN empty, 'literal_that_is_not_returned'\nMATCH p = (start)-[*]->(finish) WHERE (start.name = 'A' AND finish.name = 'D') RETURN p\nMATCH (person:`Person`) WHERE person.firstname STARTS WITH 'And' RETURN person\nCALL db.labels()\nCALL db.labels()\nCALL dbms.procedures() YIELD name, signature WHERE name = 'dbms.listConfig' RETURN signature\nCALL db.labels()\nCALL dbms.security.createUser('example_username', 'example_password', false)\nCALL dbms.security.createUser($username, $password, $requirePasswordChange)\nCALL db.labels() YIELD *\nCALL db.labels() YIELD label RETURN count(label) AS numLabels\nCALL db.labels() YIELD label WHERE label CONTAINS 'User' RETURN count(label) AS numLabels\nCALL db.propertyKeys() YIELD propertyKey AS prop MATCH (n) WHERE n[prop] IS NOT NULL RETURN prop, count(n) AS numNodes\nMERGE (keanu:`Person` {name: 'Keanu Reeves'}) ON CREATE SET keanu.created = timestamp() RETURN keanu.name, keanu.created\nMERGE (person:`Person`) ON MATCH SET person.found = true RETURN person.name, person.found\nMERGE (keanu:`Person` {name: 'Keanu Reeves'}) ON CREATE SET keanu.created = timestamp() ON MATCH SET keanu.lastSeen = timestamp() RETURN keanu.name, keanu.created, keanu.lastSeen\nMERGE (person:`Person`) ON MATCH SET person.found = true, person.lastAccessed = timestamp() RETURN person.name, person.found, person.lastAccessed\nMERGE (person:`Person`) ON CREATE SET person.created = timestamp() ON MATCH SET person.found = true, person.lastAccessed = timestamp() RETURN person.name, person.found, person.lastAccessed\nMATCH (charlie:`Person` {name: 'Charlie Sheen'}), (wallStreet:`Movie` {title: 'Wall Street'}) MERGE (charlie)-[r:`ACTED_IN`]->(wallStreet) RETURN charlie.name, type(r), wallStreet.title\nMATCH (oliver:`Person` {name: 'Oliver Stone'}), (reiner:`Person` {name: 'Rob Reiner'}) MERGE (oliver)-[:`DIRECTED`]->(movie:`Movie`)<-[:`ACTED_IN`]-(reiner) RETURN movie\nMATCH (charlie:`Person` {name: 'Charlie Sheen'}), (oliver:`Person` {name: 'Oliver Stone'}) MERGE (charlie)-[r:`KNOWS`]-(oliver) RETURN r\nMATCH (person:`Person`) MERGE (city:`City` {name: person.bornIn}) MERGE (person)-[r:`BORN_IN`]->(city) RETURN person.name, person.bornIn, city\nMATCH (person:`Person`) MERGE (person)-[r:`HAS_CHAUFFEUR`]->(chauffeur:`Chauffeur` {name: person.chauffeurName}) RETURN person.name, person.chauffeurName, chauffeur\nMATCH p = (a)-->(b)-->(c) WHERE (a.name = 'Alice' AND b.name = 'Bob' AND c.name = 'Daniel') RETURN reduce(totalAge = 0, n IN nodes(p) | (totalAge + n.age)) AS reduction\nMATCH (p:`Person`)-[r:`IS_FRIENDS_WITH`]->(friend:`Person`) WHERE exists((p)-[:`WORKS_FOR`]->(:`Company` {name: 'Neo4j'})) RETURN p, r, friend\nMATCH (p:`Person`)-[r:`IS_FRIENDS_WITH`]->(friend:`Person`) WHERE EXISTS { MATCH (p)-[:`WORKS_FOR`]->(:`Company` {name: 'Neo4j'}) } RETURN p, r, friend\nMATCH (person:`Person`)-[:`WORKS_FOR`]->(company) WHERE (company.name STARTS WITH 'Company' AND EXISTS { MATCH (person)-[:`LIKES`]->(t:`Technology`) WHERE size((t)<-[:`LIKES`]-()) >= 3 }) RETURN person.name AS person, company.name AS company\nCALL {MATCH (p:`Person`)-[:`LIKES`]->(:`Technology` {type: 'Java'}) RETURN p UNION MATCH (p:`Person`) WHERE size((p)-[:`IS_FRIENDS_WITH`]->()) > 1 RETURN p} RETURN p.name AS person, p.birthdate AS dob ORDER BY dob DESC\nMATCH p = (start)-[*]->(finish) WHERE (start.name = 'A' AND finish.name = 'D') FOREACH (n IN nodes(p) | SET n.marked = true)\nMATCH (a) WHERE a.name = 'Eskil' RETURN a.array, [x IN a.array WHERE size(x) = 3]\nMATCH p = (a)-->(b)-->(c) WHERE (a.name = 'Alice' AND b.name = 'Bob' AND c.name = 'Daniel') RETURN [n IN nodes(p) | n.age] AS extracted\nCALL apoc.cypher.run('CALL apoc.cypher.run(\\'CALL apoc.cypher.run(\\\"CALL apoc.cypher.run(\\\\\\'CALL apoc.cypher.run(\\\\\\\\\\\"RETURN true\\\\\\\\\\\", {}) YIELD value RETURN value\\\\\\', {}) YIELD value RETURN value\\\", {}) YIELD value RETURN value\\', {}) YIELD value RETURN value', {}) YIELD value RETURN value\nWITH 1 AS year WHERE (2010 <= year AND year <= 2020) RETURN *\nMATCH (person:`Person`) WHERE COUNT { (person)-[:`HAS_DOG`]->(:`Dog`) } > 1 RETURN person.name AS name\nMATCH (person:`Person`) WHERE COUNT { (person)-[:`HAS_DOG`]->(d:`Dog`) WHERE d.name = 'Lassie' } > 1 RETURN person.name AS name\nMATCH (person:`Person`) RETURN person.name, COUNT { (person)-[:`HAS_DOG`]->(:`Dog`) } AS howManyDogs\n----\n\n=== Hints\n\nYou can also use hints:\n\n[[statements-input-hints]]\n.Output\n[source,cypher,separated=true]\n----\nMATCH (s:Scientist {born: 1850})-[:RESEARCHED]->(sc:Science)<-[i:INVENTED_BY {year: 560}]-(p:Pioneer {born: 525})-[:LIVES_IN]->(c:City)-[:PART_OF]->(cc:Country {formed: 411}) RETURN *;\nMATCH (s:Scientist {born: 1850})-[:RESEARCHED]->(sc:Science)<-[i:INVENTED_BY {year: 560}]-(p:Pioneer {born: 525})-[:LIVES_IN]->(c:City)-[:PART_OF]->(cc:Country {formed: 411})\nUSING INDEX p:Pioneer(born)\nRETURN *;\nMATCH (s:Scientist {born: 1850})-[:RESEARCHED]->(sc:Science)<-[i:INVENTED_BY {year: 560}]-(p:Pioneer {born: 525})-[:LIVES_IN]->(c:City)-[:PART_OF]->(cc:Country {formed: 411})\nUSING INDEX i:INVENTED_BY(year)\nRETURN *;\nMATCH (s:Scientist {born: 1850})-[:RESEARCHED]->(sc:Science)<-[i:INVENTED_BY {year: 560}]-(p:Pioneer {born: 525})-[:LIVES_IN]->(c:City)-[:PART_OF]->(cc:Country {formed: 411})\nUSING INDEX s:Scientist(born)\nUSING INDEX cc:Country(formed)\nRETURN *;\nMATCH (s:Scientist {born: 1850})-[:RESEARCHED]->(sc:Science)<-[i:INVENTED_BY {year: 560}]-(p:Pioneer {born: 525})-[:LIVES_IN]->(c:City)-[:PART_OF]->(cc:Country {formed: 411})\nUSING SCAN s:Scientist\nRETURN *;\nMATCH (s:Scientist {born: 1850})-[:RESEARCHED]->(sc:Science)<-[i:INVENTED_BY {year: 560}]-(p:Pioneer {born: 525})-[:LIVES_IN]->(c:City)-[:PART_OF]->(cc:Country {formed: 411})\nUSING SCAN i:INVENTED_BY\nRETURN *;\nMATCH (s:Scientist {born: 1850})-[:RESEARCHED]->(sc:Science)<-[i:INVENTED_BY {year: 560}]-(p:Pioneer {born: 525})-[:LIVES_IN]->(c:City)-[:PART_OF]->(cc:Country {formed: 411})\nUSING INDEX s:Scientist(born)\nUSING INDEX cc:Country(formed)\nUSING JOIN ON p\nRETURN *;\nMATCH (s:Scientist {born: 1850})\nOPTIONAL MATCH (s)-[:RESEARCHED]->(sc:Science)\nUSING JOIN ON s\nRETURN *;\n----\n\n[[statements-output-hints]]\n.Output\n[source,cypher]\n----\nMATCH (s:`Scientist` {born: 1850})-[:`RESEARCHED`]->(sc:`Science`)<-[i:`INVENTED_BY` {year: 560}]-(p:`Pioneer` {born: 525})-[:`LIVES_IN`]->(c:`City`)-[:`PART_OF`]->(cc:`Country` {formed: 411}) RETURN *\nMATCH (s:`Scientist` {born: 1850})-[:`RESEARCHED`]->(sc:`Science`)<-[i:`INVENTED_BY` {year: 560}]-(p:`Pioneer` {born: 525})-[:`LIVES_IN`]->(c:`City`)-[:`PART_OF`]->(cc:`Country` {formed: 411}) USING INDEX p:`Pioneer`(born) RETURN *\nMATCH (s:`Scientist` {born: 1850})-[:`RESEARCHED`]->(sc:`Science`)<-[i:`INVENTED_BY` {year: 560}]-(p:`Pioneer` {born: 525})-[:`LIVES_IN`]->(c:`City`)-[:`PART_OF`]->(cc:`Country` {formed: 411}) USING INDEX i:`INVENTED_BY`(year) RETURN *\nMATCH (s:`Scientist` {born: 1850})-[:`RESEARCHED`]->(sc:`Science`)<-[i:`INVENTED_BY` {year: 560}]-(p:`Pioneer` {born: 525})-[:`LIVES_IN`]->(c:`City`)-[:`PART_OF`]->(cc:`Country` {formed: 411}) USING INDEX s:`Scientist`(born) USING INDEX cc:`Country`(formed) RETURN *\nMATCH (s:`Scientist` {born: 1850})-[:`RESEARCHED`]->(sc:`Science`)<-[i:`INVENTED_BY` {year: 560}]-(p:`Pioneer` {born: 525})-[:`LIVES_IN`]->(c:`City`)-[:`PART_OF`]->(cc:`Country` {formed: 411}) USING SCAN s:`Scientist` RETURN *\nMATCH (s:`Scientist` {born: 1850})-[:`RESEARCHED`]->(sc:`Science`)<-[i:`INVENTED_BY` {year: 560}]-(p:`Pioneer` {born: 525})-[:`LIVES_IN`]->(c:`City`)-[:`PART_OF`]->(cc:`Country` {formed: 411}) USING SCAN i:`INVENTED_BY` RETURN *\nMATCH (s:`Scientist` {born: 1850})-[:`RESEARCHED`]->(sc:`Science`)<-[i:`INVENTED_BY` {year: 560}]-(p:`Pioneer` {born: 525})-[:`LIVES_IN`]->(c:`City`)-[:`PART_OF`]->(cc:`Country` {formed: 411}) USING INDEX s:`Scientist`(born) USING INDEX cc:`Country`(formed) USING JOIN ON p RETURN *\nMATCH (s:`Scientist` {born: 1850}) OPTIONAL MATCH (s)-[:`RESEARCHED`]->(sc:`Science`) USING JOIN ON s RETURN *\n----\n\n`USING PERIODIC` is not supported anymore since Neo4j 5 and Cypher-DSL switched to the 5.x parser starting with 2023.0.0. However, you can still use `LOAD CSV`:\n\n[[statements-input-hints-periodic]]\n.Output\n[source,cypher,alwaysEscape=false,separated=true]\n----\nLOAD CSV FROM 'file:///artists-with-escaped-char.csv' AS line\nCREATE (a:Artist {name: line[1], year: toInteger(line[2])})\nRETURN\n  a.name AS name,\n  a.year AS year,\n  size(a.name) AS size;\nLOAD CSV FROM 'file:///artists.csv' AS line\nRETURN linenumber() AS number, line;\nLOAD CSV FROM 'file:///artists.csv' AS line\nRETURN DISTINCT file() AS path;\n----\n\n[[statements-output-hints-periodic]]\n.Output\n[source,cypher,alwaysEscape=false]\n----\nLOAD CSV FROM 'file:///artists-with-escaped-char.csv' AS line CREATE (a:Artist {name: line[1], year: toInteger(line[2])}) RETURN a.name AS name, a.year AS year, size(a.name) AS size\nLOAD CSV FROM 'file:///artists.csv' AS line RETURN linenumber() AS number, line\nLOAD CSV FROM 'file:///artists.csv' AS line RETURN DISTINCT file() AS path\n----\n\n=== Subqueries\n\nExecuting subqueries requires at least Neo4j 4.0, but you can of course parse and modify those queries:\n\n[[statements-input-subqueries]]\n.Input\n[source,cypher,separated=true]\n----\nUNWIND [0, 1, 2] AS x\nCALL {\n  WITH x\n  RETURN x * 10 AS y\n}\nRETURN x, y;\nCALL {\n  MATCH (p:Person)\n  RETURN p\n  ORDER BY p.age ASC\n  LIMIT 1\nUNION\n  MATCH (p:Person)\n  RETURN p\n  ORDER BY p.age DESC\n  LIMIT 1\n}\nRETURN p.name, p.age\nORDER BY p.name;\nCALL {\n  MATCH (p:Person)-[:FRIEND_OF]->(other:Person)\n  RETURN p, other\nUNION\n  MATCH (p:Child)-[:CHILD_OF]->(other:Parent)\n  RETURN p, other\n}\nRETURN DISTINCT p.name, count(other);\nMATCH (p:Person)\nCALL {\n  UNWIND range(1, 5) AS i\n  CREATE (c:Clone)\n  RETURN count(c) AS numberOfClones\n}\nRETURN p.name, numberOfClones;\nUNWIND [0, 1, 2] AS x\nCALL {\n  WITH x\n  RETURN max(x) AS xMax\n}\nRETURN x, xMax;\nMATCH (person:`Person`) WHERE 'Ozzy' IN COLLECT { MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`) RETURN dog.name } RETURN person.name AS name;\n----\n\n[[statements-output-subqueries]]\n.Output\n[source,cypher]\n----\nUNWIND [0, 1, 2] AS x CALL {WITH x RETURN (x * 10) AS y} RETURN x, y\nCALL {MATCH (p:`Person`) RETURN p ORDER BY p.age ASC LIMIT 1 UNION MATCH (p:`Person`) RETURN p ORDER BY p.age DESC LIMIT 1} RETURN p.name, p.age ORDER BY p.name ASC\nCALL {MATCH (p:`Person`)-[:`FRIEND_OF`]->(other:`Person`) RETURN p, other UNION MATCH (p:`Child`)-[:`CHILD_OF`]->(other:`Parent`) RETURN p, other} RETURN DISTINCT p.name, count(other)\nMATCH (p:`Person`) CALL {UNWIND range(1, 5) AS i CREATE (c:`Clone`) RETURN count(c) AS numberOfClones} RETURN p.name, numberOfClones\nUNWIND [0, 1, 2] AS x CALL {WITH x RETURN max(x) AS xMax} RETURN x, xMax\nMATCH (person:`Person`) WHERE 'Ozzy' IN COLLECT { MATCH (person)-[:`HAS_DOG`]->(dog:`Dog`) RETURN dog.name } RETURN person.name AS name\n----\n\n=== Original test suite\n\nSome statements from the original test suite\n\n[[statements-input-originally-generated]]\n.Input\n[source,cypher]\n----\nMATCH (app:`Location` {uuid: $app_uuid})<-[:`PART_OF`*0..3]-(loc_start:`Location`), (loc_start)<-[:`IN`|`IN_ANALYTICS`]-(r:`Resume`) WITH DISTINCT r, loc_start, app MATCH (r)-[:`IN_COHORT_OF`]->(o:`Offer` {is_valid: true})-[:`IN`]->(app) WITH DISTINCT r, loc_start, app, o MATCH (o)-[:`FOR`]->(start_n:`ResumeNode`) WHERE id(start_n) IN $start_ids RETURN DISTINCT r, loc_start, app, o, start_n\nMATCH (b:`Bike`) WHERE (:`Person`)-[:`OWNS`]->(b) WITH b MATCH (o:`Person`)-[r:`OWNS`]->(b) RETURN b.f, r.x\nMATCH (o:`Person`)-[r:`OWNS`]->(b:`Bike`) WHERE (o)-[r]->(b) RETURN r\nMATCH (node:`Division`) WITH DISTINCT node WHERE NOT (node)-[:`IN`]->(:`Department`)-[:`INSIDE` {rel_property: true}]->(:`Department`)-[:`EMPLOYS`]->(:`Employee`) RETURN *\nMATCH (person:`Person`) WHERE (((person)-[:`A`]->() OR (person)-[:`B`]->()) AND (((person)-[:`C`]->() OR ((person)-[:`D`]->() AND (person)-[:`E`]->())) OR (person)-[:`F`]->())) RETURN person\nMATCH (node:`Node`) WITH DISTINCT node, false AS f, CASE WHEN node.ll IS NULL THEN node.l ELSE node.ll END AS l RETURN *\nCALL db.index.fulltext.queryNodes('livesearch', '*a*') YIELD node MATCH (g:`Group`)-[:`GROUPS`]->(a:`Asset`)<-[:`ON`]-(:`Deploy`)<-[:`SCHEDULED`]-(d:`Device`) WHERE a.asset_id = node.asset_id WITH DISTINCT collect(d{.sigfox_id, a}) AS assetdata RETURN assetdata\nCALL db.index.fulltext.queryNodes('livesearch', '*a*') YIELD node AS x MATCH (g:`Group`)-[:`GROUPS`]->(a:`Asset`)<-[:`ON`]-(:`Deploy`)<-[:`SCHEDULED`]-(d:`Device`) WHERE a.asset_id = x.asset_id WITH DISTINCT collect(d{.sigfox_id, a}) AS assetdata RETURN assetdata\nWITH $p AS nameOfIndex CALL db.index.fulltext.queryNodes(nameOfIndex, '*a*') YIELD node MATCH (g:`Group`)-[:`GROUPS`]->(a:`Asset`)<-[:`ON`]-(:`Deploy`)<-[:`SCHEDULED`]-(d:`Device`) WHERE a.asset_id = node.asset_id WITH DISTINCT collect(d{.sigfox_id, a}) AS assetdata RETURN assetdata\nMATCH (n:`Node`) WITH n WITH n CALL my.procedure() YIELD x WITH n RETURN n\nMERGE (p:`Person` {id: apoc.create.uuid()}) SET p.firstName = 'Michael', p.surname = 'Hunger' RETURN p\nMATCH (n) WITH n CALL db.labels() YIELD label WITH label RETURN count(label) AS numLabels\nMATCH (n) WITH n CALL foo() YIELD label WITH label RETURN count(label) AS numLabels\nRETURN [p = (n)-[:`LIKES`|`OWNS`*]->() | p]\nMATCH p = (michael {name: 'Michael Douglas'})-->() RETURN p\nMATCH (person:`Person`) RETURN person{livesIn: [(person)-[:`LIVES_IN`]->(personLivesIn:`Location`) | personLivesIn{.name}][0]}\nMATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) | b.released] AS years\nMATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) WHERE b:`Movie` | b.released] AS years\nMATCH (n:`Person`) RETURN n, [[(n)-[r_f1:`FOUNDED`]->(o1:`Organisation`) | [r_f1, o1]], [(n)-[r_e1:`EMPLOYED_BY`]->(o1) | [r_e1, o1]], [(n)-[r_l1:`LIVES_AT`]->(l1:`Location`) | [r_l1, l1, [[(l1)<-[r_l2:`LIVES_AT`]-(p2:`Person`) | [r_l2, p2]]]]]]\n----\n\n[[statements-output-originally-generated]]\n.Output\n[source,cypher]\n----\nMATCH (app:`Location` {uuid: $app_uuid})<-[:`PART_OF`*0..3]-(loc_start:`Location`), (loc_start)<-[:`IN`|`IN_ANALYTICS`]-(r:`Resume`) WITH DISTINCT r, loc_start, app MATCH (r)-[:`IN_COHORT_OF`]->(o:`Offer` {is_valid: true})-[:`IN`]->(app) WITH DISTINCT r, loc_start, app, o MATCH (o)-[:`FOR`]->(start_n:`ResumeNode`) WHERE id(start_n) IN $start_ids RETURN DISTINCT r, loc_start, app, o, start_n\nMATCH (b:`Bike`) WHERE (:`Person`)-[:`OWNS`]->(b) WITH b MATCH (o:`Person`)-[r:`OWNS`]->(b) RETURN b.f, r.x\nMATCH (o:`Person`)-[r:`OWNS`]->(b:`Bike`) WHERE (o)-[r]->(b) RETURN r\nMATCH (node:`Division`) WITH DISTINCT node WHERE NOT (node)-[:`IN`]->(:`Department`)-[:`INSIDE` {rel_property: true}]->(:`Department`)-[:`EMPLOYS`]->(:`Employee`) RETURN *\nMATCH (person:`Person`) WHERE (((person)-[:`A`]->() OR (person)-[:`B`]->()) AND ((person)-[:`C`]->() OR ((person)-[:`D`]->() AND (person)-[:`E`]->()) OR (person)-[:`F`]->())) RETURN person\nMATCH (node:`Node`) WITH DISTINCT node, false AS f, CASE WHEN node.ll IS NULL THEN node.l ELSE node.ll END AS l RETURN *\nCALL db.index.fulltext.queryNodes('livesearch', '*a*') YIELD node MATCH (g:`Group`)-[:`GROUPS`]->(a:`Asset`)<-[:`ON`]-(:`Deploy`)<-[:`SCHEDULED`]-(d:`Device`) WHERE a.asset_id = node.asset_id WITH DISTINCT collect(d{.sigfox_id, a}) AS assetdata RETURN assetdata\nCALL db.index.fulltext.queryNodes('livesearch', '*a*') YIELD node AS x MATCH (g:`Group`)-[:`GROUPS`]->(a:`Asset`)<-[:`ON`]-(:`Deploy`)<-[:`SCHEDULED`]-(d:`Device`) WHERE a.asset_id = x.asset_id WITH DISTINCT collect(d{.sigfox_id, a}) AS assetdata RETURN assetdata\nWITH $p AS nameOfIndex CALL db.index.fulltext.queryNodes(nameOfIndex, '*a*') YIELD node MATCH (g:`Group`)-[:`GROUPS`]->(a:`Asset`)<-[:`ON`]-(:`Deploy`)<-[:`SCHEDULED`]-(d:`Device`) WHERE a.asset_id = node.asset_id WITH DISTINCT collect(d{.sigfox_id, a}) AS assetdata RETURN assetdata\nMATCH (n:`Node`) WITH n WITH n CALL my.procedure() YIELD x WITH n RETURN n\nMERGE (p:`Person` {id: apoc.create.uuid()}) SET p.firstName = 'Michael', p.surname = 'Hunger' RETURN p\nMATCH (n) WITH n CALL db.labels() YIELD label WITH label RETURN count(label) AS numLabels\nMATCH (n) WITH n CALL foo() YIELD label WITH label RETURN count(label) AS numLabels\nRETURN [p = (n)-[:`LIKES`|`OWNS`*]->() | p]\nMATCH p = (michael {name: 'Michael Douglas'})-->() RETURN p\nMATCH (person:`Person`) RETURN person{livesIn: [(person)-[:`LIVES_IN`]->(personLivesIn:`Location`) | personLivesIn{.name}][0]}\nMATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) | b.released] AS years\nMATCH (a:`Person` {name: 'Keanu Reeves'}) RETURN [(a)--(b) WHERE b:`Movie` | b.released] AS years\nMATCH (n:`Person`) RETURN n, [[(n)-[r_f1:`FOUNDED`]->(o1:`Organisation`) | [r_f1, o1]], [(n)-[r_e1:`EMPLOYED_BY`]->(o1) | [r_e1, o1]], [(n)-[r_l1:`LIVES_AT`]->(l1:`Location`) | [r_l1, l1, [[(l1)<-[r_l2:`LIVES_AT`]-(p2:`Person`) | [r_l2, p2]]]]]]\n----\n\n== Expressions\n\nYou can parse expressions, too.\nThey can be used to enrich queries in many places, for example as conditions or properties.\n\n=== Usable datatypes\n\n[[expressions-input-datatypes]]\n.Input\n[source,cypher]\n----\n1\n-1\n0XF\n0xF\n-0xE\n010\n-010\n1.1\n3.14\n6.022E23\n6.022e+24.0\nTRUE\ntrue\nTrue\nfAlse\nFALSE\n----\n\n[[expressions-output-datatypes]]\n.Output\n[source,cypher]\n----\n1\n-1\n15\n15\n-14\n8\n-8\n1.1\n3.14\n6.022E23\n6.022E24\ntrue\ntrue\ntrue\nfalse\nfalse\n----\n\n=== Operators and conditions\n\n[[expressions-input-0]]\n.Input\n[source,cypher]\n----\n+1\na++b\n+-1\n-1\n--1\nNOT true\n2+2\n2-2\n2*2\n2/2\n2%2\n2^2\nn.f <> 1\nn.f != 1\nn.f = 1\nn.f <= 1\nn.f >= 1\nn.f < 1\nn.f > 1\nn.f =~ '.*'\nn.f ends with \"foo\"\nn.f starts with 'foo'\nn.f contains 'foo'\nn.f is NULL\nactor{.name, .realName, movies: collect(movie{.title, .year})}\nl[1]\nl[1..2]\n[x IN range(0,10) WHERE x % 2 = 0 | x^3 ]\n[x IN range(0,10) WHERE x % 2 = 0 ]\n[x IN range(0,10) | x^3 ]\n[(a)-->(b) WHERE b:Movie | b.released]\na xor b\n----\n\n[[expressions-output-0]]\n.Rendered output\n[source,cypher]\n----\n+1\n(a + +b)\n+-1\n-1\n--1\nNOT (true)\n(2 + 2)\n(2 - 2)\n(2 * 2)\n(2 / 2)\n(2 % 2)\n2^2\nn.f <> 1\nn.f <> 1\nn.f = 1\nn.f <= 1\nn.f >= 1\nn.f < 1\nn.f > 1\nn.f =~ '.*'\nn.f ENDS WITH 'foo'\nn.f STARTS WITH 'foo'\nn.f CONTAINS 'foo'\nn.f IS NULL\nactor{.name, .realName, movies: collect(movie{.title, .year})}\nl[1]\nl[1..2]\n[x IN range(0, 10) WHERE (x % 2) = 0 | x^3]\n[x IN range(0, 10) WHERE (x % 2) = 0]\n[x IN range(0, 10) | x^3]\n[(a)-->(b) WHERE b:`Movie` | b.released]\n(a XOR b)\n----\n\n=== Quantified path patterns\n\nMost queries in this test are from Finbar Goods blog post https://medium.com/neo4j/getting-from-denmark-hill-to-gatwick-airport-with-quantified-path-patterns-bed38da27ca1[\"Getting From Denmark Hill to Gatwick Airport With Quantified Path Patterns].\nFinbar provides the UK Railway dataset at https://github.com/dogofbrian/ukrailway, in case you wanna load the data and follow the examples.\n\n[[qpp-input-qpp]]\n.Input\n[source,cypher,separated=true,alwaysEscape=false]\n----\nMATCH (:Station)--()<--(m WHERE m.departs > time('12:00'))-->()-[:NEXT]->(n) RETURN *;\nMATCH ((n:A)-[:R]->(:B) WHERE EXISTS { (n)-->+(:X) }){2,3};\nMATCH (n:Station {name: 'London Euston'})<-[:CALLS_AT]-(s1:Stop)\n  -[:NEXT]->(s2:Stop)-[:CALLS_AT]->(:Station {name: 'Coventry'})\n  <-[:CALLS_AT]-(s3:Stop)-[:NEXT]->(s4:Stop)-[:CALLS_AT]->(n)\nRETURN s1.departs+'-'+s2.departs AS outbound,\n  s3.departs+'-'+s4.departs AS `return`;\nMATCH (:Station { name: 'Denmark Hill' })<-[:X]-(d:Stop)\n      ((:Stop)-[:NEXT]->(:Stop)){1,3}\n      (a:Stop)-[:Y]->(:Station { name: 'Clapham Junction' })\nRETURN d.departs AS departureTime, a.arrives AS arrivalTime;\nmatch (:A) (()-[r:R]->()){2,3} (:B) return *;\nmatch (:A) (()-[r:R]->())+ (:B) return *;\nmatch (:A) (()-[r:R]->())* (:B) return *;\nMATCH p = ((person:`Person`)-[:`DIRECTED`]->(movie:`Movie`)) WHERE person.name = 'Walt Disney' RETURN p;\nMATCH ((:Station {name: 'Denmark Hill'})-[l:LINK]-(s:Station)){1,4} RETURN *;\nMATCH p = (:Station {name: 'Denmark Hill'}) (()-[link:LINK]-())+ (:Station {name: 'Gatwick Airport'})\nRETURN reduce(acc = 0.0, l IN link | round(acc + l.distance, 2)) AS total,\n  [n in nodes(p) | n.name] AS stations\nORDER BY total\nLIMIT 1;\nMATCH p = (:Station {name: 'Denmark Hill'}) (()-[link:LINK]-()){1,28}\n            (:Station {name: 'Gatwick Airport'})\nRETURN size(relationships(p)) AS numStations, count(*) AS numRoutes\nORDER BY numStations;\nMATCH (gtw:Station {name: 'Gatwick Airport'})\nMATCH p = (:Station {name: 'Denmark Hill'})\n          ((l)-[link:LINK]-(r) WHERE point.distance(r.location, gtw.location)\n             - point.distance(l.location, gtw.location) < 1000)+ (gtw)\nRETURN reduce(acc = 0.0, l IN link | round(acc + l.distance, 2)) AS total,\n [n in nodes(p) | n.name] AS stations\nORDER BY total\nLIMIT 1;\nMATCH (dmk:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(l1a:CallingPoint)-[:NEXT]->+\n        (l1b)-[:CALLS_AT]->(x:Station)<-[:CALLS_AT]-(l2a:CallingPoint)-[:NEXT]->+\n        (l2b)-[:CALLS_AT]->(gtw:Station {name: 'Gatwick Airport'});\nMATCH (:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(r:CallingPoint)\n(()-[:NEXT]->())+\n(:CallingPoint)-[:CALLS_AT]->(:Station {name: 'Gatwick Airport'})\nRETURN r.routeName AS route;\nMATCH (dmk:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(l1:CallingPoint)\n(()-[:NEXT]->())+\n(:CallingPoint)-[:CALLS_AT]->(x:Station)<-[:CALLS_AT]-(l2:CallingPoint)\n(()-[:NEXT]->())+\n(:CallingPoint)-[:CALLS_AT]->(gtw:Station {name: 'Gatwick Airport'})\nRETURN l1.routeName AS leg1, x.name AS changeAt, l2.routeName AS leg2;\nMATCH (dmk:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(l1a:CallingPoint)-[:NEXT]->+\n        (l1b)-[:CALLS_AT]->(x:Station)<-[:CALLS_AT]-(l2a:CallingPoint)-[:NEXT]->+\n        (l2b)-[:CALLS_AT]->(gtw:Station {name: 'Gatwick Airport'})\nMATCH (l1a)-[:HAS]->(s1:Stop)-[:NEXT]->+(s2)<-[:HAS]-(l1b)\n        WHERE time('09:30') < s1.departs < time('10:00')\nMATCH (l2a)-[:HAS]->(s3:Stop)-[:NEXT]->+(s4)<-[:HAS]-(l2b)\n        WHERE s2.arrives < s3.departs < s2.arrives + duration('PT15M')\nRETURN s1.departs AS leg1Departs, s2.arrives AS leg1Arrives, x.name AS changeAt,\n         s3.departs AS leg2Departs, s4.arrives AS leg2Arrive,\n         duration.between(s1.departs, s4.arrives).minutes AS journeyTime\nORDER BY leg2Arrive\nLIMIT 5;\nMATCH (dmk:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(l1a:CallingPoint)\n        (()-[:NEXT]->(n)\n          WHERE NOT EXISTS { (n)-[:CALLS_AT]->(:Station:LondonGroup) })+\n        (l1b)-[:CALLS_AT]->(x:Station)<-[:CALLS_AT]-(l2a:CallingPoint)\n        (()-[:NEXT]->(m)\n          WHERE NOT EXISTS { (m)-[:CALLS_AT]->(:Station:LondonGroup) })+\n        (l2b)-[:CALLS_AT]->(gtw:Station {name: 'Gatwick Airport'})\nMATCH (l1a)-[:HAS]->(s1:Stop)-[:NEXT]->+(s2)<-[:HAS]-(l1b)\nWHERE time('09:30') < s1.departs < time('10:00')\nMATCH (l2a)-[:HAS]->(s3:Stop)-[:NEXT]->+(s4)<-[:HAS]-(l2b)\nWHERE s2.arrives < s3.departs < s2.arrives + duration('PT15M')\nRETURN s1.departs AS leg1Departs, s2.arrives AS leg1Arrives, x.name AS changeAt,\n        s3.departs AS leg2Departs, s4.arrives AS leg2Arrive,\n        duration.between(s1.departs, s4.arrives).minutes AS journeyTime\nORDER BY leg2Arrive\nLIMIT 5;\n----\n\n[[qpp-output-qpp]]\n.Input\n[source,cypher,separated=true,alwaysEscape=false]\n----\nMATCH (:Station)--()<--(m WHERE m.departs > time('12:00'))-->()-[:NEXT]->(n) RETURN *;\nMATCH ((n:A)-[:R]->(:B) WHERE EXISTS { (n)-->+(:X) }){2,3};\nMATCH (n:Station {name: 'London Euston'})<-[:CALLS_AT]-(s1:Stop)-[:NEXT]->(s2:Stop)-[:CALLS_AT]->(:Station {name: 'Coventry'})<-[:CALLS_AT]-(s3:Stop)-[:NEXT]->(s4:Stop)-[:CALLS_AT]->(n) RETURN ((s1.departs + '-') + s2.departs) AS outbound, ((s3.departs + '-') + s4.departs) AS return;\nMATCH (:Station {name: 'Denmark Hill'})<-[:X]-(d:Stop)\n      ((:Stop)-[:NEXT]->(:Stop)){1,3}\n      (a:Stop)-[:Y]->(:Station {name: 'Clapham Junction'})\nRETURN d.departs AS departureTime, a.arrives AS arrivalTime;\nMATCH (:A) (()-[r:R]->()){2,3} (:B) RETURN *;\nMATCH (:A) (()-[r:R]->())+ (:B) RETURN *;\nMATCH (:A) (()-[r:R]->())* (:B) RETURN *;\nMATCH p = ((person:Person)-[:DIRECTED]->(movie:Movie)) WHERE person.name = 'Walt Disney' RETURN p;\nMATCH ((:Station {name: 'Denmark Hill'})-[l:LINK]-(s:Station)){1,4} RETURN *;\nMATCH p = (:Station {name: 'Denmark Hill'}) (()-[link:LINK]-())+ (:Station {name: 'Gatwick Airport'})\nRETURN reduce(acc = 0.0, l IN link | round((acc + l.distance), 2)) AS total,\n[n IN nodes(p) | n.name] AS stations\nORDER BY total ASC\nLIMIT 1;\nMATCH p = (:Station {name: 'Denmark Hill'}) (()-[link:LINK]-()){1,28} (:Station {name: 'Gatwick Airport'})\nRETURN size(relationships(p)) AS numStations, count(*) AS numRoutes\nORDER BY numStations ASC;\nMATCH (gtw:Station {name: 'Gatwick Airport'})\nMATCH p = (:Station {name: 'Denmark Hill'}) ((l)-[link:LINK]-(r) WHERE (point.distance(r.location, gtw.location) - point.distance(l.location, gtw.location)) < 1000)+ (gtw)\nRETURN reduce(acc = 0.0, l IN link | round((acc + l.distance), 2)) AS total,\n[n IN nodes(p) | n.name] AS stations\nORDER BY total ASC\nLIMIT 1;\nMATCH (dmk:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(l1a:CallingPoint)-[:NEXT]->+(l1b)-[:CALLS_AT]->(x:Station)<-[:CALLS_AT]-(l2a:CallingPoint)-[:NEXT]->+(l2b)-[:CALLS_AT]->(gtw:Station {name: 'Gatwick Airport'});\nMATCH (:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(r:CallingPoint)\n(()-[:NEXT]->())+\n(:CallingPoint)-[:CALLS_AT]->(:Station {name: 'Gatwick Airport'})\nRETURN r.routeName AS route;\nMATCH (dmk:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(l1:CallingPoint)\n(()-[:NEXT]->())+\n(:CallingPoint)-[:CALLS_AT]->(x:Station)<-[:CALLS_AT]-(l2:CallingPoint)\n(()-[:NEXT]->())+\n(:CallingPoint)-[:CALLS_AT]->(gtw:Station {name: 'Gatwick Airport'})\nRETURN l1.routeName AS leg1, x.name AS changeAt, l2.routeName AS leg2;\nMATCH (dmk:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(l1a:CallingPoint)-[:NEXT]->+(l1b)-[:CALLS_AT]->(x:Station)<-[:CALLS_AT]-(l2a:CallingPoint)-[:NEXT]->+(l2b)-[:CALLS_AT]->(gtw:Station {name: 'Gatwick Airport'})\nMATCH (l1a)-[:HAS]->(s1:Stop)-[:NEXT]->+(s2)<-[:HAS]-(l1b)\nWHERE (time('09:30') < s1.departs AND s1.departs < time('10:00'))\nMATCH (l2a)-[:HAS]->(s3:Stop)-[:NEXT]->+(s4)<-[:HAS]-(l2b)\nWHERE (s2.arrives < s3.departs AND s3.departs < (s2.arrives + duration('PT15M')))\nRETURN s1.departs AS leg1Departs, s2.arrives AS leg1Arrives, x.name AS changeAt,\ns3.departs AS leg2Departs, s4.arrives AS leg2Arrive,\nduration.between(s1.departs, s4.arrives).minutes AS journeyTime\nORDER BY leg2Arrive ASC\nLIMIT 5;\nMATCH (dmk:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(l1a:CallingPoint)\n(()-[:NEXT]->(n)\nWHERE NOT (EXISTS { (n)-[:CALLS_AT]->(:Station:LondonGroup) }))+\n(l1b)-[:CALLS_AT]->(x:Station)<-[:CALLS_AT]-(l2a:CallingPoint)\n(()-[:NEXT]->(m)\nWHERE NOT (EXISTS { (m)-[:CALLS_AT]->(:Station:LondonGroup) }))+\n(l2b)-[:CALLS_AT]->(gtw:Station {name: 'Gatwick Airport'})\nMATCH (l1a)-[:HAS]->(s1:Stop)-[:NEXT]->+(s2)<-[:HAS]-(l1b)\nWHERE (time('09:30') < s1.departs AND s1.departs < time('10:00'))\nMATCH (l2a)-[:HAS]->(s3:Stop)-[:NEXT]->+(s4)<-[:HAS]-(l2b)\nWHERE (s2.arrives < s3.departs AND s3.departs < (s2.arrives + duration('PT15M')))\nRETURN s1.departs AS leg1Departs, s2.arrives AS leg1Arrives, x.name AS changeAt,\ns3.departs AS leg2Departs, s4.arrives AS leg2Arrive,\nduration.between(s1.departs, s4.arrives).minutes AS journeyTime\nORDER BY leg2Arrive ASC\nLIMIT 5;\n----\n\n=== Unsupported operations\n\nThe following operations are unsupported:\n\n[[unsupported-input-f]]\n.Input\n[source,cypher,separated=true]\n----\nGRANT ROLE poolImpersonation TO pool;\nSHOW TRANSACTION YIELD *;\nUNWIND range(1, 10) AS i\n    CALL { WITH i\n      UNWIND [1, 2] AS j\n      CREATE (n:N {i: i, j: j})\n    } IN TRANSACTIONS;\nCREATE INDEX node_index_name FOR (n:Person) ON (n.surname);\nCREATE INDEX rel_index_name FOR ()-[r:KNOWS]-() ON (r.since);\nCREATE INDEX FOR (n:Person) ON n.firstname;\nCREATE CONSTRAINT FOR (book:Book) REQUIRE book.isbn IS UNIQUE\nCREATE INDEX node_index_name IF NOT EXISTS FOR (n:Person) ON (n.surname);\nSHOW INDEXES;\nCREATE CONSTRAINT constraint_name FOR (book:Book) REQUIRE book.isbn IS UNIQUE;\nDROP CONSTRAINT constraint_name;\nSHOW CONSTRAINTS;\nREVOKE GRANT TRAVERSE ON HOME GRAPH NODES Post FROM regularUsers;\nSHOW FUNCTIONS;\nSHOW PROCEDURES;\nCREATE ROLE myrole;\nRENAME ROLE mysecondrole TO mythirdrole;\nSHOW ROLES;\nGRANT ROLE myrole TO bob;\nREVOKE ROLE myrole FROM bob;\nDROP ROLE mythirdrole;\nSHOW CURRENT USER;\nSHOW USERS;\nCREATE USER jake SET PASSWORD 'abc' CHANGE REQUIRED SET STATUS SUSPENDED SET HOME DATABASE anotherDb;\nRENAME USER jake TO bob;\nALTER USER bob SET PASSWORD 'abc123' CHANGE NOT REQUIRED SET STATUS ACTIVE;\nALTER CURRENT USER SET PASSWORD FROM 'abc123' TO '123xyz';\nALTER CURRENT USER SET PASSWORD FROM $oldPassword TO $newPassword;\nALTER USER bob SET STATUS ACTIVE;\nSHOW DATABASES;\nCREATE DATABASE customers;\nALTER DATABASE customers SET ACCESS READ ONLY;\nSTOP DATABASE customers;\nSTART DATABASE customers;\nDROP DATABASE customers;\nCREATE DATABASE slow WAIT 5 SECONDS;\nCREATE ALIAS `northwind` FOR DATABASE `northwind-graph-2020`;\nALTER ALIAS `northwind` SET DATABASE TARGET `northwind-graph-2021`;\nDROP ALIAS `northwind` FOR DATABASE;\nCREATE DATABASE d01;\nSHOW DATABASE d01 YIELD serverID, databaseID, lastCommittedTxn, replicationLag;\nUSE foo;\nCREATE USER jake SET ENCRYPTED PASSWORD '1,6d57a5e0b3317055454e455f96c98c750c77fb371f3f0634a1b8ff2a55c5b825,190ae47c661e0668a0c8be8a21ff78a4a34cdf918cae3c407e907b73932bd16c' CHANGE NOT REQUIRED SET STATUS ACTIVE IF NOT EXISTS;\nDROP USER f;\nGRANT read privilege ON HOME GRAPH TO myrole;\nDENY read privilege ON HOME GRAPH TO myrole;\nREVOKE read privilege ON HOME GRAPH TO myrole;\nREVOKE GRANT read privilege ON HOME GRAPH TO myrole;\nREVOKE DENY read privilege ON HOME GRAPH TO myrole;\nGRANT ASSIGN PRIVILEGE ON DBMS TO role;\nDENY ASSIGN PRIVILEGE ON DBMS TO role;\nREVOKE ASSIGN PRIVILEGE ON DBMS TO role;\nGRANT ALL DATABASE PRIVILEGES ON DATABASE neo4j TO databaseAdminUsers;\n----\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-parent</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-parser</artifactId>\n\n\t<name>Neo4j Cypher DSL (Parser)</name>\n\t<description>Building on top of the Neo4j 4.4 JavaCC parsers it provides a way from Cypher to Cypher-DSL Ast.</description>\n\n\t<properties>\n\t\t<covered-ratio-complexity>0.68</covered-ratio-complexity>\n\t\t<sonar.coverage.jacoco.xmlReportPaths>${basedir}/../${aggregate.report.dir}</sonar.coverage.jacoco.xmlReportPaths>\n\t</properties>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-dsl-bom</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-javacc-parser</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.opencsv</groupId>\n\t\t\t<artifactId>opencsv</artifactId>\n\t\t\t<version>${opencsv.version}</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.asciidoctor</groupId>\n\t\t\t<artifactId>asciidoctorj</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.assertj</groupId>\n\t\t\t<artifactId>assertj-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j.test</groupId>\n\t\t\t<artifactId>neo4j-harness</artifactId>\n\t\t\t<version>${neo4j.version}</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-simple</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<useModulePath>false</useModulePath>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<!-- This forces the failsafe plugin not to use the byte-code manipulated classes in the full bundle (yep, I know, it kinda\n\t\t\t\tdefeats the purpose of \"IT\", thank you very much), otherwise JaCoCo won't be able to actually recognize that classes have\n\t\t\t\tbeen tested. Sure I might be as well just rename the tests and treat them as unit, ok, but at some time another developer\n\t\t\t\twill add an integration tests and things will joyfully not work, so better have it here.\n\t\t\t\tAh and yes, please don't change the order, otherwise the source plugin now thinks things have been attached twice.\n\t\t\t\tWhat a madness. -->\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-failsafe-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<classesDirectory>${project.build.outputDirectory}</classesDirectory>\n\t\t\t\t\t<classpathDependencyExcludes>\n\t\t\t\t\t\t<classpathDependencyExclude>org.neo4j:neo4j-cypher-dsl-parser</classpathDependencyExclude>\n\t\t\t\t\t</classpathDependencyExcludes>\n\t\t\t\t\t<useModulePath>false</useModulePath>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<!--\n\t\t\tDon't change the order of maven-javadoc-plugin, maven-shade-plugin, moditect-maven-plugin:\n\t\t\t- JavaDoc can't live with a module-info.java that requires automatic modules and mess up class- and module path\n\t\t\t  (JavaCC Cypher parser and dependencies are only automatic ones)\n\t\t\t- Even if we would have one, the shade plugin would nuke it without an option to say \"yes, this is ok, we know what we are doing\"\n\t\t\t- Therefor, we must add it \"manually\" with moditect\n\t\t\t- That must however happen after javadoc plugin did his work. The resulting javadoc could be better, because right now\n\t\t\t  it is based on the non-modular source version, whereas a proper one would be perfectly possible if the plugin\n\t\t\t  just would allow to specify class- and module-path manually and independent.\n\t\t\t-->\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>attach-javadocs</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>jar</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-shade-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>shade</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<artifactSet>\n\t\t\t\t\t\t\t\t<includes>\n\t\t\t\t\t\t\t\t\t<include>org.neo4j:cypher-ast-factory</include>\n\t\t\t\t\t\t\t\t\t<include>org.neo4j:neo4j-cypher-javacc-parser</include>\n\t\t\t\t\t\t\t\t\t<include>org.neo4j:cypher-parser-common</include>\n\t\t\t\t\t\t\t\t</includes>\n\t\t\t\t\t\t\t</artifactSet>\n\t\t\t\t\t\t\t<relocations>\n\t\t\t\t\t\t\t\t<relocation>\n\t\t\t\t\t\t\t\t\t<pattern>org.neo4j.cypher.internal</pattern>\n\t\t\t\t\t\t\t\t\t<shadedPattern>org.neo4j.cypherdsl.parser.internal</shadedPattern>\n\t\t\t\t\t\t\t\t</relocation>\n\t\t\t\t\t\t\t</relocations>\n\t\t\t\t\t\t\t<createSourcesJar>true</createSourcesJar>\n\t\t\t\t\t\t\t<filters>\n\t\t\t\t\t\t\t\t<filter>\n\t\t\t\t\t\t\t\t\t<artifact>*:*</artifact>\n\t\t\t\t\t\t\t\t\t<excludes>\n\t\t\t\t\t\t\t\t\t\t<exclude>module-info.class</exclude>\n\t\t\t\t\t\t\t\t\t\t<exclude>library.properties</exclude>\n\t\t\t\t\t\t\t\t\t\t<exclude>LICENSE.txt</exclude>\n\t\t\t\t\t\t\t\t\t\t<exclude>rootdoc.txt</exclude>\n\t\t\t\t\t\t\t\t\t</excludes>\n\t\t\t\t\t\t\t\t</filter>\n\t\t\t\t\t\t\t\t<filter>\n\t\t\t\t\t\t\t\t\t<artifact>org.neo4j:cypher-ast-factory</artifact>\n\t\t\t\t\t\t\t\t\t<excludes>\n\t\t\t\t\t\t\t\t\t\t<exclude>META-INF/**/*</exclude>\n\t\t\t\t\t\t\t\t\t</excludes>\n\t\t\t\t\t\t\t\t</filter>\n\t\t\t\t\t\t\t\t<filter>\n\t\t\t\t\t\t\t\t\t<artifact>org.neo4j:neo4j-cypher-javacc-parser</artifact>\n\t\t\t\t\t\t\t\t\t<excludes>\n\t\t\t\t\t\t\t\t\t\t<exclude>META-INF/**/*</exclude>\n\t\t\t\t\t\t\t\t\t</excludes>\n\t\t\t\t\t\t\t\t</filter>\n\t\t\t\t\t\t\t\t<filter>\n\t\t\t\t\t\t\t\t\t<artifact>org.neo4j:cypher-parser-common</artifact>\n\t\t\t\t\t\t\t\t\t<excludes>\n\t\t\t\t\t\t\t\t\t\t<exclude>META-INF/**/*</exclude>\n\t\t\t\t\t\t\t\t\t</excludes>\n\t\t\t\t\t\t\t\t</filter>\n\t\t\t\t\t\t\t</filters>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.moditect</groupId>\n\t\t\t\t<artifactId>moditect-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>add-module-infos</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>add-module-info</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<overwriteExistingFiles>true</overwriteExistingFiles>\n\t\t\t\t\t\t\t<module>\n\t\t\t\t\t\t\t\t<moduleInfoSource><![CDATA[module org.neo4j.cypherdsl.parser {\n\n\t\t\t\t\t\t\t\t\t\trequires transitive org.apiguardian.api;\n\t\t\t\t\t\t\t\t\t\trequires transitive org.neo4j.cypherdsl.core;\n\n\t\t\t\t\t\t\t\t\t\t// Those are shaded\n\t\t\t\t\t\t\t\t\t\t// requires org.neo4j.cypher.internal.parser;\n\t\t\t\t\t\t\t\t\t\t// requires org.neo4j.cypher.internal.parser.javacc;\n\t\t\t\t\t\t\t\t\t\t// requires org.neo4j.cypher.internal.ast.factory;\n\n\t\t\t\t\t\t\t\t\t\texports org.neo4j.cypherdsl.parser;\n\t\t\t\t\t\t\t\t\t}]]></moduleInfoSource>\n\t\t\t\t\t\t\t</module>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-resources-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>copy-resources</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>copy-resources</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>generate-test-resources</phase>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<outputDirectory>${basedir}/target/test-classes</outputDirectory>\n\t\t\t\t\t\t\t<resources>\n\t\t\t\t\t\t\t\t<resource>\n\t\t\t\t\t\t\t\t\t<directory>${project.basedir}</directory>\n\t\t\t\t\t\t\t\t\t<includes>\n\t\t\t\t\t\t\t\t\t\t<include>README.adoc</include>\n\t\t\t\t\t\t\t\t\t</includes>\n\t\t\t\t\t\t\t\t</resource>\n\t\t\t\t\t\t\t</resources>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.github.siom79.japicmp</groupId>\n\t\t\t\t<artifactId>japicmp-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\t<reporting>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-checkstyle-plugin</artifactId>\n\t\t\t\t<reportSets>\n\t\t\t\t\t<reportSet>\n\t\t\t\t\t\t<reports>\n\t\t\t\t\t\t\t<report>checkstyle</report>\n\t\t\t\t\t\t</reports>\n\t\t\t\t\t</reportSet>\n\t\t\t\t</reportSets>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</reporting>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/module-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * @author Michael J. Simons\n * @since 2023.0.0\n */\n@SuppressWarnings( {\"requires-automatic\"}) // Neo4j Cypher Parser\nmodule org.neo4j.cypherdsl.parser {\n\n\trequires transitive org.apiguardian.api;\n\trequires transitive org.neo4j.cypherdsl.core;\n\n\trequires org.neo4j.cypher.internal.parser;\n\trequires org.neo4j.cypher.internal.parser.javacc;\n\trequires org.neo4j.cypher.internal.ast.factory;\n\trequires org.neo4j.gql.status;\n\n\texports org.neo4j.cypherdsl.parser;\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/CyperDslParseException.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.io.Serial;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A runtime exception wrapping checked parsing exception into a sensible exception\n * hierarchy.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = STABLE, since = \"2021.3.0\")\npublic final class CyperDslParseException extends RuntimeException {\n\n\t@Serial\n\tprivate static final long serialVersionUID = -3188559145717360828L;\n\n\t/**\n\t * Creates a new Cypher-DSL specific exception with the given cause.\n\t * @param cause original cause, being wrapped in a {@link RuntimeException}.\n\t */\n\tpublic CyperDslParseException(Throwable cause) {\n\t\tsuper(cause);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/CypherDslASTExceptionFactory.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.ASTExceptionFactory;\nimport org.neo4j.gqlstatus.ErrorGqlStatusObject;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Implementation of the exception factory for Neo4j 5s JavaCC based parser.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = INTERNAL, since = \"2021.3.0\")\nenum CypherDslASTExceptionFactory implements ASTExceptionFactory {\n\n\tINSTANCE;\n\n\t@Override\n\tpublic Exception syntaxException(ErrorGqlStatusObject errorGqlStatusObject, String s, List<String> list,\n\t\t\tException e, int i, int i1, int i2) {\n\t\treturn new RuntimeException(errorGqlStatusObject.getMessage());\n\t}\n\n\t@Override\n\tpublic Exception syntaxException(String got, List<String> expected, Exception source, int offset, int line,\n\t\t\tint column) {\n\t\treturn new RuntimeException(source.getMessage());\n\t}\n\n\t@Override\n\tpublic Exception syntaxException(Exception source, int offset, int line, int column) {\n\t\treturn new RuntimeException(source.getMessage());\n\t}\n\n\t@Override\n\tpublic Exception syntaxException(ErrorGqlStatusObject errorGqlStatusObject, Exception e, int i, int i1, int i2) {\n\t\treturn new RuntimeException(errorGqlStatusObject.getMessage());\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/CypherDslASTFactory.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.EnumSet;\nimport java.util.Iterator;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.function.UnaryOperator;\nimport java.util.stream.Stream;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypher.internal.ast.factory.ASTFactory;\nimport org.neo4j.cypher.internal.ast.factory.ASTFactory.NULL;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.AccessType;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.ActionType;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.CallInTxsOnErrorBehaviourType;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.ConstraintType;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.CreateIndexTypes;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.HintIndexType;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.ParameterType;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.ParserCypherTypeName;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.ParserNormalForm;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.ParserTrimSpecification;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.ScopeType;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.ShowCommandFilterTypes;\nimport org.neo4j.cypher.internal.parser.common.ast.factory.SimpleEither;\nimport org.neo4j.cypherdsl.core.Case;\nimport org.neo4j.cypherdsl.core.Clause;\nimport org.neo4j.cypherdsl.core.Clauses;\nimport org.neo4j.cypherdsl.core.Comparison;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.ExposesRelationships;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.Finish;\nimport org.neo4j.cypherdsl.core.FunctionInvocation;\nimport org.neo4j.cypherdsl.core.Hint;\nimport org.neo4j.cypherdsl.core.KeyValueMapEntry;\nimport org.neo4j.cypherdsl.core.Labels;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.MapProjection;\nimport org.neo4j.cypherdsl.core.MergeAction;\nimport org.neo4j.cypherdsl.core.NamedPath;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.NodeLabel;\nimport org.neo4j.cypherdsl.core.Operation;\nimport org.neo4j.cypherdsl.core.Operator;\nimport org.neo4j.cypherdsl.core.Parameter;\nimport org.neo4j.cypherdsl.core.PatternComprehension;\nimport org.neo4j.cypherdsl.core.PatternElement;\nimport org.neo4j.cypherdsl.core.PatternSelector;\nimport org.neo4j.cypherdsl.core.Property;\nimport org.neo4j.cypherdsl.core.PropertyLookup;\nimport org.neo4j.cypherdsl.core.QuantifiedPathPattern;\nimport org.neo4j.cypherdsl.core.Relationship;\nimport org.neo4j.cypherdsl.core.RelationshipPattern;\nimport org.neo4j.cypherdsl.core.Return;\nimport org.neo4j.cypherdsl.core.Set;\nimport org.neo4j.cypherdsl.core.SortItem;\nimport org.neo4j.cypherdsl.core.Statement;\nimport org.neo4j.cypherdsl.core.StringLiteral;\nimport org.neo4j.cypherdsl.core.SymbolicName;\nimport org.neo4j.cypherdsl.core.Where;\nimport org.neo4j.cypherdsl.core.ast.TypedSubtree;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * An implementation of Neo4j's {@link ASTFactory} that creates Cypher-DSL AST elements\n * that can be used for creating conditions, patterns to match etc.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = INTERNAL, since = \"2021.3.0\")\nfinal class CypherDslASTFactory implements\n\t\tASTFactory<Statements, Statement, Statement, Clause, Finish, Return, Expression, List<Expression>, SortItem, PatternElement, NodeAtom, PathAtom, PathLength, Clause, Expression, Expression, Expression, Hint, Expression, Labels, Expression, Parameter<?>, Expression, Property, Expression, Clause, Statement, Statement, Statement, Clause, Where, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, InputPosition, EntityType, QuantifiedPathPattern.Quantifier, PatternAtom, DatabaseName, PatternSelector, NULL, PatternElement> {\n\n\tprivate static CypherDslASTFactory instanceFromDefaultOptions;\n\n\tprivate final Options options;\n\n\tprivate CypherDslASTFactory(Options options) {\n\t\tthis.options = options;\n\t}\n\n\tstatic CypherDslASTFactory getInstance(Options options) {\n\n\t\tCypherDslASTFactory instance;\n\n\t\tif (options != null && !options.areDefault()) {\n\t\t\tinstance = new CypherDslASTFactory(options);\n\t\t}\n\t\telse {\n\t\t\tinstance = instanceFromDefaultOptions;\n\t\t\tif (instance == null) {\n\t\t\t\tsynchronized (CypherDslASTFactory.class) {\n\t\t\t\t\tinstance = instanceFromDefaultOptions;\n\t\t\t\t\tif (instance == null) {\n\t\t\t\t\t\tinstanceFromDefaultOptions = new CypherDslASTFactory(\n\t\t\t\t\t\t\t\tOptional.ofNullable(options).orElseGet(Options::defaultOptions));\n\t\t\t\t\t\tinstance = instanceFromDefaultOptions;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn instance;\n\t}\n\n\tstatic void isInstanceOf(Class<?> type, Object obj, String message) {\n\t\tif (type == null) {\n\t\t\tthrow new IllegalArgumentException(\"Type to check against must not be null\");\n\t\t}\n\t\tif (!type.isInstance(obj)) {\n\t\t\tthrow new IllegalArgumentException(message);\n\t\t}\n\t}\n\n\tprivate static void notNull(Object object, String message) {\n\t\tif (object == null) {\n\t\t\tthrow new IllegalArgumentException(message);\n\t\t}\n\t}\n\n\tprivate static SymbolicName assertSymbolicName(Expression v) {\n\n\t\tif (v == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tisInstanceOf(SymbolicName.class, v,\n\t\t\t\t\"An invalid type has been generated where a SymbolicName was required. Generated type was \"\n\t\t\t\t\t\t+ v.getClass().getName());\n\t\treturn (SymbolicName) v;\n\t}\n\n\tprivate String[] computeFinalLabelList(LabelParsedEventType event, List<StringPos<InputPosition>> inputLabels) {\n\n\t\treturn (inputLabels != null) ? this.options.getLabelFilter()\n\t\t\t.apply(event, inputLabels.stream().map(v -> v.string).toList())\n\t\t\t.toArray(new String[0]) : new String[0];\n\t}\n\n\tprivate String[] computeFinalTypeList(TypeParsedEventType event, Labels inputTypes) {\n\n\t\tif (inputTypes == null) {\n\t\t\treturn new String[0];\n\t\t}\n\n\t\tif ((inputTypes.isNegated() && inputTypes.getValue().size() > 1)\n\t\t\t\t|| inputTypes.getType() == Labels.Type.CONJUNCTION) {\n\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\"Expressions for relationship types are not supported in Cypher-DSL\");\n\t\t}\n\n\t\tCollection<String> types = inputTypes.getStaticValues();\n\n\t\treturn this.options.getTypeFilter().apply(event, types).toArray(new String[0]);\n\t}\n\n\tprivate <T extends Expression> T applyCallbacksFor(ExpressionCreatedEventType type, T newExpression) {\n\t\treturn applyCallbacksFor(type, List.of(newExpression)).get(0);\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tprivate <T extends Expression> List<T> applyCallbacksFor(ExpressionCreatedEventType type, List<T> expressions) {\n\n\t\tvar callbacks = this.options.getOnNewExpressionCallbacks().getOrDefault(type, List.of());\n\t\tif (callbacks.isEmpty()) {\n\t\t\treturn expressions;\n\t\t}\n\n\t\tvar chainedCallbacks = callbacks.stream().reduce(Function.identity(), Function::andThen);\n\t\treturn expressions.stream().map(e -> (T) chainedCallbacks.apply(e)).toList();\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tprivate <T extends Visitable> T applyCallbacksFor(InvocationCreatedEventType type, T newExpression) {\n\n\t\tvar callbacks = this.options.getOnNewInvocationCallbacks().getOrDefault(type, List.of());\n\t\tif (callbacks.isEmpty()) {\n\t\t\treturn newExpression;\n\t\t}\n\n\t\tVisitable result = newExpression;\n\t\tfor (UnaryOperator<Visitable> callback : callbacks) {\n\t\t\tresult = callback.apply(result);\n\t\t}\n\t\treturn (T) result;\n\t}\n\n\t@Override\n\tpublic Statements statements(List<Statement> statements) {\n\t\treturn new Statements(statements);\n\t}\n\n\t@Override\n\tpublic Statement newSingleQuery(InputPosition p, List<Clause> clauses) {\n\t\treturn newSingleQuery(clauses);\n\t}\n\n\t@Override\n\tpublic Statement newSingleQuery(List<Clause> clauses) {\n\t\treturn Statement.of(clauses);\n\t}\n\n\t@Override\n\tpublic Statement newUnion(InputPosition p, Statement lhs, Statement rhs, boolean all) {\n\t\tif (all) {\n\t\t\treturn Cypher.unionAll(lhs, rhs);\n\t\t}\n\t\telse {\n\t\t\treturn Cypher.union(lhs, rhs);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Clause directUseClause(InputPosition p, DatabaseName databaseName) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Clause functionUseClause(InputPosition p, Expression function) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Finish newFinishClause(InputPosition p) {\n\t\treturn Finish.create();\n\t}\n\n\t@Override\n\tpublic List<Expression> newReturnItems(InputPosition p, boolean returnAll, List<Expression> returnItems) {\n\t\tvar finalReturnItems = returnItems;\n\n\t\tif (returnAll) {\n\t\t\tfinalReturnItems = Stream.concat(Stream.of(Cypher.asterisk()), finalReturnItems.stream()).toList();\n\t\t}\n\n\t\tif (finalReturnItems.isEmpty()) {\n\t\t\tif (!returnAll) {\n\t\t\t\tthrow new IllegalArgumentException(\"Cannot return nothing.\");\n\t\t\t}\n\t\t\tfinalReturnItems = Collections.singletonList(Cypher.asterisk());\n\t\t}\n\t\treturn finalReturnItems;\n\t}\n\n\t@Override\n\tpublic Return newReturnClause(InputPosition p, boolean distinct, List<Expression> returnItems,\n\t\t\tList<SortItem> sortItems, InputPosition orderPos, Expression skip, InputPosition skipPosition,\n\t\t\tExpression limit, InputPosition limitPosition) {\n\n\t\treturn this.options.getReturnClauseFactory()\n\t\t\t.apply(new ReturnDefinition(distinct, returnItems, sortItems, skip, limit));\n\t}\n\n\t@Override\n\tpublic Expression newReturnItem(InputPosition p, Expression e, Expression v) {\n\n\t\tvar s = assertSymbolicName(v);\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_RETURN_ITEM, e.as(s));\n\t}\n\n\t@Override\n\tpublic Expression newReturnItem(InputPosition p, Expression e, int eStartOffset, int eEndOffset) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_RETURN_ITEM, e);\n\t}\n\n\t@Override\n\tpublic SortItem orderDesc(InputPosition p, Expression e) {\n\t\treturn e.descending();\n\t}\n\n\t@Override\n\tpublic SortItem orderAsc(InputPosition p, Expression e) {\n\t\treturn e.ascending();\n\t}\n\n\t@Override\n\tpublic Clause withClause(InputPosition p, Return returnClause, Where where) {\n\t\treturn Clauses.with(returnClause, where);\n\t}\n\n\t@Override\n\tpublic Clause matchClause(InputPosition p, boolean optional, NULL matchMode, List<PatternElement> patternElements,\n\t\t\tInputPosition patternPos, List<Hint> hints, Where whereIn) {\n\n\t\tvar patternElementCallbacks = this.options.getOnNewPatternElementCallbacks()\n\t\t\t.getOrDefault(PatternElementCreatedEventType.ON_MATCH, List.of());\n\t\tList<PatternElement> openForTransformation = new ArrayList<>();\n\t\tfor (PatternElement patternElement : patternElements) {\n\t\t\tif (patternElement instanceof NodeAtom nodeAtom) {\n\t\t\t\topenForTransformation.add(nodeAtom.value());\n\t\t\t}\n\t\t\telse {\n\t\t\t\topenForTransformation.add(patternElement);\n\t\t\t}\n\t\t}\n\t\tvar transformedPatternElements = transformIfPossible(patternElementCallbacks, openForTransformation);\n\n\t\treturn this.options.getMatchClauseFactory()\n\t\t\t.apply(new MatchDefinition(optional, transformedPatternElements, whereIn, hints));\n\t}\n\n\tprivate List<PatternElement> transformIfPossible(List<UnaryOperator<PatternElement>> callbacks,\n\t\t\tList<PatternElement> patternElements) {\n\t\tif (callbacks.isEmpty()) {\n\t\t\treturn patternElements;\n\t\t}\n\n\t\t@SuppressWarnings(\"squid:S4276\") // The function is needed due to the assigment\n\t\t// below\n\t\tvar transformer = Function.<PatternElement>identity();\n\t\tfor (UnaryOperator<PatternElement> callback : callbacks) {\n\t\t\ttransformer = transformer.andThen(callback);\n\t\t}\n\t\treturn patternElements.stream().map(transformer).filter(Objects::nonNull).toList();\n\t}\n\n\t@Override\n\tpublic Hint usingIndexHint(InputPosition p, Expression v, String labelOrRelType, List<String> properties,\n\t\t\tboolean seekOnly, HintIndexType indexType) {\n\n\t\t// We build nodes here. As of now, the node isn't used anyway, but only the label\n\t\t// will be used down further the AST.\n\t\t// It is easier than introduce a new common abstraction of label and relationship\n\t\t// type (probably\n\t\t// in line with the decision made for the parser)\n\t\tvar node = Cypher.node(labelOrRelType).named(assertSymbolicName(v));\n\t\treturn Hint.useIndexFor(seekOnly, properties.stream().map(node::property).toArray(Property[]::new));\n\t}\n\n\t@Override\n\tpublic Hint usingJoin(InputPosition p, List<Expression> joinVariables) {\n\n\t\treturn Hint.useJoinOn(\n\t\t\t\tjoinVariables.stream().map(CypherDslASTFactory::assertSymbolicName).toArray(SymbolicName[]::new));\n\t}\n\n\t@Override\n\tpublic Hint usingScan(InputPosition p, Expression v, String label) {\n\n\t\tvar s = assertSymbolicName(v);\n\t\t// Same note applies as with usingIndexHint in regard to relationships\n\t\treturn Hint.useScanFor(Cypher.node(label).named(s));\n\t}\n\n\t@Override\n\tpublic Clause createClause(InputPosition p, List<PatternElement> patternElements) {\n\n\t\tvar callbacks = this.options.getOnNewPatternElementCallbacks()\n\t\t\t.getOrDefault(PatternElementCreatedEventType.ON_CREATE, List.of());\n\t\treturn Clauses.create(transformIfPossible(callbacks,\n\t\t\t\tpatternElements.stream().map(v -> (v instanceof NodeAtom n) ? n.value() : v).toList()));\n\t}\n\n\t@Override\n\tpublic Clause insertClause(InputPosition p, List<PatternElement> patternElements) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Clause setClause(InputPosition p, List<Expression> setItems) {\n\t\treturn Clauses.set(setItems);\n\t}\n\n\t@Override\n\tpublic Operation setProperty(Property property, Expression value) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_SET_PROPERTY, property.to(value));\n\t}\n\n\t@Override\n\tpublic Expression setDynamicProperty(Expression dynamicProperty, Expression value) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_SET_PROPERTY, Cypher.set(dynamicProperty, value));\n\t}\n\n\t@Override\n\tpublic Operation setVariable(Expression v, Expression value) {\n\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_SET_VARIABLE, Cypher.set(v, value));\n\t}\n\n\t@Override\n\tpublic Operation addAndSetVariable(Expression v, Expression value) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_ADD_AND_SET_VARIABLE, Cypher.mutate(v, value));\n\t}\n\n\t@Override\n\tpublic Expression setLabels(Expression v, List<StringPos<InputPosition>> values, List<Expression> dynamicLabels,\n\t\t\tboolean containsIs) {\n\n\t\tvar s = assertSymbolicName(v);\n\t\tOperation operation;\n\t\tif (values.isEmpty() && !(dynamicLabels == null || dynamicLabels.isEmpty())) {\n\t\t\tvar labels = Cypher.allLabels(dynamicLabels.get(0));\n\t\t\tfor (var e : dynamicLabels.subList(1, dynamicLabels.size())) {\n\t\t\t\tlabels = labels.conjunctionWith(Cypher.allLabels(e));\n\t\t\t}\n\t\t\toperation = Cypher.setLabel(Cypher.anyNode(s), labels);\n\t\t}\n\t\telse {\n\t\t\tvar labels = computeFinalLabelList(LabelParsedEventType.ON_SET, values);\n\t\t\toperation = Cypher.setLabel(Cypher.anyNode(s), labels);\n\t\t}\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_SET_LABELS, operation);\n\t}\n\n\t@Override\n\tpublic Clause removeClause(InputPosition p, List<Expression> removeItems) {\n\t\treturn Clauses.remove(removeItems);\n\t}\n\n\t@Override\n\tpublic Expression removeProperty(Property property) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_REMOVE_PROPERTY, property);\n\t}\n\n\t@Override\n\tpublic Expression removeDynamicProperty(Expression dynamicProperty) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_REMOVE_PROPERTY, dynamicProperty);\n\t}\n\n\t@Override\n\tpublic Expression removeLabels(Expression v, List<StringPos<InputPosition>> values, List<Expression> dynamicLabels,\n\t\t\tboolean containsIs) {\n\n\t\tvar s = assertSymbolicName(v);\n\t\tvar labels = computeFinalLabelList(LabelParsedEventType.ON_REMOVE, values);\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_REMOVE_LABELS,\n\t\t\t\tCypher.removeLabel(Cypher.anyNode(s), labels));\n\t}\n\n\t@Override\n\tpublic Clause deleteClause(InputPosition p, boolean detach, List<Expression> expressions) {\n\t\treturn Clauses.delete(detach, applyCallbacksFor(ExpressionCreatedEventType.ON_DELETE_ITEM, expressions));\n\t}\n\n\t@Override\n\tpublic Clause unwindClause(InputPosition p, Expression e, Expression v) {\n\t\treturn Clauses.unwind(e, assertSymbolicName(v));\n\t}\n\n\t@Override\n\tpublic Clause mergeClause(InputPosition p, PatternElement patternElementIn, List<Clause> setClauses,\n\t\t\tList<MergeActionType> actionTypes, List<InputPosition> positions) {\n\n\t\tvar patternElement = (patternElementIn instanceof NodeAtom n) ? n.value() : patternElementIn;\n\t\tvar mergeActions = new ArrayList<MergeAction>();\n\t\tif (setClauses != null && !setClauses.isEmpty() && actionTypes != null && !actionTypes.isEmpty()) {\n\n\t\t\tvar iteratorClauses = setClauses.iterator();\n\t\t\tvar iteratorTypes = actionTypes.iterator();\n\t\t\twhile (iteratorClauses.hasNext() && iteratorTypes.hasNext()) {\n\t\t\t\tvar type = iteratorTypes.next();\n\t\t\t\tswitch (type) {\n\t\t\t\t\tcase OnCreate ->\n\t\t\t\t\t\tmergeActions.add(MergeAction.of(MergeAction.Type.ON_CREATE, (Set) iteratorClauses.next()));\n\t\t\t\t\tcase OnMatch ->\n\t\t\t\t\t\tmergeActions.add(MergeAction.of(MergeAction.Type.ON_MATCH, (Set) iteratorClauses.next()));\n\t\t\t\t\tdefault -> throw new IllegalArgumentException(\"Unsupported MergeActionType: \" + type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvar callbacks = this.options.getOnNewPatternElementCallbacks()\n\t\t\t.getOrDefault(PatternElementCreatedEventType.ON_MERGE, List.of());\n\t\treturn Clauses.merge(transformIfPossible(callbacks, List.of(patternElement)), mergeActions);\n\t}\n\n\t@Override\n\tpublic Clause callClause(InputPosition p, InputPosition namespacePosition, InputPosition procedureNamePosition,\n\t\t\tInputPosition procedureResultPosition, List<String> namespace, String name, List<Expression> arguments,\n\t\t\tboolean yieldAll, List<Expression> resultItems, Where where, boolean optional) {\n\t\tvar intermediateResult = Clauses.callClause(namespace, name, arguments,\n\t\t\t\t(!yieldAll || (resultItems != null)) ? resultItems : List.of(Cypher.asterisk()), where);\n\t\tif (optional) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot render optional call clause\");\n\t\t}\n\t\treturn applyCallbacksFor(InvocationCreatedEventType.ON_CALL, intermediateResult);\n\t}\n\n\t@Override\n\tpublic Expression callResultItem(InputPosition p, String name, Expression alias) {\n\t\tvar finalName = Cypher.name(name);\n\t\tif (alias != null) {\n\t\t\treturn finalName.as(assertSymbolicName(alias));\n\t\t}\n\t\treturn finalName;\n\t}\n\n\t@Override\n\tpublic PatternElement patternWithSelector(PatternSelector patternSelector, PatternElement patternPart) {\n\t\treturn NamedPath.select(patternSelector, patternPart);\n\t}\n\n\t@Override\n\tpublic PatternElement namedPattern(Expression v, PatternElement patternElement) {\n\t\treturn Cypher.path(assertSymbolicName(v)).definedBy(patternElement);\n\t}\n\n\t@Override\n\tpublic PatternElement shortestPathPattern(InputPosition p, PatternElement patternElement) {\n\n\t\tisInstanceOf(RelationshipPattern.class, patternElement,\n\t\t\t\t\"Only relationship patterns are supported for the shortestPath function.\");\n\n\t\treturn new ExpressionAsPatternElementWrapper(\n\t\t\t\tFunctionInvocation.create(PatternElementFunctions.SHORTEST_PATH, patternElement));\n\t}\n\n\t@Override\n\tpublic PatternElement allShortestPathsPattern(InputPosition p, PatternElement patternElement) {\n\n\t\tisInstanceOf(RelationshipPattern.class, patternElement,\n\t\t\t\t\"Only relationship patterns are supported for the allShortestPaths function.\");\n\n\t\treturn new ExpressionAsPatternElementWrapper(\n\t\t\t\tFunctionInvocation.create(PatternElementFunctions.ALL_SHORTEST_PATHS, patternElement));\n\t}\n\n\t@Override\n\tpublic PatternElement pathPattern(PatternElement patternElement) {\n\t\treturn patternElement;\n\t}\n\n\t@Override\n\tpublic PatternElement insertPathPattern(List<PatternAtom> patternAtoms) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@SuppressWarnings(\"squid:S3776\") // Yep, it's complex\n\t@Override\n\tpublic PatternElement patternElement(List<PatternAtom> atoms) {\n\n\t\tif (atoms.isEmpty()) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot create a PatternElement from an empty list of patterns.\");\n\t\t}\n\n\t\tif (atoms.size() == 1 && atoms.get(0) instanceof ParenthesizedPathPatternAtom atom) {\n\t\t\treturn atom.asPatternElement();\n\t\t}\n\n\t\tList<PatternElement> patternElements = new ArrayList<>();\n\t\tNodeAtom lastNodeAtom = null;\n\t\tPathAtom lastPathAtom = null;\n\t\tExposesRelationships<?> relationshipPattern = null;\n\t\tList<PatternElement> patternList = null;\n\t\tfor (PatternAtom atom : atoms) {\n\n\t\t\tif (atom instanceof ParenthesizedPathPatternAtom specificAtom) {\n\t\t\t\tif (lastNodeAtom != null) {\n\t\t\t\t\tpatternElements.add(lastNodeAtom.value());\n\t\t\t\t}\n\t\t\t\tif (relationshipPattern != null) {\n\t\t\t\t\tpatternElements.add((PatternElement) relationshipPattern);\n\t\t\t\t}\n\t\t\t\tif (patternList != null) {\n\t\t\t\t\tpatternElements.add(new PatternList(patternList));\n\t\t\t\t}\n\t\t\t\tlastNodeAtom = null;\n\t\t\t\tlastPathAtom = null;\n\t\t\t\trelationshipPattern = null;\n\t\t\t\tpatternList = null;\n\t\t\t\tpatternElements.add(specificAtom.asPatternElement());\n\t\t\t}\n\t\t\telse if (atom instanceof NodeAtom nodeAtom) {\n\t\t\t\tif (relationshipPattern != null) {\n\t\t\t\t\trelationshipPattern = lastPathAtom.asRelationshipBetween(relationshipPattern, nodeAtom,\n\t\t\t\t\t\t\tthis.options.isAlwaysCreateRelationshipsLTR());\n\t\t\t\t}\n\t\t\t\telse if (lastNodeAtom == null) {\n\t\t\t\t\tlastNodeAtom = nodeAtom;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\trelationshipPattern = lastNodeAtom.value();\n\t\t\t\t\tlastNodeAtom = null;\n\t\t\t\t\t// Will be added to the pattern elements either on the occurrence of a\n\t\t\t\t\t// parenthesized pattern or\n\t\t\t\t\t// after iterating all atoms.\n\t\t\t\t\trelationshipPattern = lastPathAtom.asRelationshipBetween(relationshipPattern, nodeAtom,\n\t\t\t\t\t\t\tthis.options.isAlwaysCreateRelationshipsLTR());\n\t\t\t\t\tif ((lastPathAtom.getDirection() == Relationship.Direction.RTL || patternList != null)\n\t\t\t\t\t\t\t&& this.options.isAlwaysCreateRelationshipsLTR()) {\n\t\t\t\t\t\tif (patternList == null) {\n\t\t\t\t\t\t\tpatternList = new ArrayList<>();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpatternList.add(((PatternElement) relationshipPattern));\n\t\t\t\t\t\trelationshipPattern = null;\n\t\t\t\t\t\tlastNodeAtom = nodeAtom;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (atom instanceof PathAtom pathAtom) {\n\t\t\t\tlastPathAtom = pathAtom;\n\t\t\t}\n\t\t}\n\n\t\tif (relationshipPattern == null && patternList != null && patternList.size() == 1\n\t\t\t\t&& patternList.get(0) instanceof RelationshipPattern singleListItem) {\n\t\t\trelationshipPattern = singleListItem;\n\t\t\tpatternList = null;\n\t\t}\n\n\t\tif (relationshipPattern != null) {\n\t\t\tpatternElements.add((PatternElement) relationshipPattern);\n\t\t}\n\t\telse if (patternList != null) {\n\t\t\tpatternElements.add(new PatternList(patternList));\n\t\t}\n\t\telse if (lastNodeAtom != null) {\n\t\t\tpatternElements.add(lastNodeAtom.value());\n\t\t}\n\n\t\treturn (patternElements.size() == 1) ? patternElements.get(0) : new PatternJuxtaposition(patternElements);\n\t}\n\n\t@Override\n\tpublic PatternSelector anyPathSelector(String count, InputPosition countPosition, InputPosition position) {\n\t\tif (count != null) {\n\t\t\tthrow new UnsupportedOperationException(\"ANY with k is not supported\");\n\t\t}\n\t\treturn PatternSelector.any();\n\t}\n\n\t@Override\n\tpublic PatternSelector allPathSelector(InputPosition position) {\n\t\treturn PatternSelector.allShortest();\n\t}\n\n\t@Override\n\tpublic PatternSelector anyShortestPathSelector(String count, InputPosition countPosition, InputPosition position) {\n\t\tvar k = 1;\n\t\tif (count != null) {\n\t\t\tk = Integer.parseInt(count);\n\t\t}\n\t\treturn PatternSelector.shortestK(k);\n\t}\n\n\t@Override\n\tpublic PatternSelector allShortestPathSelector(InputPosition position) {\n\t\treturn PatternSelector.allShortest();\n\t}\n\n\t@Override\n\tpublic PatternSelector shortestGroupsSelector(String count, InputPosition countPosition, InputPosition position) {\n\t\tvar k = 1;\n\t\tif (count != null) {\n\t\t\tk = Integer.parseInt(count);\n\t\t}\n\t\treturn PatternSelector.shortestKGroups(k);\n\t}\n\n\tprivate static Collection<Labels.Value> flatten(Labels labels) {\n\n\t\tvar values = new LinkedHashSet<Labels.Value>();\n\t\tflatten0(labels, values);\n\t\treturn values;\n\t}\n\n\tprivate static void flatten0(Labels l, java.util.Set<Labels.Value> values) {\n\t\tif (l == null) {\n\t\t\treturn;\n\t\t}\n\t\tvar current = l.getType();\n\t\tflatten0(l.getLhs(), values);\n\t\tif (current == Labels.Type.LEAF || (l.getLhs() == null && l.getRhs() == null\n\t\t\t\t&& EnumSet.of(Labels.Type.COLON_CONJUNCTION, Labels.Type.COLON_DISJUNCTION).contains(l.getType()))) {\n\t\t\tvalues.addAll(l.getValue());\n\t\t}\n\t\tflatten0(l.getRhs(), values);\n\t}\n\n\t@Override\n\tpublic NodeAtom nodePattern(InputPosition p, Expression v, Labels labels, Expression properties,\n\t\t\tExpression predicate) {\n\n\t\tNode node;\n\t\tif (labels == null) {\n\t\t\tnode = Cypher.anyNode();\n\t\t}\n\t\telse if (labels.getType() == Labels.Type.COLON_CONJUNCTION\n\t\t\t\t|| (labels.getType() == Labels.Type.LEAF && labels.getValue() != null)) {\n\t\t\tvar values = flatten(labels);\n\n\t\t\tList<String> staticLabels = new ArrayList<>();\n\t\t\tint dynamicLabelsCnt = 0;\n\t\t\tfor (var value : values) {\n\t\t\t\tif (value.modifier() == Labels.Modifier.STATIC && value.visitable() instanceof NodeLabel nodeLabel) {\n\t\t\t\t\tstaticLabels.add(nodeLabel.getValue());\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t++dynamicLabelsCnt;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar newConjunctionRequired = dynamicLabelsCnt > 0;\n\t\t\tstaticLabels = List\n\t\t\t\t.copyOf(this.options.getLabelFilter().apply(LabelParsedEventType.ON_NODE_PATTERN, staticLabels));\n\n\t\t\tif (newConjunctionRequired) {\n\t\t\t\tList<Labels.Value> newValues = new ArrayList<>();\n\t\t\t\tfor (var value : values) {\n\t\t\t\t\tif (value.modifier() != Labels.Modifier.STATIC || value.visitable() instanceof NodeLabel nodeLabel\n\t\t\t\t\t\t\t&& staticLabels.contains(nodeLabel.getValue())) {\n\t\t\t\t\t\tnewValues.add(value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnode = Cypher.node(Labels.colonConjunction(newValues));\n\t\t\t}\n\t\t\telse if (staticLabels.isEmpty()) {\n\t\t\t\tnode = Cypher.anyNode();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tnode = Cypher.node(staticLabels.get(0), staticLabels.subList(1, staticLabels.size()));\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tnode = Cypher.node(labels);\n\t\t}\n\n\t\tif (v != null) {\n\t\t\tnode = node.named(assertSymbolicName(v));\n\t\t}\n\t\tif (properties != null) {\n\t\t\tnode = node.withProperties((MapExpression) properties);\n\t\t}\n\t\tif (predicate != null) {\n\t\t\tnode = (Node) node.where(predicate);\n\t\t}\n\t\treturn new NodeAtom(node);\n\t}\n\n\t@Override\n\tpublic PathAtom relationshipPattern(InputPosition p, boolean left, boolean right, Expression v, Labels relTypes,\n\t\t\tPathLength pathLength, Expression properties, Expression predicate) {\n\t\treturn PathAtom.of(assertSymbolicName(v), pathLength, left, right,\n\t\t\t\tcomputeFinalTypeList(TypeParsedEventType.ON_RELATIONSHIP_PATTERN, relTypes), (MapExpression) properties,\n\t\t\t\trelTypes != null && relTypes.isNegated(), predicate);\n\t}\n\n\t@Override\n\tpublic PathLength pathLength(InputPosition p, InputPosition pMin, InputPosition pMax, String minLength,\n\t\t\tString maxLength) {\n\t\treturn PathLength.of(minLength, maxLength);\n\t}\n\n\t@Override\n\tpublic QuantifiedPathPattern.Quantifier intervalPathQuantifier(InputPosition p, InputPosition posLowerBound,\n\t\t\tInputPosition posUpperBound, String lowerBound, String upperBound) {\n\n\t\treturn QuantifiedPathPattern.interval((lowerBound != null) ? Integer.parseInt(lowerBound) : null,\n\t\t\t\t(upperBound != null) ? Integer.parseInt(upperBound) : null);\n\t}\n\n\t@Override\n\tpublic QuantifiedPathPattern.Quantifier fixedPathQuantifier(InputPosition p, InputPosition valuePos, String value) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic QuantifiedPathPattern.Quantifier plusPathQuantifier(InputPosition p) {\n\t\treturn QuantifiedPathPattern.plus();\n\t}\n\n\t@Override\n\tpublic QuantifiedPathPattern.Quantifier starPathQuantifier(InputPosition p) {\n\t\treturn QuantifiedPathPattern.star();\n\t}\n\n\t@Override\n\tpublic NULL repeatableElements(InputPosition p) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL differentRelationships(InputPosition p) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic PatternAtom parenthesizedPathPattern(InputPosition p, PatternElement internalPattern, Expression where,\n\t\t\tQuantifiedPathPattern.Quantifier pathPatternQuantifier) {\n\t\treturn new ParenthesizedPathPatternAtom((RelationshipPattern) internalPattern, pathPatternQuantifier, where);\n\t}\n\n\t@Override\n\tpublic PatternAtom quantifiedRelationship(PathAtom rel, QuantifiedPathPattern.Quantifier pathPatternQuantifier) {\n\t\treturn rel.withQuantifier(pathPatternQuantifier);\n\t}\n\n\t@Override\n\tpublic Clause loadCsvClause(InputPosition p, boolean headers, Expression source, Expression v,\n\t\t\tString fieldTerminator) {\n\n\t\tisInstanceOf(StringLiteral.class, source,\n\t\t\t\t\"Only string literals are supported as source for the LOAD CSV clause.\");\n\t\treturn Clauses.loadCSV(headers, (StringLiteral) source, assertSymbolicName(v), fieldTerminator);\n\t}\n\n\t@Override\n\tpublic Clause foreachClause(InputPosition p, Expression v, Expression list, List<Clause> objects) {\n\t\treturn Clauses.forEach(assertSymbolicName(v), list, objects);\n\t}\n\n\t@Override\n\tpublic Clause subqueryClause(InputPosition p, Statement subquery, NULL inTransactions, boolean scopeAll,\n\t\t\tboolean hasScope, List<Expression> expressions, boolean optional) {\n\t\tif (optional) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot render optional subquery clause\");\n\t\t}\n\t\treturn Clauses.callClause(subquery);\n\t}\n\n\t@Override\n\tpublic NULL subqueryInTransactionsParams(InputPosition p, NULL batchParams, NULL concurrencyParams,\n\t\t\tNULL errorParams, NULL reportParams) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Clause yieldClause(InputPosition p, boolean returnAll, List<Expression> expressions,\n\t\t\tInputPosition returnItemsPosition, List<SortItem> orderBy, InputPosition orderPos, Expression skip,\n\t\t\tInputPosition skipPosition, Expression limit, InputPosition limitPosition, Where where) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Clause showIndexClause(InputPosition p, ShowCommandFilterTypes indexType, Where where, Clause yieldClause) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Clause showConstraintClause(InputPosition p, ShowCommandFilterTypes constraintType, Where where,\n\t\t\tClause yieldClause) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Clause showProcedureClause(InputPosition p, boolean currentUser, String user, Where where,\n\t\t\tClause yieldClause) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Clause showFunctionClause(InputPosition p, ShowCommandFilterTypes functionType, boolean currentUser,\n\t\t\tString user, Where where, Clause yieldClause) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement useGraph(Statement command, Clause useGraph) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement showRoles(InputPosition p, boolean withUsers, boolean showAll, Clause yieldExpr,\n\t\t\tReturn returnWithoutGraph, Where where) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement grantRoles(InputPosition p, List<SimpleEither<StringPos<InputPosition>, Parameter<?>>> roles,\n\t\t\tList<SimpleEither<StringPos<InputPosition>, Parameter<?>>> users) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement revokeRoles(InputPosition p, List<SimpleEither<StringPos<InputPosition>, Parameter<?>>> roles,\n\t\t\tList<SimpleEither<StringPos<InputPosition>, Parameter<?>>> users) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement createUser(InputPosition p, boolean replace, boolean ifNotExists,\n\t\t\tSimpleEither<StringPos<InputPosition>, Parameter<?>> username, Boolean suspended, DatabaseName homeDatabase,\n\t\t\tList<NULL> nulls, List<NULL> systemAuthAttributes) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement dropUser(InputPosition p, boolean ifExists,\n\t\t\tSimpleEither<StringPos<InputPosition>, Parameter<?>> username) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement renameUser(InputPosition p, SimpleEither<StringPos<InputPosition>, Parameter<?>> fromUserName,\n\t\t\tSimpleEither<StringPos<InputPosition>, Parameter<?>> toUserName, boolean ifExists) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement setOwnPassword(InputPosition p, Expression currentPassword, Expression newPassword) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL auth(String provider, List<NULL> nulls, InputPosition p) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL authId(InputPosition s, Expression id) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL password(InputPosition p, Expression password, boolean encrypted) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL passwordChangeRequired(InputPosition p, boolean changeRequired) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement alterUser(InputPosition p, boolean ifExists,\n\t\t\tSimpleEither<StringPos<InputPosition>, Parameter<?>> username, Boolean suspended, DatabaseName homeDatabase,\n\t\t\tboolean removeHome, List<NULL> nulls, List<NULL> systemAuthAttributes, boolean removeAllAuth,\n\t\t\tList<Expression> removeAuths) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Expression passwordExpression(Parameter<?> password) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Expression passwordExpression(InputPosition s, InputPosition e, String password) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement showUsers(InputPosition p, Clause yieldExpr, Return returnWithoutGraph, Where where,\n\t\t\tboolean withAuth) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement showCurrentUser(InputPosition p, Clause yieldExpr, Return returnWithoutGraph, Where where) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement showSupportedPrivileges(InputPosition p, Clause yieldExpr, Return returnWithoutGraph,\n\t\t\tWhere where) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement showAllPrivileges(InputPosition p, boolean asCommand, boolean asRevoke, Clause yieldExpr,\n\t\t\tReturn returnWithoutGraph, Where where) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement showRolePrivileges(InputPosition p,\n\t\t\tList<SimpleEither<StringPos<InputPosition>, Parameter<?>>> roles, boolean asCommand, boolean asRevoke,\n\t\t\tClause yieldExpr, Return returnWithoutGraph, Where where) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement showUserPrivileges(InputPosition p,\n\t\t\tList<SimpleEither<StringPos<InputPosition>, Parameter<?>>> users, boolean asCommand, boolean asRevoke,\n\t\t\tClause yieldExpr, Return returnWithoutGraph, Where where) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement grantPrivilege(InputPosition p, List<SimpleEither<StringPos<InputPosition>, Parameter<?>>> roles,\n\t\t\tNULL privilege) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement denyPrivilege(InputPosition p, List<SimpleEither<StringPos<InputPosition>, Parameter<?>>> roles,\n\t\t\tNULL privilege) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement revokePrivilege(InputPosition p, List<SimpleEither<StringPos<InputPosition>, Parameter<?>>> roles,\n\t\t\tNULL privilege, boolean revokeGrant, boolean revokeDeny) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t// The database options are quite different options than ours ;)\n\t@SuppressWarnings(\"HiddenField\")\n\t@Override\n\tpublic Statement createDatabase(InputPosition p, boolean replace, DatabaseName databaseName, boolean ifNotExists,\n\t\t\tNULL aNull, SimpleEither<Map<String, Expression>, Parameter<?>> options,\n\t\t\tSimpleEither<Integer, Parameter<?>> topologyPrimaries,\n\t\t\tSimpleEither<Integer, Parameter<?>> topologySecondaries) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement createCompositeDatabase(InputPosition p, boolean replace, DatabaseName compositeDatabaseName,\n\t\t\tboolean ifNotExists, SimpleEither<Map<String, Expression>, Parameter<?>> databaseOptions, NULL aNull) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement dropDatabase(InputPosition p, DatabaseName databaseName, boolean ifExists, boolean composite,\n\t\t\tboolean aliasAction, boolean dumpData, NULL wait) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@SuppressWarnings(\"HiddenField\") // The database options are quite different options\n\t// than ours ;)\n\t@Override\n\tpublic Statement alterDatabase(InputPosition p, DatabaseName databaseName, boolean ifExists, AccessType accessType,\n\t\t\tSimpleEither<Integer, Parameter<?>> topologyPrimaries,\n\t\t\tSimpleEither<Integer, Parameter<?>> topologySecondaries, Map<String, Expression> options,\n\t\t\tjava.util.Set<String> optionsToRemove, NULL aNull) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement showDatabase(InputPosition p, NULL scope, Clause yieldExpr, Return returnWithoutGraph,\n\t\t\tWhere where) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement startDatabase(InputPosition p, DatabaseName databaseName, NULL wait) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement stopDatabase(InputPosition p, DatabaseName databaseName, NULL wait) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL databaseScope(InputPosition p, DatabaseName databaseName, boolean isDefault, boolean isHome) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement dropAlias(InputPosition p, DatabaseName aliasName, boolean ifExists) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement showAliases(InputPosition p, DatabaseName aliasName, Clause yieldExpr, Return returnWithoutGraph,\n\t\t\tWhere where) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic void addDeprecatedIdentifierUnicodeNotification(InputPosition p, Character character, String identifier) {\n\t}\n\n\t@Override\n\tpublic NULL wait(boolean wait, long seconds) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic DatabaseName databaseName(InputPosition p, List<String> names) {\n\t\tif (names.isEmpty()) {\n\t\t\tthrow new IllegalArgumentException(\"No database name\");\n\t\t}\n\t\tif (names.size() == 1) {\n\t\t\treturn new DatabaseName(Cypher.literalOf(names.get(0)));\n\t\t}\n\t\treturn new DatabaseName(Cypher.literalOf(names));\n\t}\n\n\t@Override\n\tpublic DatabaseName databaseName(Parameter<?> param) {\n\t\treturn new DatabaseName(param);\n\t}\n\n\t@Override\n\tpublic Statement createLocalDatabaseAlias(InputPosition p, boolean replace, DatabaseName aliasName,\n\t\t\tDatabaseName targetName, boolean ifNotExists,\n\t\t\tSimpleEither<Map<String, Expression>, Parameter<?>> properties) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement createRemoteDatabaseAlias(InputPosition p, boolean replace, DatabaseName aliasName,\n\t\t\tDatabaseName targetName, boolean ifNotExists, SimpleEither<String, Parameter<?>> url,\n\t\t\tSimpleEither<StringPos<InputPosition>, Parameter<?>> username, Expression password,\n\t\t\tSimpleEither<Map<String, Expression>, Parameter<?>> driverSettings,\n\t\t\tSimpleEither<Map<String, Expression>, Parameter<?>> properties) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement alterLocalDatabaseAlias(InputPosition p, DatabaseName aliasName, DatabaseName targetName,\n\t\t\tboolean ifExists, SimpleEither<Map<String, Expression>, Parameter<?>> properties) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement alterRemoteDatabaseAlias(InputPosition p, DatabaseName aliasName, DatabaseName targetName,\n\t\t\tboolean ifExists, SimpleEither<String, Parameter<?>> url,\n\t\t\tSimpleEither<StringPos<InputPosition>, Parameter<?>> username, Expression password,\n\t\t\tSimpleEither<Map<String, Expression>, Parameter<?>> driverSettings,\n\t\t\tSimpleEither<Map<String, Expression>, Parameter<?>> properties) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Expression newVariable(InputPosition p, String name) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_NEW_VARIABLE, Cypher.name(name));\n\t}\n\n\t@Override\n\tpublic Parameter<?> newParameter(InputPosition p, Expression v, ParameterType type) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_NEW_PARAMETER, parameterFromSymbolicName(v));\n\t}\n\n\t@Override\n\tpublic Parameter<?> newParameter(InputPosition p, String v, ParameterType type) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_NEW_PARAMETER,\n\t\t\t\tparameterFromSymbolicName(Cypher.name(v)));\n\t}\n\n\t@Override\n\tpublic Parameter<?> newSensitiveStringParameter(InputPosition p, Expression v) {\n\t\tthrow new UnsupportedOperationException(\"The Cypher-DSL does not support sensitive parameters.\");\n\t}\n\n\t@Override\n\tpublic Parameter<?> newSensitiveStringParameter(InputPosition p, String v) {\n\t\tthrow new UnsupportedOperationException(\"The Cypher-DSL does not support sensitive parameters.\");\n\t}\n\n\tParameter<?> parameterFromSymbolicName(Expression v) {\n\t\tvar symbolicName = assertSymbolicName(v);\n\t\tif (symbolicName == null) {\n\t\t\treturn Cypher.anonParameter(Cypher.literalNull());\n\t\t}\n\n\t\tvar name = symbolicName.getValue();\n\t\treturn this.options.getParameterValues().containsKey(name)\n\t\t\t\t? Cypher.parameter(name, this.options.getParameterValues().get(name)) : Cypher.parameter(name);\n\t}\n\n\t@Override\n\tpublic Expression newDouble(InputPosition p, String image) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_NEW_LITERAL,\n\t\t\t\tCypher.literalOf(Double.parseDouble(image)));\n\t}\n\n\t@Override\n\tpublic Expression newDecimalInteger(InputPosition p, String image, boolean negated) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_NEW_LITERAL,\n\t\t\t\tCypher.literalOf(Long.parseUnsignedLong(image) * (negated ? -1 : 1)));\n\t}\n\n\t@Override\n\tpublic Expression newHexInteger(InputPosition p, String image, boolean negated) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_NEW_LITERAL,\n\t\t\t\tCypher.literalOf(Long.parseUnsignedLong(image.replaceFirst(\"(?i)0x\", \"\"), 16) * (negated ? -1 : 1)));\n\t}\n\n\t@Override\n\tpublic Expression newOctalInteger(InputPosition p, String image, boolean negated) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_NEW_LITERAL,\n\t\t\t\tCypher.literalOf(Long.parseUnsignedLong(image.replaceFirst(\"(?i)0o\", \"\"), 8) * (negated ? -1 : 1)));\n\t}\n\n\t@Override\n\tpublic Expression newString(InputPosition start, InputPosition end, String image) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_NEW_LITERAL, Cypher.literalOf(image));\n\t}\n\n\t@Override\n\tpublic Expression newTrueLiteral(InputPosition p) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_NEW_LITERAL, Cypher.literalTrue());\n\t}\n\n\t@Override\n\tpublic Expression newFalseLiteral(InputPosition p) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_NEW_LITERAL, Cypher.literalFalse());\n\t}\n\n\t@Override\n\tpublic Expression newInfinityLiteral(InputPosition p) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_NEW_LITERAL, InfinityLiteral.INSTANCE);\n\t}\n\n\t@Override\n\tpublic Expression newNaNLiteral(InputPosition p) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_NEW_LITERAL, NaNLiteral.INSTANCE);\n\t}\n\n\t@Override\n\tpublic Expression newNullLiteral(InputPosition p) {\n\t\treturn applyCallbacksFor(ExpressionCreatedEventType.ON_NEW_LITERAL, Cypher.literalNull());\n\t}\n\n\t@Override\n\tpublic Expression listLiteral(InputPosition p, List<Expression> values) {\n\t\treturn Cypher.listOf(values.toArray(new Expression[0]));\n\t}\n\n\t@Override\n\tpublic MapExpression mapLiteral(InputPosition p, List<StringPos<InputPosition>> keys, List<Expression> values) {\n\t\tObject[] keysAndValues = new Object[keys.size() * 2];\n\t\tint i = 0;\n\t\tIterator<Expression> valueIterator = values.iterator();\n\t\tfor (StringPos<InputPosition> key : keys) {\n\t\t\tkeysAndValues[i++] = key.string;\n\t\t\tkeysAndValues[i++] = valueIterator.next();\n\t\t}\n\t\treturn this.options.isCreateSortedMaps() ? Cypher.sortedMapOf(keysAndValues) : Cypher.mapOf(keysAndValues);\n\t}\n\n\t@Override\n\tpublic Property property(Expression subject, StringPos<InputPosition> propertyKeyName) {\n\t\treturn subject.property(propertyKeyName.string);\n\t}\n\n\t@Override\n\tpublic Expression or(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.asCondition().or(rhs.asCondition());\n\t}\n\n\t@Override\n\tpublic Expression xor(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.asCondition().xor(rhs.asCondition());\n\t}\n\n\t@Override\n\tpublic Expression and(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.asCondition().and(rhs.asCondition());\n\t}\n\n\t@Override\n\tpublic Labels labelConjunction(InputPosition p, Labels lhs, Labels rhs, boolean containsIs) {\n\n\t\treturn lhs.and(rhs);\n\t}\n\n\t@Override\n\tpublic Labels labelDisjunction(InputPosition p, Labels lhs, Labels rhs, boolean containsIs) {\n\n\t\treturn lhs.or(rhs);\n\t}\n\n\t@Override\n\tpublic Labels labelNegation(InputPosition p, Labels e, boolean containsIs) {\n\n\t\treturn e.negate();\n\t}\n\n\t@Override\n\tpublic Labels labelWildcard(InputPosition p, boolean containsIs) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Labels labelLeaf(InputPosition p, String e, EntityType entityType, boolean containsIs) {\n\t\treturn Cypher.exactlyLabel(e);\n\t}\n\n\t@Override\n\tpublic Labels labelColonConjunction(InputPosition p, Labels lhs, Labels rhs, boolean containsIs) {\n\t\treturn lhs.conjunctionWith(rhs);\n\t}\n\n\t@Override\n\tpublic Labels labelColonDisjunction(InputPosition p, Labels lhs, Labels rhs, boolean containsIs) {\n\n\t\treturn lhs.disjunctionWith(rhs);\n\t}\n\n\t@Override\n\tpublic Expression labelExpressionPredicate(Expression subject, Labels exp) {\n\n\t\tif (!(subject instanceof SymbolicName symbolicName)) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"Expected an symbolic name to create a label based expression predicate!\");\n\t\t}\n\n\t\treturn Cypher.hasLabelsOrType(symbolicName, exp);\n\t}\n\n\t@Override\n\tpublic Expression ands(List<Expression> exprs) {\n\t\treturn exprs.stream().reduce(Cypher.noCondition(), (l, r) -> l.asCondition().and(r.asCondition()));\n\t}\n\n\t@Override\n\tpublic Expression not(InputPosition p, Expression e) {\n\t\treturn e.asCondition().not();\n\t}\n\n\t@Override\n\tpublic Expression plus(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.add(rhs);\n\t}\n\n\t@Override\n\tpublic Expression minus(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.subtract(rhs);\n\t}\n\n\t@Override\n\tpublic Expression concatenate(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.concat(rhs);\n\t}\n\n\t@Override\n\tpublic Expression multiply(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.multiply(rhs);\n\t}\n\n\t@Override\n\tpublic Expression divide(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.divide(rhs);\n\t}\n\n\t@Override\n\tpublic Expression modulo(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.remainder(rhs);\n\t}\n\n\t@Override\n\tpublic Expression pow(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.pow(rhs);\n\t}\n\n\t@Override\n\tpublic Expression unaryPlus(Expression e) {\n\t\treturn Cypher.plus(e);\n\t}\n\n\t@Override\n\tpublic Expression unaryPlus(InputPosition inputPosition, Expression expression) {\n\t\treturn Cypher.plus(expression);\n\t}\n\n\t@Override\n\tpublic Expression unaryMinus(InputPosition inputPosition, Expression expression) {\n\t\treturn Cypher.minus(expression);\n\t}\n\n\t@Override\n\tpublic Expression eq(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.eq(rhs);\n\t}\n\n\t@Override\n\tpublic Expression neq(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.ne(rhs);\n\t}\n\n\t@Override\n\tpublic Expression neq2(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.ne(rhs);\n\t}\n\n\t@Override\n\tpublic Expression lte(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.lte(rhs);\n\t}\n\n\t@Override\n\tpublic Expression gte(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.gte(rhs);\n\t}\n\n\t@Override\n\tpublic Expression lt(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.lt(rhs);\n\t}\n\n\t@Override\n\tpublic Expression gt(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.gt(rhs);\n\t}\n\n\t@Override\n\tpublic Expression regeq(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.matches(rhs);\n\t}\n\n\t@Override\n\tpublic Expression startsWith(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.startsWith(rhs);\n\t}\n\n\t@Override\n\tpublic Expression endsWith(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.endsWith(rhs);\n\t}\n\n\t@Override\n\tpublic Expression contains(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.contains(rhs);\n\t}\n\n\t@Override\n\tpublic Expression in(InputPosition p, Expression lhs, Expression rhs) {\n\t\treturn lhs.in(rhs);\n\t}\n\n\t@Override\n\tpublic Expression isNull(InputPosition p, Expression e) {\n\t\treturn e.isNull();\n\t}\n\n\t@Override\n\tpublic Expression isNotNull(InputPosition p, Expression e) {\n\t\treturn e.isNotNull();\n\t}\n\n\t@Override\n\tpublic Expression isTyped(InputPosition p, Expression e, ParserCypherTypeName typeName) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Expression isNotTyped(InputPosition p, Expression e, ParserCypherTypeName typeName) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Expression isNormalized(InputPosition p, Expression e, ParserNormalForm normalForm) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Expression isNotNormalized(InputPosition p, Expression e, ParserNormalForm normalForm) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Expression listLookup(Expression list, Expression index) {\n\t\treturn Cypher.valueAt(list, index);\n\t}\n\n\t@Override\n\tpublic Expression listSlice(InputPosition p, Expression list, Expression start, Expression end) {\n\t\treturn Cypher.subList(list, start, end);\n\t}\n\n\t@Override\n\tpublic Expression newCountStar(InputPosition p) {\n\t\treturn Cypher.count(Cypher.asterisk());\n\t}\n\n\t@Override\n\tpublic Expression functionInvocation(InputPosition p, InputPosition functionNamePosition, List<String> namespace,\n\t\t\tString name, boolean distinct, List<Expression> arguments, boolean calledFromUseClause) {\n\n\t\tString[] parts = new String[namespace.size() + 1];\n\t\tfor (int i = 0; i < namespace.size(); i++) {\n\t\t\tparts[i] = namespace.get(i);\n\t\t}\n\t\tparts[parts.length - 1] = name;\n\t\tvar expression = Cypher.call(parts).withArgs(arguments.toArray(Expression[]::new)).asFunction(distinct);\n\t\treturn applyCallbacksFor(InvocationCreatedEventType.ON_INVOCATION, expression);\n\t}\n\n\t@Override\n\tpublic Expression listComprehension(InputPosition p, Expression v, Expression list, Expression where,\n\t\t\tExpression projection) {\n\n\t\tvar in = Cypher.listWith(assertSymbolicName(v)).in(list);\n\t\tif (where != null) {\n\t\t\tvar ongoingComprehension = in.where(where.asCondition());\n\t\t\tif (projection != null) {\n\t\t\t\treturn ongoingComprehension.returning(projection);\n\t\t\t}\n\t\t\treturn ongoingComprehension.returning();\n\t\t}\n\t\treturn in.returning(projection);\n\t}\n\n\t@Override\n\tpublic Expression patternComprehension(InputPosition p, InputPosition relationshipPatternPosition, Expression v,\n\t\t\tPatternElement patternElement, Expression where, Expression projection) {\n\n\t\tPatternComprehension.OngoingDefinitionWithoutReturn ongoingDefinitionWithPattern;\n\t\tif (patternElement instanceof RelationshipPattern relationshipPattern) {\n\t\t\tif (v != null) {\n\t\t\t\tongoingDefinitionWithPattern = Cypher\n\t\t\t\t\t.listBasedOn(Cypher.path(assertSymbolicName(v)).definedBy(relationshipPattern));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tongoingDefinitionWithPattern = Cypher.listBasedOn(relationshipPattern);\n\t\t\t}\n\t\t}\n\t\telse if (patternElement instanceof NamedPath namedPath) {\n\t\t\tongoingDefinitionWithPattern = Cypher.listBasedOn(namedPath);\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"Cannot build a pattern comprehension around \" + patternElement.getClass().getSimpleName());\n\t\t}\n\t\tif (where != null) {\n\t\t\tongoingDefinitionWithPattern = ((PatternComprehension.OngoingDefinitionWithPattern) ongoingDefinitionWithPattern)\n\t\t\t\t.where(where.asCondition());\n\t\t}\n\n\t\treturn ongoingDefinitionWithPattern.returning(projection);\n\t}\n\n\t@Override\n\tpublic Expression reduceExpression(InputPosition p, Expression acc, Expression accExpr, Expression v,\n\t\t\tExpression list, Expression innerExpr) {\n\n\t\tvar variable = assertSymbolicName(v);\n\t\tif (variable == null) {\n\t\t\tthrow new IllegalArgumentException(\"A variable to be reduced must be present.\");\n\t\t}\n\t\treturn Cypher.reduce(variable)\n\t\t\t.in(list)\n\t\t\t.map(innerExpr)\n\t\t\t.accumulateOn(assertSymbolicName(acc))\n\t\t\t.withInitialValueOf(accExpr);\n\t}\n\n\t@Override\n\tpublic Expression allExpression(InputPosition p, Expression v, Expression list, Expression where) {\n\n\t\tnotNull(where, \"all(...) requires a WHERE predicate\");\n\t\treturn Cypher.all(assertSymbolicName(v)).in(list).where(where.asCondition());\n\t}\n\n\t@Override\n\tpublic Expression anyExpression(InputPosition p, Expression v, Expression list, Expression where) {\n\n\t\tnotNull(where, \"any(...) requires a WHERE predicate\");\n\t\treturn Cypher.any(assertSymbolicName(v)).in(list).where(where.asCondition());\n\t}\n\n\t@Override\n\tpublic Expression noneExpression(InputPosition p, Expression v, Expression list, Expression where) {\n\n\t\tnotNull(where, \"none(...) requires a WHERE predicate\");\n\t\treturn Cypher.none(assertSymbolicName(v)).in(list).where(where.asCondition());\n\t}\n\n\t@Override\n\tpublic Expression singleExpression(InputPosition p, Expression v, Expression list, Expression where) {\n\n\t\tnotNull(where, \"single(...) requires a WHERE predicate\");\n\t\treturn Cypher.single(assertSymbolicName(v)).in(list).where(where.asCondition());\n\t}\n\n\t@Override\n\tpublic Expression normalizeExpression(InputPosition p, Expression i, ParserNormalForm normalForm) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Expression trimFunction(InputPosition inputPosition, ParserTrimSpecification parserTrimSpecification,\n\t\t\tExpression expression, Expression expression1) {\n\n\t\tvar call = switch (parserTrimSpecification) {\n\t\t\tcase BOTH -> Cypher.call(\"trim\");\n\t\t\tcase LEADING -> Cypher.call(\"ltrim\");\n\t\t\tcase TRAILING -> Cypher.call(\"rtrim\");\n\t\t};\n\t\treturn call\n\t\t\t.withArgs((expression != null) ? new Expression[] { expression1, expression }\n\t\t\t\t\t: new Expression[] { expression1 })\n\t\t\t.asFunction();\n\t}\n\n\t@Override\n\tpublic Expression patternExpression(InputPosition p, PatternElement patternElement) {\n\n\t\tif (patternElement instanceof ExpressionAsPatternElementWrapper wrapper) {\n\t\t\treturn wrapper.getExpression();\n\t\t}\n\n\t\tif (patternElement instanceof RelationshipPattern relationshipPattern) {\n\t\t\treturn new PatternElementAsExpressionWrapper(relationshipPattern);\n\t\t}\n\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Expression existsExpression(InputPosition p, NULL matchMode, List<PatternElement> patternElements,\n\t\t\tStatement q, Where where) {\n\n\t\tif (q == null) {\n\t\t\treturn Cypher.exists(patternElements, where);\n\t\t}\n\t\telse {\n\t\t\treturn Cypher.exists(q);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Expression countExpression(InputPosition p, NULL matchMode, List<PatternElement> patternElements,\n\t\t\tStatement q, Where where) {\n\n\t\tif (q == null) {\n\t\t\treturn Cypher.count(patternElements, where);\n\t\t}\n\t\telse {\n\t\t\treturn Cypher.count(q);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Expression collectExpression(InputPosition inputPosition, Statement statement) {\n\n\t\treturn Cypher.collect(statement);\n\t}\n\n\t@Override\n\tpublic Expression mapProjection(InputPosition p, Expression v, List<Expression> items) {\n\t\treturn this.options.isCreateSortedMaps()\n\t\t\t\t? MapProjection.sorted(assertSymbolicName(v), items.toArray(new Object[0]))\n\t\t\t\t: MapProjection.create(assertSymbolicName(v), items.toArray(new Object[0]));\n\t}\n\n\t@Override\n\tpublic Expression mapProjectionLiteralEntry(StringPos<InputPosition> property, Expression value) {\n\t\treturn KeyValueMapEntry.create(property.string, value);\n\t}\n\n\t@Override\n\tpublic Expression mapProjectionProperty(StringPos<InputPosition> property) {\n\t\treturn PropertyLookup.forName(property.string);\n\t}\n\n\t@Override\n\tpublic Expression mapProjectionVariable(Expression v) {\n\t\treturn v;\n\t}\n\n\t@Override\n\tpublic Expression mapProjectionAll(InputPosition p) {\n\t\treturn Cypher.asterisk();\n\t}\n\n\t@Override\n\tpublic Expression caseExpression(InputPosition p, Expression e, List<Expression> whens, List<Expression> thens,\n\t\t\tExpression elze) {\n\n\t\tif (whens != null && thens != null && whens.size() != thens.size()) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot combine lists of whens with a different sized list of thens.\");\n\t\t}\n\n\t\tvar aCase = Cypher.caseExpression(e);\n\t\tif (whens != null && thens != null) {\n\t\t\tvar iteratorWhens = whens.iterator();\n\t\t\tvar iteratorThens = thens.iterator();\n\t\t\twhile (iteratorWhens.hasNext() && iteratorThens.hasNext()) {\n\t\t\t\tvar when = iteratorWhens.next();\n\t\t\t\tif (e != null && when instanceof Comparison comparison\n\t\t\t\t\t\t&& comparison.getComparator().equals(Operator.EQUALITY) && e.equals(comparison.getLeft())) {\n\t\t\t\t\taCase = aCase.when(comparison.getRight()).then(iteratorThens.next());\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\taCase = aCase.when(when).then(iteratorThens.next());\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (elze != null) {\n\t\t\t\treturn ((Case.CaseEnding) aCase).elseDefault(elze);\n\t\t\t}\n\t\t\treturn aCase;\n\t\t}\n\t\treturn aCase;\n\t}\n\n\t@Override\n\tpublic InputPosition inputPosition(int offset, int line, int column) {\n\t\treturn new InputPosition(offset, line, column);\n\t}\n\n\t@Override\n\tpublic EntityType nodeType() {\n\t\treturn EntityType.NODE;\n\t}\n\n\t@Override\n\tpublic EntityType relationshipType() {\n\t\treturn EntityType.RELATIONSHIP;\n\t}\n\n\t@Override\n\tpublic EntityType nodeOrRelationshipType() {\n\t\treturn EntityType.LOLWHAT;\n\t}\n\n\t@Override\n\tpublic Where whereClause(InputPosition p, Expression optionalWhere) {\n\n\t\treturn Where.from(optionalWhere);\n\t}\n\n\t@Override\n\tpublic NULL subqueryInTransactionsBatchParameters(InputPosition p, Expression batchSize) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL subqueryInTransactionsConcurrencyParameters(InputPosition p, Expression concurrency) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL subqueryInTransactionsErrorParameters(InputPosition p, CallInTxsOnErrorBehaviourType onErrorBehaviour) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL subqueryInTransactionsReportParameters(InputPosition p, Expression v) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Clause orderBySkipLimitClause(InputPosition t, List<SortItem> order, InputPosition orderPos, Expression skip,\n\t\t\tInputPosition skipPos, Expression limit, InputPosition limitPos) {\n\t\treturn Clauses.orderBy(order, skip, limit);\n\t}\n\n\t@Override\n\tpublic Clause showTransactionsClause(InputPosition p, SimpleEither<List<String>, Expression> ids, Where where,\n\t\t\tClause yieldClause) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Clause terminateTransactionsClause(InputPosition p, SimpleEither<List<String>, Expression> ids, Where where,\n\t\t\tClause yieldClause) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Clause showSettingsClause(InputPosition p, SimpleEither<List<String>, Expression> names, Where where,\n\t\t\tClause yieldClause) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Clause turnYieldToWith(Clause yieldClause) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement createConstraint(InputPosition p, ConstraintType constraintType, boolean replace,\n\t\t\tboolean ifNotExists, SimpleEither<StringPos<InputPosition>, Parameter<?>> constraintName,\n\t\t\tExpression expression, StringPos<InputPosition> label, List<Property> properties,\n\t\t\tParserCypherTypeName propertyType, SimpleEither<Map<String, Expression>, Parameter<?>> constraintOptions) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement dropConstraint(InputPosition p, SimpleEither<StringPos<InputPosition>, Parameter<?>> name,\n\t\t\tboolean ifExists) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement createLookupIndex(InputPosition p, boolean replace, boolean ifNotExists, boolean isNode,\n\t\t\tSimpleEither<StringPos<InputPosition>, Parameter<?>> indexName, Expression expression,\n\t\t\tStringPos<InputPosition> functionName, Expression functionParameter,\n\t\t\tSimpleEither<Map<String, Expression>, Parameter<?>> indexOptions) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement createIndex(InputPosition p, boolean replace, boolean ifNotExists, boolean isNode,\n\t\t\tSimpleEither<StringPos<InputPosition>, Parameter<?>> indexName, Expression expression,\n\t\t\tStringPos<InputPosition> label, List<Property> properties,\n\t\t\tSimpleEither<Map<String, Expression>, Parameter<?>> indexOptions, CreateIndexTypes indexType) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement createFulltextIndex(InputPosition p, boolean replace, boolean ifNotExists, boolean isNode,\n\t\t\tSimpleEither<StringPos<InputPosition>, Parameter<?>> indexName, Expression expression,\n\t\t\tList<StringPos<InputPosition>> labels, List<Property> properties,\n\t\t\tSimpleEither<Map<String, Expression>, Parameter<?>> indexOptions) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement dropIndex(InputPosition p, SimpleEither<StringPos<InputPosition>, Parameter<?>> name,\n\t\t\tboolean ifExists) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement createRole(InputPosition p, boolean replace,\n\t\t\tSimpleEither<StringPos<InputPosition>, Parameter<?>> roleName,\n\t\t\tSimpleEither<StringPos<InputPosition>, Parameter<?>> fromRole, boolean ifNotExists, boolean immutable) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement dropRole(InputPosition p, SimpleEither<StringPos<InputPosition>, Parameter<?>> roleName,\n\t\t\tboolean ifExists) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement renameRole(InputPosition p, SimpleEither<StringPos<InputPosition>, Parameter<?>> fromRoleName,\n\t\t\tSimpleEither<StringPos<InputPosition>, Parameter<?>> toRoleName, boolean ifExists) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL databasePrivilege(InputPosition p, NULL aNull, NULL aNull2, List<NULL> qualifier, boolean immutable) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL dbmsPrivilege(InputPosition p, NULL aNull, List<NULL> qualifier, boolean immutable) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL loadPrivilege(InputPosition inputPosition, SimpleEither<String, Parameter<?>> simpleEither,\n\t\t\tSimpleEither<String, Parameter<?>> simpleEither1, boolean b) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic NULL graphPrivilege(InputPosition inputPosition, NULL aNull, NULL aNull2, NULL aNull3, List<NULL> qualifier,\n\t\t\tboolean immutable) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL privilegeAction(ActionType action) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL propertiesResource(InputPosition p, List<String> property) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL allPropertiesResource(InputPosition p) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL labelsResource(InputPosition p, List<String> label) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL allLabelsResource(InputPosition p) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL databaseResource(InputPosition p) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL noResource(InputPosition p) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL labelQualifier(InputPosition p, String label) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL relationshipQualifier(InputPosition p, String relationshipType) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL elementQualifier(InputPosition p, String name) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL allElementsQualifier(InputPosition p) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL patternQualifier(List<NULL> list, Expression expression, Expression expression2) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL allLabelsQualifier(InputPosition p) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL allRelationshipsQualifier(InputPosition p) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic List<NULL> allQualifier() {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic List<NULL> allDatabasesQualifier() {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic List<NULL> userQualifier(List<SimpleEither<StringPos<InputPosition>, Parameter<?>>> users) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic List<NULL> allUsersQualifier() {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic List<NULL> functionQualifier(InputPosition p, List<String> functions) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic List<NULL> procedureQualifier(InputPosition p, List<String> procedures) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic List<NULL> settingQualifier(InputPosition inputPosition, List<String> list) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL graphScope(InputPosition inputPosition, List<DatabaseName> graphNames, ScopeType scopeType) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic NULL databasePrivilegeScope(InputPosition inputPosition, List<DatabaseName> list, ScopeType scopeType) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Labels dynamicLabelLeaf(InputPosition p, Expression e, EntityType entityType, boolean all,\n\t\t\tboolean containsIs) {\n\t\tif (all) {\n\t\t\treturn Cypher.allLabels(e);\n\t\t}\n\t\treturn Cypher.anyLabel(e);\n\t}\n\n\t@Override\n\tpublic Statement enableServer(InputPosition p, SimpleEither<String, Parameter<?>> serverName,\n\t\t\tSimpleEither<Map<String, Expression>, Parameter<?>> serverOptions) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement alterServer(InputPosition p, SimpleEither<String, Parameter<?>> serverName,\n\t\t\tSimpleEither<Map<String, Expression>, Parameter<?>> serverOptions) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement renameServer(InputPosition p, SimpleEither<String, Parameter<?>> serverName,\n\t\t\tSimpleEither<String, Parameter<?>> newName) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement dropServer(InputPosition p, SimpleEither<String, Parameter<?>> serverName) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement showServers(InputPosition p, Clause yieldExpr, Return returnWithoutGraph, Where where) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement deallocateServers(InputPosition p, boolean dryRun,\n\t\t\tList<SimpleEither<String, Parameter<?>>> serverNames) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Statement reallocateDatabases(InputPosition p, boolean dryRun) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\tstatic class PatternJuxtaposition extends TypedSubtree<PatternElement> implements PatternElement {\n\n\t\tPatternJuxtaposition(Collection<PatternElement> children) {\n\t\t\tsuper(children);\n\t\t}\n\n\t\t@Override\n\t\tpublic String separator() {\n\t\t\treturn \" \";\n\t\t}\n\n\t}\n\n\tstatic class PatternList extends TypedSubtree<PatternElement> implements PatternElement {\n\n\t\tPatternList(Collection<PatternElement> children) {\n\t\t\tsuper(children);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/CypherParser.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypher.internal.parser.javacc.CharStream;\nimport org.neo4j.cypher.internal.parser.javacc.Cypher;\nimport org.neo4j.cypher.internal.parser.javacc.CypherCharStream;\nimport org.neo4j.cypher.internal.parser.javacc.ParseException;\nimport org.neo4j.cypherdsl.core.Clause;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.RelationshipPattern;\nimport org.neo4j.cypherdsl.core.Statement;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Main entrypoint to a Cypher parser that produces Cypher-DSL statements.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = STABLE, since = \"2021.3.0\")\npublic final class CypherParser {\n\n\t/**\n\t * Not to be instantiated.\n\t */\n\tprivate CypherParser() {\n\t}\n\n\t/**\n\t * Parses a single node.\n\t * @param input a Cypher fragment\n\t * @return a node\n\t * @see #parseNode(String, Options)\n\t */\n\tpublic static Node parseNode(String input) {\n\t\treturn parseNode(input, Options.defaultOptions());\n\t}\n\n\t/**\n\t * Parses a Cypher fragment describing a Node-pattern into a {@link Node} instance.\n\t * @param input a Cypher fragment\n\t * @param options options for the parser\n\t * @return a node\n\t */\n\tpublic static Node parseNode(String input, Options options) {\n\n\t\treturn handle(input, () -> new Cypher<>(CypherDslASTFactory.getInstance(options),\n\t\t\t\tCypherDslASTExceptionFactory.INSTANCE, getCharStream(input))\n\t\t\t.NodePattern()).value();\n\t}\n\n\t/**\n\t * Parses a single relationship.\n\t * @param input a Cypher fragment\n\t * @return a relationship pattern or chain of relationship pattern\n\t * @see #parseNode(String, Options)\n\t */\n\tpublic static RelationshipPattern parseRelationship(String input) {\n\t\treturn parseRelationship(input, Options.defaultOptions());\n\t}\n\n\t/**\n\t * Parses a Cypher fragment describing a relationship into a\n\t * {@link RelationshipPattern} instance.\n\t * @param input a Cypher fragment\n\t * @param options options for the parser\n\t * @return a relationship pattern or chain of relationship pattern\n\t */\n\tpublic static RelationshipPattern parseRelationship(String input, Options options) {\n\n\t\treturn handle(input, () -> (RelationshipPattern) new Cypher<>(CypherDslASTFactory.getInstance(options),\n\t\t\t\tCypherDslASTExceptionFactory.INSTANCE, getCharStream(input))\n\t\t\t.Pattern());\n\t}\n\n\t/**\n\t * Parses a full expression.\n\t * @param input a Cypher fragment of an expression\n\t * @return a valid Cypher-DSL expression instance\n\t * @see #parseExpression(String, Options)\n\t */\n\tpublic static Expression parseExpression(String input) {\n\t\treturn parseExpression(input, Options.defaultOptions());\n\t}\n\n\t/**\n\t * Parses a Cypher expression into an {@link Expression}.\n\t * @param input a Cypher fragment of an expression\n\t * @param options options for the parser\n\t * @return a valid Cypher-DSL expression instance\n\t */\n\tpublic static Expression parseExpression(String input, Options options) {\n\n\t\treturn handle(input, () -> new Cypher<>(CypherDslASTFactory.getInstance(options),\n\t\t\t\tCypherDslASTExceptionFactory.INSTANCE, getCharStream(input))\n\t\t\t.Expression());\n\t}\n\n\t/**\n\t * Parses a single clause.\n\t * @param input a Cypher fragment containing a valid clause\n\t * @return a {@link Clause} instance\n\t * @see #parseClause(String, Options)\n\t */\n\tpublic static Clause parseClause(String input) {\n\t\treturn parseClause(input, Options.defaultOptions());\n\t}\n\n\t/**\n\t * Parses a fragment into a {@link Clause} that can be put together into a whole\n\t * statement via {@link Statement#of(List)}.\n\t * @param input a Cypher fragment containing a valid clause\n\t * @param options options for the parser\n\t * @return a {@link Clause} instance\n\t */\n\tpublic static Clause parseClause(String input, Options options) {\n\n\t\treturn handle(input, () -> new Cypher<>(CypherDslASTFactory.getInstance(options),\n\t\t\t\tCypherDslASTExceptionFactory.INSTANCE, getCharStream(input))\n\t\t\t.Clause());\n\t}\n\n\t/**\n\t * Parses a full statement.\n\t * @param input string representing a statement\n\t * @return a {@link Statement} statement.\n\t * @see #parseStatement(String, Options)\n\t */\n\tpublic static Statement parseStatement(String input) {\n\t\treturn parseStatement(input, Options.defaultOptions());\n\t}\n\n\t/**\n\t * Parses a whole statement into a renderable Cypher-DSL {@link Statement}. The\n\t * statement might be used in a subquery, with a union or maybe just rewritten.\n\t * @param input string representing a statement\n\t * @param options options for the parser\n\t * @return a {@link Statement} statement.\n\t */\n\tpublic static Statement parseStatement(String input, Options options) {\n\n\t\treturn handle(input, () -> new Cypher<>(CypherDslASTFactory.getInstance(options),\n\t\t\t\tCypherDslASTExceptionFactory.INSTANCE, getCharStream(input))\n\t\t\t.Statement());\n\t}\n\n\t/**\n\t * Parses a {@link String} into a {@link Statement}.\n\t * @param input string representing a statement\n\t * @return a {@link Statement} statement.\n\t * @see #parseStatement(String)\n\t */\n\tpublic static Statement parse(String input) {\n\t\treturn parse(input, Options.defaultOptions());\n\t}\n\n\t/**\n\t * Parses a {@link String} into a {@link Statement}.\n\t * @param input string representing a statement\n\t * @param options options for the parser\n\t * @return a {@link Statement} statement.\n\t * @see #parseStatement(String, Options)\n\t */\n\tpublic static Statement parse(String input, Options options) {\n\t\treturn parseStatement(input, options);\n\t}\n\n\tprivate static <T> T handle(String input, ThrowingParser<T> parser) {\n\t\ttry {\n\t\t\treturn parser.parse();\n\t\t}\n\t\tcatch (ParseException ex) {\n\t\t\tthrow new CyperDslParseException(ex);\n\t\t}\n\t\tcatch (IllegalArgumentException ex) {\n\t\t\tthrow ex;\n\t\t}\n\t\tcatch (UnsupportedOperationException ex) {\n\t\t\tthrow new UnsupportedCypherException(input, ex);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tthrow new RuntimeException(\"Unexpected exception\", ex);\n\t\t}\n\t}\n\n\tprivate static CharStream getCharStream(String input) {\n\t\treturn new CypherCharStream(input);\n\t}\n\n\t@FunctionalInterface\n\tprivate interface ThrowingParser<T> {\n\n\t\tT parse() throws Exception;\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/DatabaseName.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.neo4j.cypherdsl.core.Expression;\n\n/**\n * Value object for expressions representing database names.\n *\n * @param value representing a database name.\n * @author Michael J. Simons\n */\npublic record DatabaseName(Expression value) {\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/EntityType.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.neo4j.cypher.internal.ast.factory.ASTFactory;\n\n/**\n * The type of a parsed entity.\n *\n * @author Michael J. Simons\n * @since 2023.0.0\n */\nenum EntityType {\n\n\tNODE, RELATIONSHIP,\n\t/**\n\t * Why the hell is there {@link ASTFactory#nodeOrRelationshipType()} ?!\n\t */\n\tLOLWHAT\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/ExpressionAsPatternElementWrapper.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.PatternElement;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Necessary for {@code shortestPath} and friends.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = INTERNAL, since = \"2021.3.0\")\nfinal class ExpressionAsPatternElementWrapper implements PatternElement {\n\n\tprivate final Expression expression;\n\n\tExpressionAsPatternElementWrapper(Expression expression) {\n\t\tthis.expression = expression;\n\t}\n\n\tExpression getExpression() {\n\t\treturn this.expression;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tthis.expression.accept(visitor);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/ExpressionCreatedEventType.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.Operation;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * The type of the event when a new expression is parsed and instantiated. Callbacks are\n * tied to this type.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = STABLE, since = \"2021.3.0\")\npublic enum ExpressionCreatedEventType {\n\n\t/**\n\t * Fired for every new return item.\n\t */\n\tON_RETURN_ITEM(Expression.class),\n\t/**\n\t * Fired when a property is set.\n\t */\n\tON_SET_PROPERTY(Operation.class),\n\t/**\n\t * Fired when a label is defined.\n\t */\n\tON_SET_LABELS(Operation.class),\n\t/**\n\t * Fired when a variable is defined.\n\t */\n\tON_SET_VARIABLE(Operation.class),\n\t/**\n\t * Fired when a variable is added or redefined (set).\n\t */\n\tON_ADD_AND_SET_VARIABLE(Operation.class),\n\t/**\n\t * Fired when parsing a property removal expression.\n\t */\n\tON_REMOVE_PROPERTY(Expression.class),\n\t/**\n\t * Fired when parsing a label removing expression.\n\t */\n\tON_REMOVE_LABELS(Expression.class),\n\t/**\n\t * Fired when parsing a new variable expression.\n\t */\n\tON_NEW_VARIABLE(Expression.class),\n\t/**\n\t * Fired when parsing a new parameter expression.\n\t */\n\tON_NEW_PARAMETER(Expression.class),\n\t/**\n\t * Fired when preparing a {@code DELETE x, y, z} clause.\n\t */\n\tON_DELETE_ITEM(Expression.class),\n\t/**\n\t * Fired when new literals are created.\n\t */\n\tON_NEW_LITERAL(Expression.class);\n\n\tprivate final Class<? extends Expression> typeProduced;\n\n\tExpressionCreatedEventType(Class<? extends Expression> typeProduced) {\n\t\tthis.typeProduced = typeProduced;\n\t}\n\n\t/**\n\t * {@return the actual type that will be produced, might be a specialization}\n\t */\n\tClass<? extends Expression> getTypeProduced() {\n\t\treturn this.typeProduced;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/InfinityLiteral.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.neo4j.cypherdsl.core.Literal;\n\n/**\n * Custom literal for infinity.\n *\n * @author Michael J. Simons\n * @since 2023.0.0\n */\nenum InfinityLiteral implements Literal<Double> {\n\n\tINSTANCE;\n\n\t@Override\n\tpublic String asString() {\n\t\treturn \"Infinity\";\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/InputPosition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Needed for implementing the {@link org.neo4j.cypher.internal.ast.factory.ASTFactory}.\n *\n * @param offset the offset\n * @param line the line number\n * @param column the column number\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = INTERNAL, since = \"2021.3.0\")\nrecord InputPosition(int offset, int line, int column) {\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/InvocationCreatedEventType.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.neo4j.cypherdsl.core.Clause;\nimport org.neo4j.cypherdsl.core.Expression;\n\n/**\n * The type of event emitted when creating a procedure call or function invocation.\n *\n * @author Michael J. Simons\n * @since 2022.8.6\n */\npublic enum InvocationCreatedEventType {\n\n\t/**\n\t * When parsing a {@code CALL x.y(z)} like statement.\n\t */\n\tON_CALL(Clause.class),\n\n\t/**\n\t * When parsing a {@code sin(x)} like statement.\n\t */\n\tON_INVOCATION(Expression.class);\n\n\tprivate final Class<?> typeProduced;\n\n\tInvocationCreatedEventType(Class<?> typeProduced) {\n\t\tthis.typeProduced = typeProduced;\n\t}\n\n\tClass<?> getTypeProduced() {\n\t\treturn this.typeProduced;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/LabelParsedEventType.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Type of an event when a label is parsed and created.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = STABLE, since = \"2021.3.0\")\npublic enum LabelParsedEventType {\n\n\t/**\n\t * Parsed when creating a {@link org.neo4j.cypherdsl.core.Node node pattern}.\n\t */\n\tON_NODE_PATTERN,\n\n\t/**\n\t * Parsed in the context of setting new labels.\n\t */\n\tON_SET,\n\n\t/**\n\t * Parsed in the context of removing labels.\n\t */\n\tON_REMOVE\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/MatchDefinition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.Hint;\nimport org.neo4j.cypherdsl.core.PatternElement;\nimport org.neo4j.cypherdsl.core.Where;\n\n/**\n * Shape of a match clause.\n *\n * @author Michael J. Simons\n * @param optional flag if this is an optional match\n * @param patternElements the pattern elements inside the match\n * @param optionalWhere an optional where clause\n * @param optionalHints optional hints\n * @since 2023.0.2\n */\npublic record MatchDefinition(boolean optional, List<PatternElement> patternElements, Where optionalWhere,\n\t\tList<Hint> optionalHints) {\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/NaNLiteral.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.neo4j.cypherdsl.core.Literal;\n\n/**\n * Custom literal for {@link Double#NaN}.\n *\n * @author Michael J. Simons\n * @since 2023.0.0\n */\nenum NaNLiteral implements Literal<Double> {\n\n\tINSTANCE;\n\n\t@Override\n\tpublic String asString() {\n\t\treturn \"NaN\";\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/NodeAtom.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.PatternElement;\n\n/**\n * A value object for {@link Node nodes}.\n *\n * @author Michael J. Simons\n * @param value the actual node\n * @since 2023.0.0\n */\nrecord NodeAtom(Node value) implements PatternAtom, PatternElement {\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/Options.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.EnumMap;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.function.BiFunction;\nimport java.util.function.Function;\nimport java.util.function.UnaryOperator;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Clauses;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.Match;\nimport org.neo4j.cypherdsl.core.PatternElement;\nimport org.neo4j.cypherdsl.core.Return;\nimport org.neo4j.cypherdsl.core.Where;\nimport org.neo4j.cypherdsl.core.ast.Visitable;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Provides arguments to the {@link CypherParser cypher parser}. The options itself are\n * thread safe and can be reused. The listener and modifications you provide are of course\n * out of our control.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = STABLE, since = \"2021.3.0\")\npublic final class Options {\n\n\tprivate static final Options DEFAULT_OPTIONS = newOptions().build();\n\n\tprivate final BiFunction<LabelParsedEventType, Collection<String>, Collection<String>> labelFilter;\n\n\tprivate final BiFunction<TypeParsedEventType, Collection<String>, Collection<String>> typeFilter;\n\n\tprivate final Map<ExpressionCreatedEventType, List<Function<Expression, ? extends Expression>>> onNewExpressionCallbacks;\n\n\tprivate final Map<PatternElementCreatedEventType, List<UnaryOperator<PatternElement>>> onNewPatternElementCallbacks;\n\n\tprivate final Map<InvocationCreatedEventType, List<UnaryOperator<Visitable>>> onNewInvocationCallbacks;\n\n\tprivate final Function<ReturnDefinition, Return> returnClauseFactory;\n\n\tprivate final Function<MatchDefinition, Match> matchClauseFactory;\n\n\tprivate final boolean createSortedMaps;\n\n\tprivate final Map<String, Object> parameterValues;\n\n\tprivate boolean alwaysCreateRelationshipsLTR;\n\n\tprivate Options(Builder builder) {\n\n\t\tthis.labelFilter = builder.labelFilter;\n\t\tthis.typeFilter = builder.typeFilter;\n\n\t\tMap<ExpressionCreatedEventType, List<Function<Expression, ? extends Expression>>> tmp = new EnumMap<>(\n\t\t\t\tExpressionCreatedEventType.class);\n\t\tbuilder.onNewExpressionCallbacks.forEach((k, v) -> tmp.put(k, List.copyOf(v)));\n\t\tthis.onNewExpressionCallbacks = Map.copyOf(tmp);\n\n\t\tMap<PatternElementCreatedEventType, List<UnaryOperator<PatternElement>>> tmp2 = new EnumMap<>(\n\t\t\t\tPatternElementCreatedEventType.class);\n\t\tbuilder.onNewPatternElementCallbacks.forEach((k, v) -> tmp2.put(k, List.copyOf(v)));\n\t\tthis.onNewPatternElementCallbacks = Map.copyOf(tmp2);\n\n\t\tMap<InvocationCreatedEventType, List<UnaryOperator<Visitable>>> tmp3 = new EnumMap<>(\n\t\t\t\tInvocationCreatedEventType.class);\n\t\tbuilder.onNewInvocationCallbacks.forEach((k, v) -> tmp3.put(k, List.copyOf(v)));\n\t\tthis.onNewInvocationCallbacks = Map.copyOf(tmp3);\n\n\t\tthis.returnClauseFactory = (builder.returnClauseFactory != null) ? builder.returnClauseFactory\n\t\t\t\t: returnDefinition -> Clauses.returning(returnDefinition.isDistinct(),\n\t\t\t\t\t\treturnDefinition.getExpressions(), returnDefinition.getOptionalSortItems(),\n\t\t\t\t\t\treturnDefinition.getOptionalSkip(), returnDefinition.getOptionalLimit());\n\n\t\tthis.matchClauseFactory = (builder.matchClauseFactory != null) ? builder.matchClauseFactory\n\t\t\t\t: returnDefinition -> (Match) Clauses.match(returnDefinition.optional(),\n\t\t\t\t\t\treturnDefinition.patternElements(), returnDefinition.optionalWhere(),\n\t\t\t\t\t\treturnDefinition.optionalHints());\n\n\t\tthis.createSortedMaps = builder.createSortedMaps;\n\t\tthis.alwaysCreateRelationshipsLTR = builder.alwaysCreateRelationshipsLTR;\n\t\tthis.parameterValues = builder.parameterValues;\n\t}\n\n\t/**\n\t * {@return the default options}\n\t */\n\tpublic static Options defaultOptions() {\n\t\treturn DEFAULT_OPTIONS;\n\t}\n\n\t/**\n\t * Use this method to start defining new options for a parser.\n\t * @return a builder for new options.\n\t */\n\tpublic static Builder newOptions() {\n\t\treturn Builder.newConfig();\n\t}\n\n\tBiFunction<LabelParsedEventType, Collection<String>, Collection<String>> getLabelFilter() {\n\t\treturn this.labelFilter;\n\t}\n\n\tBiFunction<TypeParsedEventType, Collection<String>, Collection<String>> getTypeFilter() {\n\t\treturn this.typeFilter;\n\t}\n\n\tMap<ExpressionCreatedEventType, List<Function<Expression, ? extends Expression>>> getOnNewExpressionCallbacks() {\n\t\treturn this.onNewExpressionCallbacks;\n\t}\n\n\tMap<PatternElementCreatedEventType, List<UnaryOperator<PatternElement>>> getOnNewPatternElementCallbacks() {\n\t\treturn this.onNewPatternElementCallbacks;\n\t}\n\n\tFunction<ReturnDefinition, Return> getReturnClauseFactory() {\n\t\treturn this.returnClauseFactory;\n\t}\n\n\tFunction<MatchDefinition, Match> getMatchClauseFactory() {\n\t\treturn this.matchClauseFactory;\n\t}\n\n\tboolean isCreateSortedMaps() {\n\t\treturn this.createSortedMaps;\n\t}\n\n\tboolean isAlwaysCreateRelationshipsLTR() {\n\t\treturn this.alwaysCreateRelationshipsLTR;\n\t}\n\n\tMap<InvocationCreatedEventType, List<UnaryOperator<Visitable>>> getOnNewInvocationCallbacks() {\n\t\treturn this.onNewInvocationCallbacks;\n\t}\n\n\t/**\n\t * {@return <code>true</code> if these are the default options}\n\t */\n\tboolean areDefault() {\n\t\treturn this == DEFAULT_OPTIONS;\n\t}\n\n\tMap<String, Object> getParameterValues() {\n\t\treturn this.parameterValues;\n\t}\n\n\t/**\n\t * Use this builder to create a new set of options..\n\t */\n\t@SuppressWarnings(\"HiddenField\")\n\tpublic static final class Builder {\n\n\t\tprivate final Map<ExpressionCreatedEventType, List<Function<Expression, ? extends Expression>>> onNewExpressionCallbacks = new EnumMap<>(\n\t\t\t\tExpressionCreatedEventType.class);\n\n\t\tprivate final Map<PatternElementCreatedEventType, List<UnaryOperator<PatternElement>>> onNewPatternElementCallbacks = new EnumMap<>(\n\t\t\t\tPatternElementCreatedEventType.class);\n\n\t\tprivate final Map<InvocationCreatedEventType, List<UnaryOperator<Visitable>>> onNewInvocationCallbacks = new EnumMap<>(\n\t\t\t\tInvocationCreatedEventType.class);\n\n\t\tprivate BiFunction<LabelParsedEventType, Collection<String>, Collection<String>> labelFilter = (e, l) -> l;\n\n\t\tprivate BiFunction<TypeParsedEventType, Collection<String>, Collection<String>> typeFilter = (e, t) -> t;\n\n\t\tprivate Function<ReturnDefinition, Return> returnClauseFactory;\n\n\t\tprivate Function<MatchDefinition, Match> matchClauseFactory;\n\n\t\tprivate Map<String, Object> parameterValues = Map.of();\n\n\t\tprivate boolean createSortedMaps = false;\n\n\t\tprivate boolean alwaysCreateRelationshipsLTR = false;\n\n\t\tprivate Builder() {\n\t\t}\n\n\t\tstatic Builder newConfig() {\n\t\t\treturn new Builder();\n\t\t}\n\n\t\t/**\n\t\t * Configure a filter that is applied to labels.\n\t\t * @param labelFilter takes in an event type, a collection of labels and returns a\n\t\t * probably new collection of labels.\n\t\t * @return this builder.\n\t\t */\n\t\tpublic Builder withLabelFilter(\n\t\t\t\tBiFunction<LabelParsedEventType, Collection<String>, Collection<String>> labelFilter) {\n\n\t\t\tif (labelFilter == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"Label filter may not be null.\");\n\t\t\t}\n\t\t\tthis.labelFilter = labelFilter;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configure a filter that is applied to types.\n\t\t * @param typeFilter takes in an event type and the parsed type. May return the\n\t\t * type itself or something else.\n\t\t * @return this builder.\n\t\t */\n\t\tpublic Builder withTypeFilter(\n\t\t\t\tBiFunction<TypeParsedEventType, Collection<String>, Collection<String>> typeFilter) {\n\n\t\t\tif (typeFilter == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"Type filter may not be null.\");\n\t\t\t}\n\t\t\tthis.typeFilter = typeFilter;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Adds a callback for when the specific {@link ExpressionCreatedEventType\n\t\t * expression is created} event. For one type of event one or more callbacks can\n\t\t * be declared which will be called in order in which they have been declared.\n\t\t * <p>\n\t\t * Parsing will be aborted when a callback throws a {@link RuntimeException}.\n\t\t * @param expressionCreatedEventType the type of the event\n\t\t * @param resultingType the type of the expression the callback returns. Must\n\t\t * match the one of the event type.\n\t\t * @param callback a callback\n\t\t * @param <T> the type of the expression produced by the callback. Must match the\n\t\t * one of the event type\n\t\t * @return this builder\n\t\t */\n\t\tpublic <T extends Expression> Builder withCallback(ExpressionCreatedEventType expressionCreatedEventType,\n\t\t\t\tClass<T> resultingType, Function<Expression, T> callback) {\n\n\t\t\tif (!expressionCreatedEventType.getTypeProduced().isAssignableFrom(resultingType)) {\n\t\t\t\tthrow new IllegalArgumentException(\"The type that is produced by '\" + expressionCreatedEventType\n\t\t\t\t\t\t+ \"' is not compatible with \" + resultingType);\n\t\t\t}\n\t\t\tvar callbacks = this.onNewExpressionCallbacks.computeIfAbsent(expressionCreatedEventType,\n\t\t\t\t\tk -> new ArrayList<>());\n\t\t\tcallbacks.add(callback);\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Adds a callback for when a {@link PatternElement} is created during one of the\n\t\t * phases described by {@link PatternElementCreatedEventType}. For one type of\n\t\t * event one or more callbacks can be declared which will be called in order in\n\t\t * which they have been declared. Callbacks can just collect or actually visit the\n\t\t * elements created, or they are free to create new ones, effectively rewriting\n\t\t * the query.\n\t\t * <p>\n\t\t * Parsing will be aborted when a callback throws a {@link RuntimeException}.\n\t\t * @param patternElementCreatedEventType the type of the event\n\t\t * @param callback a callback\n\t\t * @return this builder\n\t\t * @since 2022.2.0\n\t\t */\n\t\tpublic Builder withCallback(PatternElementCreatedEventType patternElementCreatedEventType,\n\t\t\t\tUnaryOperator<PatternElement> callback) {\n\n\t\t\tvar callbacks = this.onNewPatternElementCallbacks.computeIfAbsent(patternElementCreatedEventType,\n\t\t\t\t\tk -> new ArrayList<>());\n\t\t\tcallbacks.add(callback);\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Adds a callback for when either a CALL-Procedure clause or a\n\t\t * function-invocation expression is created. For one type of event one or more\n\t\t * callbacks can be declared which will be called in order in which they have been\n\t\t * declared. Callbacks can just collect or actually visit the elements created, or\n\t\t * they are free to create new ones, effectively rewriting the query.\n\t\t * <p>\n\t\t * Parsing will be aborted when a callback throws a {@link RuntimeException}.\n\t\t * @param invocationCreatedEventType the event type\n\t\t * @param resultingType the reified type being produced\n\t\t * @param callback a callback\n\t\t * @param <T> the type of the result, must match the one of the event\n\t\t * @return this builder\n\t\t * @since 2022.8.6\n\t\t */\n\t\t@SuppressWarnings(\"unchecked\")\n\t\tpublic <T extends Visitable> Builder withCallback(InvocationCreatedEventType invocationCreatedEventType,\n\t\t\t\tClass<T> resultingType, UnaryOperator<T> callback) {\n\n\t\t\tif (!invocationCreatedEventType.getTypeProduced().isAssignableFrom(resultingType)) {\n\t\t\t\tthrow new IllegalArgumentException(\"The type that is produced by '\" + invocationCreatedEventType\n\t\t\t\t\t\t+ \"' is not compatible with \" + resultingType);\n\t\t\t}\n\t\t\tvar callbacks = this.onNewInvocationCallbacks.computeIfAbsent(invocationCreatedEventType,\n\t\t\t\t\tk -> new ArrayList<>());\n\t\t\tcallbacks.add((UnaryOperator<Visitable>) callback);\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configures the factory for return clauses. The idea here is that you might\n\t\t * intercept what is being returned or how it is sorted, limited and the like. The\n\t\t * {@link ReturnDefinition definition} passed to the factory contains all\n\t\t * necessary information for delegating to the\n\t\t * {@link org.neo4j.cypherdsl.core.Clauses#returning(boolean, List, List, Expression, Expression)}\n\t\t * factory.\n\t\t * @param returnClauseFactory the factory producing return classes that should be\n\t\t * used.\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder withReturnClauseFactory(Function<ReturnDefinition, Return> returnClauseFactory) {\n\t\t\tthis.returnClauseFactory = returnClauseFactory;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Configures the factory for return clauses. The idea here is that you might\n\t\t * intercept what is being matched and or how it is restricted. The\n\t\t * {@link MatchDefinition definition} passed to the factory contains all necessary\n\t\t * information for delegating to the\n\t\t * {@link org.neo4j.cypherdsl.core.Clauses#match(boolean, List, Where, List)}\n\t\t * factory.\n\t\t * @param matchClauseFactory the factory producing return classes that should be\n\t\t * used.\n\t\t * @return this builder\n\t\t * @since 2023.0.2\n\t\t */\n\t\tpublic Builder withMatchClauseFactory(Function<MatchDefinition, Match> matchClauseFactory) {\n\t\t\tthis.matchClauseFactory = matchClauseFactory;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Set {@code createSortedMaps} to {@literal true} to parse existing maps into\n\t\t * alphabetically sorted maps.\n\t\t * @param createSortedMaps a flag whether to create sorted maps or not\n\t\t * @return this builder\n\t\t * @since 2023.2.0\n\t\t */\n\t\tpublic Builder createSortedMaps(boolean createSortedMaps) {\n\t\t\tthis.createSortedMaps = createSortedMaps;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Instructs the parser to turn relationships that are given as\n\t\t * {@code (a:A) <-[:TYPE]- (b:B)} into {@code (b:B) -[:TYPE]-> (a:A)}. Multi-hop\n\t\t * patterns will be split into a relationship enumeration from left to right with\n\t\t * all parts pointing from left to right\n\t\t * @param alwaysCreateRelationshipsLTR a flag whether to only use left-to-right\n\t\t * relationships\n\t\t * @return this builder\n\t\t * @since 2023.9.3\n\t\t */\n\t\tpublic Builder alwaysCreateRelationshipsLTR(boolean alwaysCreateRelationshipsLTR) {\n\t\t\tthis.alwaysCreateRelationshipsLTR = alwaysCreateRelationshipsLTR;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Defines a lookup table for parameters. Everytime a parameter is parsed, we do\n\t\t * check if a value in this table exists. If so, the parameter will be created as\n\t\t * a named parameter carrying that value.\n\t\t * <p>\n\t\t * Any previous lookup table will be overwritten when using this method multiple\n\t\t * times.\n\t\t * @param newParameterValues a new lookup table. Use an empty map or\n\t\t * {@literal null} to clear any lookups in the config\n\t\t * @return this builder\n\t\t * @since 2023.4.0\n\t\t */\n\t\tpublic Builder withParameterValues(Map<String, Object> newParameterValues) {\n\t\t\tthis.parameterValues = (newParameterValues != null)\n\t\t\t\t\t? Collections.unmodifiableMap(new HashMap<>(newParameterValues)) : Map.of();\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Returns a new, unmodifiable {@link Options options instance}.\n\t\t * @return a new, unmodifiable {@link Options options instance}\n\t\t */\n\t\tpublic Options build() {\n\t\t\treturn new Options(this);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/ParenthesizedPathPatternAtom.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.PatternElement;\nimport org.neo4j.cypherdsl.core.QuantifiedPathPattern;\nimport org.neo4j.cypherdsl.core.RelationshipPattern;\n\n/**\n * Helper to deal with quantified path patterns.\n *\n * @param patternElement the pattern element in parentheses\n * @param quantifier the quantifier\n * @param predicate any predicate\n * @author Michael J. Simons\n */\nrecord ParenthesizedPathPatternAtom(RelationshipPattern patternElement, QuantifiedPathPattern.Quantifier quantifier,\n\t\tExpression predicate) implements PatternAtom {\n\n\tPatternElement asPatternElement() {\n\n\t\treturn this.patternElement.quantify(this.quantifier).where(this.predicate);\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/PathAtom.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.neo4j.cypherdsl.core.ExposesPatternLengthAccessors;\nimport org.neo4j.cypherdsl.core.ExposesProperties;\nimport org.neo4j.cypherdsl.core.ExposesRelationships;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.MapExpression;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.QuantifiedPathPattern;\nimport org.neo4j.cypherdsl.core.Relationship;\nimport org.neo4j.cypherdsl.core.Relationship.Direction;\nimport org.neo4j.cypherdsl.core.RelationshipChain;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\n/**\n * A value object for the details of a path.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\nfinal class PathAtom implements PatternAtom {\n\n\tprivate final SymbolicName name;\n\n\tprivate final PathLength length;\n\n\tprivate final Direction direction;\n\n\tprivate final boolean negatedType;\n\n\tprivate final String[] types;\n\n\tprivate final MapExpression properties;\n\n\tprivate final Expression predicate;\n\n\tprivate final QuantifiedPathPattern.Quantifier quantifier;\n\n\tprivate PathAtom(SymbolicName name, PathLength length, Direction direction, boolean negatedType, String[] types,\n\t\t\tMapExpression properties, Expression predicate, QuantifiedPathPattern.Quantifier quantifier) {\n\t\tthis.name = name;\n\t\tthis.length = length;\n\t\tthis.direction = direction;\n\t\tthis.negatedType = negatedType;\n\t\tthis.types = types;\n\t\tthis.properties = properties;\n\t\tthis.predicate = predicate;\n\t\tthis.quantifier = quantifier;\n\t}\n\n\t@SuppressWarnings(\"squid:S107\") // Totally fine with that number of args for this\n\t\t\t\t\t\t\t\t\t// internal API.\n\tstatic PathAtom of(SymbolicName name, PathLength length, boolean left, boolean right, String[] relTypes,\n\t\t\tMapExpression properties, boolean negatedType, Expression predicate) {\n\n\t\tif (left && right) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"Only left-to-right, right-to-left or unidirectional path elements are supported.\");\n\t\t}\n\n\t\tDirection direction;\n\t\tif (left) {\n\t\t\tdirection = Direction.RTL;\n\t\t}\n\t\telse if (right) {\n\t\t\tdirection = Direction.LTR;\n\t\t}\n\t\telse {\n\t\t\tdirection = Direction.UNI;\n\t\t}\n\n\t\treturn new PathAtom(name, length, direction, negatedType, relTypes, properties, predicate, null);\n\t}\n\n\tExposesRelationships<?> asRelationshipBetween(ExposesRelationships<?> previous, NodeAtom nodeAtom,\n\t\t\tboolean alwaysLtr) {\n\t\tvar node = nodeAtom.value();\n\t\tExposesRelationships<?> relationshipPattern = switch (this.getDirection()) {\n\t\t\tcase LTR -> previous.relationshipTo(node, this.getTypes());\n\t\t\tcase RTL -> alwaysLtr ? node.relationshipTo((Node) previous, this.getTypes())\n\t\t\t\t\t: previous.relationshipFrom(node, this.getTypes());\n\t\t\tcase UNI -> previous.relationshipBetween(node, this.getTypes());\n\t\t};\n\t\trelationshipPattern = applyOptionalName(relationshipPattern);\n\t\trelationshipPattern = applyOptionalProperties(relationshipPattern);\n\t\trelationshipPattern = applyOptionalPredicate(relationshipPattern);\n\t\trelationshipPattern = applyOptionalLength(relationshipPattern);\n\t\treturn applyOptionalQuantifier(relationshipPattern);\n\t}\n\n\tprivate ExposesRelationships<?> applyOptionalLength(ExposesRelationships<?> relationshipPattern) {\n\t\tif (this.length == null) {\n\t\t\treturn relationshipPattern;\n\t\t}\n\t\tif (this.length.isUnbounded()) {\n\t\t\treturn ((ExposesPatternLengthAccessors<?>) relationshipPattern).unbounded();\n\t\t}\n\t\treturn ((ExposesPatternLengthAccessors<?>) relationshipPattern).length(this.length.getMinimum(),\n\t\t\t\tthis.length.getMaximum());\n\t}\n\n\tprivate ExposesRelationships<?> applyOptionalProperties(ExposesRelationships<?> relationshipPattern) {\n\t\tif (this.properties == null) {\n\t\t\treturn relationshipPattern;\n\t\t}\n\t\tif (relationshipPattern instanceof ExposesProperties<?> exposesProperties) {\n\t\t\treturn (ExposesRelationships<?>) exposesProperties.withProperties(this.properties);\n\t\t}\n\t\treturn ((RelationshipChain) relationshipPattern).properties(this.properties);\n\t}\n\n\tprivate ExposesRelationships<?> applyOptionalName(ExposesRelationships<?> relationshipPattern) {\n\t\tif (this.name == null) {\n\t\t\treturn relationshipPattern;\n\t\t}\n\t\tif (relationshipPattern instanceof Relationship relationship) {\n\t\t\treturn relationship.named(this.name);\n\t\t}\n\t\treturn ((RelationshipChain) relationshipPattern).named(this.name);\n\t}\n\n\tprivate ExposesRelationships<?> applyOptionalPredicate(ExposesRelationships<?> relationshipPattern) {\n\t\tif (this.predicate == null) {\n\t\t\treturn relationshipPattern;\n\t\t}\n\t\tif (relationshipPattern instanceof Relationship relationship) {\n\t\t\treturn (ExposesRelationships<?>) relationship.where(this.predicate);\n\t\t}\n\t\treturn ((RelationshipChain) relationshipPattern).where(this.predicate);\n\t}\n\n\tprivate ExposesRelationships<?> applyOptionalQuantifier(ExposesRelationships<?> relationshipPattern) {\n\t\tif (this.quantifier == null) {\n\t\t\treturn relationshipPattern;\n\t\t}\n\t\tif (relationshipPattern instanceof Relationship relationship) {\n\t\t\treturn (ExposesRelationships<?>) relationship.quantifyRelationship(this.quantifier);\n\t\t}\n\t\treturn ((RelationshipChain) relationshipPattern).quantifyRelationship(this.quantifier);\n\t}\n\n\tDirection getDirection() {\n\t\treturn this.direction;\n\t}\n\n\tString[] getTypes() {\n\t\treturn this.types;\n\t}\n\n\tPathAtom withQuantifier(QuantifiedPathPattern.Quantifier newQuantifier) {\n\t\treturn (newQuantifier != null) ? new PathAtom(this.name, this.length, this.direction, this.negatedType,\n\t\t\t\tthis.types, this.properties, this.predicate, newQuantifier) : this;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/PathLength.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Value object for the lenght of a path.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = INTERNAL, since = \"2021.3.0\")\nfinal class PathLength {\n\n\tprivate final Integer minimum;\n\n\tprivate final Integer maximum;\n\n\tprivate final boolean unbounded;\n\n\tprivate PathLength(Integer minimum, Integer maximum) {\n\t\tthis.minimum = minimum;\n\t\tthis.maximum = maximum;\n\t\tthis.unbounded = minimum == null && maximum == null;\n\t}\n\n\tstatic PathLength of(String minimum, String maximum) {\n\t\tInteger min = ((minimum == null) || minimum.isBlank()) ? null : Integer.valueOf(minimum.trim());\n\t\tInteger max = ((maximum == null) || maximum.isBlank()) ? null : Integer.valueOf(maximum.trim());\n\t\treturn new PathLength(min, max);\n\t}\n\n\tInteger getMinimum() {\n\t\treturn this.minimum;\n\t}\n\n\tInteger getMaximum() {\n\t\treturn this.maximum;\n\t}\n\n\tboolean isUnbounded() {\n\t\treturn this.unbounded;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/PatternAtom.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\n/**\n * Artificial interface over a {@link org.neo4j.cypherdsl.core.Node} and {@link PathAtom}.\n *\n * @author Michael J. Simons\n * @since 2023.0.0\n */\ninterface PatternAtom {\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/PatternElementAsExpressionWrapper.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Condition;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.RelationshipPattern;\nimport org.neo4j.cypherdsl.core.ast.Visitor;\n\nimport static org.apiguardian.api.API.Status.INTERNAL;\n\n/**\n * Necessary for using relationship pattern as expressions.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = INTERNAL, since = \"2021.3.0\")\nfinal class PatternElementAsExpressionWrapper implements Expression {\n\n\tprivate final RelationshipPattern relationshipPattern;\n\n\tPatternElementAsExpressionWrapper(RelationshipPattern relationshipPattern) {\n\t\tthis.relationshipPattern = relationshipPattern;\n\t}\n\n\t@Override\n\tpublic void accept(Visitor visitor) {\n\t\tthis.relationshipPattern.accept(visitor);\n\t}\n\n\t@Override\n\tpublic Condition asCondition() {\n\t\treturn Cypher.matching(this.relationshipPattern);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/PatternElementCreatedEventType.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * The type of an event fired when a Cypher-DSL AST element is created.\n *\n * @author Michael J. Simons\n * @since 2022.1.1\n */\n@API(status = STABLE, since = \"2022.2.0\")\npublic enum PatternElementCreatedEventType {\n\n\t/**\n\t * A {@link org.neo4j.cypherdsl.core.PatternElement} is created during the creation of\n\t * a {@code MATCH} clause.\n\t */\n\tON_MATCH,\n\t/**\n\t * A {@link org.neo4j.cypherdsl.core.PatternElement} is created during the creation of\n\t * a {@code CREATE} clause.\n\t */\n\tON_CREATE,\n\t/**\n\t * A {@link org.neo4j.cypherdsl.core.PatternElement} is created during the creation of\n\t * a {@code MERGE} clause.\n\t */\n\tON_MERGE,\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/PatternElementFunctions.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.neo4j.cypherdsl.core.FunctionInvocation;\n\n/**\n * A list of additional pattern element functions, to avoid opening up or extending the\n * Cypher-DSLs build in API.\n *\n * @author Michael J. Simons\n */\nenum PatternElementFunctions implements FunctionInvocation.FunctionDefinition {\n\n\tSHORTEST_PATH(\"shortestPath\"), ALL_SHORTEST_PATHS(\"allShortestPaths\");\n\n\tprivate final String implementationName;\n\n\tPatternElementFunctions(String implementationName) {\n\t\tthis.implementationName = implementationName;\n\t}\n\n\t@Override\n\tpublic String getImplementationName() {\n\t\treturn this.implementationName;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/ReturnDefinition.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.List;\n\nimport org.apiguardian.api.API;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.SortItem;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * A value object containing the necessary pieces for creating a\n * {@link org.neo4j.cypherdsl.core.Return RETURN clause}. One possible producer after\n * fiddling with the elements is\n * {@link org.neo4j.cypherdsl.core.Clauses#returning(boolean, List, List, Expression, Expression)}.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = STABLE, since = \"2021.3.0\")\npublic final class ReturnDefinition {\n\n\tprivate final boolean distinct;\n\n\tprivate final List<Expression> expressions;\n\n\tprivate final List<SortItem> optionalSortItems;\n\n\tprivate final Expression optionalSkip;\n\n\tprivate final Expression optionalLimit;\n\n\tReturnDefinition(boolean distinct, List<Expression> expressions, List<SortItem> optionalSortItems,\n\t\t\tExpression optionalSkip, Expression optionalLimit) {\n\t\tthis.distinct = distinct;\n\t\tthis.expressions = expressions;\n\t\tthis.optionalSortItems = optionalSortItems;\n\t\tthis.optionalSkip = optionalSkip;\n\t\tthis.optionalLimit = optionalLimit;\n\t}\n\n\t/**\n\t * Returns <code>true</code> to indicate this return clause should return only\n\t * distinct elements.\n\t * @return <code>true</code> if the <code>DISTINCT</code> clause is present\n\t */\n\tpublic boolean isDistinct() {\n\t\treturn this.distinct;\n\t}\n\n\t/**\n\t * {@return list of expressions to be returned}\n\t */\n\tpublic List<Expression> getExpressions() {\n\t\treturn this.expressions;\n\t}\n\n\t/**\n\t * {@return list of expressions to sort the result by}\n\t */\n\tpublic List<SortItem> getOptionalSortItems() {\n\t\treturn this.optionalSortItems;\n\t}\n\n\t/**\n\t * {@return numerical expression how many items to skip}\n\t */\n\tpublic Expression getOptionalSkip() {\n\t\treturn this.optionalSkip;\n\t}\n\n\t/**\n\t * {@return numerical expression how many items to return}\n\t */\n\tpublic Expression getOptionalLimit() {\n\t\treturn this.optionalLimit;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/Statements.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.List;\n\nimport org.neo4j.cypherdsl.core.Statement;\n\nrecord Statements(List<Statement> value) {\n\tStatements {\n\t\tvalue = (value != null) ? List.copyOf(value) : List.of();\n\t}\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/TypeParsedEventType.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Type of an event when a relationship type is parsed.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = STABLE, since = \"2021.3.0\")\npublic enum TypeParsedEventType {\n\n\t/**\n\t * Parsed when creating a {@link org.neo4j.cypherdsl.core.RelationshipPattern\n\t * relationship pattern}.\n\t */\n\tON_RELATIONSHIP_PATTERN\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/UnsupportedCypherException.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.io.Serial;\n\nimport org.apiguardian.api.API;\n\nimport static org.apiguardian.api.API.Status.STABLE;\n\n/**\n * Thrown when the parser detects a clause which is not yet supported.\n *\n * @author Michael J. Simons\n * @since 2021.3.0\n */\n@API(status = STABLE, since = \"2021.3.0\")\npublic final class UnsupportedCypherException extends UnsupportedOperationException {\n\n\t@Serial\n\tprivate static final long serialVersionUID = 2871262762217922044L;\n\n\t/**\n\t * Original input to the parser.\n\t */\n\tprivate final String input;\n\n\tUnsupportedCypherException(String input, UnsupportedOperationException cause) {\n\t\tsuper(String.format(\"You used one Cypher construct not yet supported by the Cypher-DSL:%n%n\\t%s%n%n\"\n\t\t\t\t+ \"Feel free to open an issue so that we might add support for it at https://github.com/neo4j-contrib/cypher-dsl/issues/new\",\n\t\t\t\tinput), cause);\n\t\tthis.input = input;\n\t}\n\n\t/**\n\t * {@return the original Cypher input handled to the parser}\n\t */\n\tpublic String getInput() {\n\t\treturn this.input;\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/main/java/org/neo4j/cypherdsl/parser/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Parses any Neo4j 5.x Cypher statement into a Cypher-DSL AST.\n */\npackage org.neo4j.cypherdsl.parser;\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/ComparisonIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.EnumSet;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.Statement;\nimport org.neo4j.cypherdsl.core.TreeNode;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Dialect;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * Tests combining parser and builder and demonstrating comparisons\n */\nclass ComparisonIT {\n\n\tstatic Stream<Arguments> generatedNamesShouldBeGood() {\n\t\treturn Stream.of(Arguments.of(\"\"\"\n\t\t\t\tMATCH\n\t\t\t\t\t(charlie:Person {name: 'Charlie Sheen'}),\n\t\t\t\t\t(rob:Person {name: 'Rob Reiner'})\n\t\t\t\tCREATE (rob)-[:`TYPE INCLUDING A SPACE`]->(charlie)\n\t\t\t\t\"\"\", \"\"\"\n\t\t\t\tMATCH\n\t\t\t\t\t(v0:Person {name: 'Charlie Sheen'}),\n\t\t\t\t\t(v1:Person {name: 'Rob Reiner'})\n\t\t\t\tCREATE (v1)-[:`TYPE INCLUDING A SPACE`]->(v0)\n\t\t\t\t\"\"\", false), Arguments.of(\"\"\"\n\t\t\t\tMATCH (actor:Person {name: 'Charlie Sheen'})-[:ACTED_IN]->(movie:Movie)\n\t\t\t\tRETURN actor{.name, .realName, movies: collect(movie{.title, .year})};\n\t\t\t\t\"\"\", \"\"\"\n\t\t\t\tMATCH (v0:Person {name: 'Charlie Sheen'})-[:ACTED_IN]->(v1:Movie)\n\t\t\t\tRETURN v0{.name, .realName, movies: collect(v1{.title, .year})};\n\t\t\t\t\"\"\", false), Arguments.of(\"\"\"\n\t\t\t\tmatch (n:Person)\n\t\t\t\tcall {\n\t\t\t\tmatch (n:Movie {title: 'The Matrix'}) where n.released >= 1900 return n as m\n\t\t\t\t}\n\t\t\t\treturn n.name\n\t\t\t\t\"\"\", \"\"\"\n\t\t\t\tmatch (v0:Person)\n\t\t\t\tcall {\n\t\t\t\tmatch (v0:Movie {title: 'The Matrix'}) where v0.released >= 1900 return v0 as v1\n\t\t\t\t}\n\t\t\t\treturn v0.name\n\t\t\t\t\"\"\", false), Arguments.of(\"\"\"\n\t\t\t\tMATCH (n:Person {name: 'Tom Hanks'})\n\t\t\t\tCALL {\n\t\t\t\t\tWITH n\n\t\t\t\t\tMATCH (m:Movie)<-[:ACTED_IN]-(n)\n\t\t\t\t\tWHERE (m.released >= 1900\n\t\t\t\t\tAND n.born = 1956)\n\t\t\t\t\tRETURN m\n\t\t\t\t}\n\t\t\t\tRETURN n.name, m.title\n\t\t\t\t\"\"\", \"\"\"\n\t\t\t\tMATCH (v0:Person {name: 'Tom Hanks'})\n\t\t\t\tCALL {\n\t\t\t\t\tWITH v0\n\t\t\t\t\tMATCH (v1:Movie)<-[:ACTED_IN]-(v0)\n\t\t\t\t\tWHERE (v1.released >= 1900\n\t\t\t\t\tAND v0.born = 1956)\n\t\t\t\t\tRETURN v1\n\t\t\t\t}\n\t\t\t\tRETURN v0.name, v1.title\n\t\t\t\t\"\"\", false), Arguments.of(\"\"\"\n\t\t\t\tUNWIND $foo AS input\n\t\t\t\tCALL {\n\t\t\t\t\tWITH input\n\t\t\t\t\tCREATE (v0:Movie)\n\t\t\t\t\tSET v0.title = input.title\n\t\t\t\t\tRETURN v0\n\t\t\t\t}\n\t\t\t\tRETURN count(*)\n\t\t\t\t\"\"\", \"\"\"\n\t\t\t\tUNWIND $p0 AS v0\n\t\t\t\tCALL {\n\t\t\t\t\tWITH v0\n\t\t\t\t\tCREATE (v1:Movie)\n\t\t\t\t\tSET v1.title = v0.title\n\t\t\t\t\tRETURN v1\n\t\t\t\t}\n\t\t\t\tRETURN count(*)\n\t\t\t\t\"\"\", false), Arguments.of(\"\"\"\n\t\t\t\tMATCH (this:Movie)\n\t\t\t\tCALL {\n\t\t\t\t\tWITH this\n\t\t\t\t\tMATCH (this_actorsAggregate_this1:Actor)-[this_actorsAggregate_this0:ACTED_IN]->(this)\n\t\t\t\t\tRETURN {\n\t\t\t\t\t\tmin: min(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tmax: max(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\taverage: avg(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tsum: sum(this_actorsAggregate_this0.screentime)\n\t\t\t\t\t} AS this_actorsAggregate_var2\n\t\t\t\t}\n\t\t\t\tRETURN this {\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tedge: {\n\t\t\t\t\t\t\tscreentime: this_actorsAggregate_var2\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} AS this\n\t\t\t\t\"\"\", \"\"\"\n\t\t\t\tMATCH (v0:Movie)\n\t\t\t\tCALL {\n\t\t\t\t\tWITH v0\n\t\t\t\t\tMATCH (v1:Actor)-[v2:ACTED_IN]->(v0)\n\t\t\t\t\tRETURN {\n\t\t\t\t\t\tmin: min(v2.screentime),\n\t\t\t\t\t\tmax: max(v2.screentime),\n\t\t\t\t\t\taverage: avg(v2.screentime),\n\t\t\t\t\t\tsum: sum(v2.screentime)\n\t\t\t\t\t} AS v3\n\t\t\t\t}\n\t\t\t\tRETURN v0 {\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tedge: {\n\t\t\t\t\t\t\tscreentime: v3\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} AS v0\n\t\t\t\t\"\"\", false), Arguments.of(\"\"\"\n\t\t\t\tMATCH (this:Movie)\n\t\t\t\tCALL {\n\t\t\t\t\tWITH this\n\t\t\t\t\tMATCH (person:Person)-[edge:ACTED_IN]->(this)\n\t\t\t\t\tWITH *\n\t\t\t\t\tWHERE person.name CONTAINS $param0\n\t\t\t\t\tRETURN count(person) AS this_actorsAggregate_var0\n\t\t\t\t}\n\t\t\t\tCALL {\n\t\t\t\t\tWITH this\n\t\t\t\t\tMATCH (person:Person)-[edge:DIRECTED]->(this)\n\t\t\t\t\tWITH *\n\t\t\t\t\tWHERE person.name CONTAINS $param1\n\t\t\t\t\tRETURN count(person) AS this_directorsAggregate_var0\n\t\t\t\t}\n\t\t\t\tRETURN this {\n\t\t\t\t\t.title,\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tcount: this_actorsAggregate_var0\n\t\t\t\t\t},\n\t\t\t\t\tdirectorsAggregate: {\n\t\t\t\t\t\tcount: this_directorsAggregate_var0\n\t\t\t\t\t}\n\t\t\t\t} AS this\"\"\", \"\"\"\n\t\t\t\tMATCH (v0:Movie)\n\t\t\t\tCALL {\n\t\t\t\t\tWITH v0\n\t\t\t\t\tMATCH (v1:Person)-[v2:ACTED_IN]->(v0)\n\t\t\t\t\tWITH *\n\t\t\t\t\tWHERE v1.name CONTAINS $p0\n\t\t\t\t\tRETURN count(v1) AS v3\n\t\t\t\t}\n\t\t\t\tCALL {\n\t\t\t\t\tWITH v0\n\t\t\t\t\tMATCH (v1:Person)-[v2:DIRECTED]->(v0)\n\t\t\t\t\tWITH *\n\t\t\t\t\tWHERE v1.name CONTAINS $p1\n\t\t\t\t\tRETURN count(v1) AS v4\n\t\t\t\t}\n\t\t\t\tRETURN v0 {\n\t\t\t\t\t.title,\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tcount: v3\n\t\t\t\t\t},\n\t\t\t\t\tdirectorsAggregate: {\n\t\t\t\t\t\tcount: v4\n\t\t\t\t\t}\n\t\t\t\t} AS v0\n\t\t\t\t\"\"\", false), Arguments.of(\"\"\"\n\t\t\t\tMATCH (this:Movie)\n\t\t\t\tCALL {\n\t\t\t\t\tWITH this\n\t\t\t\t\tMATCH (this_actorsAggregate_this1:Person)-[this_actorsAggregate_this0:ACTED_IN]->(this)\n\t\t\t\t\tWITH *\n\t\t\t\t\tWHERE this_actorsAggregate_this1.name CONTAINS $this_actorsAggregate_param0\n\t\t\t\t\tRETURN count(this_actorsAggregate_this1) AS this_actorsAggregate_var2\n\t\t\t\t}\n\t\t\t\tCALL {\n\t\t\t\t\tWITH this\n\t\t\t\t\tMATCH (this_directorsAggregate_this1:Person)-[this_directorsAggregate_this0:DIRECTED]->(this)\n\t\t\t\t\tWITH *\n\t\t\t\t\tWHERE this_directorsAggregate_this1.name CONTAINS $this_directorsAggregate_param0\n\t\t\t\t\tRETURN count(this_directorsAggregate_this1) AS this_directorsAggregate_var2\n\t\t\t\t}\n\t\t\t\tRETURN this {\n\t\t\t\t\t.title,\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tcount: this_actorsAggregate_var2\n\t\t\t\t\t},\n\t\t\t\t\tdirectorsAggregate: {\n\t\t\t\t\t\tcount: this_directorsAggregate_var2\n\t\t\t\t\t}\n\t\t\t\t} AS this\"\"\", \"\"\"\n\t\t\t\tMATCH (v0:Movie)\n\t\t\t\tCALL {\n\t\t\t\t\tWITH v0\n\t\t\t\t\tMATCH (v1:Person)-[v2:ACTED_IN]->(v0)\n\t\t\t\t\tWITH *\n\t\t\t\t\tWHERE v1.name CONTAINS $p0\n\t\t\t\t\tRETURN count(v1) AS v3\n\t\t\t\t}\n\t\t\t\tCALL {\n\t\t\t\t\tWITH v0\n\t\t\t\t\tMATCH (v1:Person)-[v2:DIRECTED]->(v0)\n\t\t\t\t\tWITH *\n\t\t\t\t\tWHERE v1.name CONTAINS $p1\n\t\t\t\t\tRETURN count(v1) AS v4\n\t\t\t\t}\n\t\t\t\tRETURN v0 {\n\t\t\t\t\t.title,\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tcount: v3\n\t\t\t\t\t},\n\t\t\t\t\tdirectorsAggregate: {\n\t\t\t\t\t\tcount: v4\n\t\t\t\t\t}\n\t\t\t\t} AS v0\n\t\t\t\t\"\"\", false), Arguments.of(\"\"\"\n\t\t\t\tMATCH (this:Post)\n\t\t\t\tCALL {\n\t\t\t\t\tWITH this\n\t\t\t\t\tMATCH (this1:User)-[this0:LIKES]->(this)\n\t\t\t\t\tRETURN any(var2 IN collect(this0.someBigInt) WHERE var2 = $param0) AS var3\n\t\t\t\t}\n\t\t\t\tWITH *\n\t\t\t\tWHERE var3 = true\n\t\t\t\tRETURN this {\n\t\t\t\t\t.content\n\t\t\t\t} AS this\n\t\t\t\t\"\"\", \"\"\"\n\t\t\t\tMATCH (v0:Post)\n\t\t\t\tCALL {\n\t\t\t\t\tWITH v0\n\t\t\t\t\tMATCH (v1:User)-[v2:LIKES]->(v0)\n\t\t\t\t\tRETURN any(v3 IN collect(v2.someBigInt) WHERE v3 = $p0) AS v4\n\t\t\t\t}\n\t\t\t\tWITH *\n\t\t\t\tWHERE v4 = true\n\t\t\t\tRETURN v0 {\n\t\t\t\t\t.content\n\t\t\t\t} AS v0\"\"\", false),\n\t\t\t\tArguments.of(\"MATCH (n:Movie)<-[:ACTED_IN]-(p:Person)\",\n\t\t\t\t\t\t\"MATCH (v0:`Person`)-[:`ACTED_IN`]->(v1:`Movie`)\", true),\n\t\t\t\tArguments.of(\"MATCH (a:A)-[:R]->(b:B)-[:R2]->(c:C) RETURN *\",\n\t\t\t\t\t\t\"MATCH (v0:`A`)-[:`R`]->(v1:`B`)-[:`R2`]->(v2:`C`) RETURN *\", true),\n\t\t\t\tArguments.of(\"MATCH (a:A)-[:R]->(b:B)-[:R2]->(c:C), (x) --> (y) RETURN *\",\n\t\t\t\t\t\t\"MATCH (v0:`A`)-[:`R`]->(v1:`B`)-[:`R2`]->(v2:`C`), (v3)-->(v4) RETURN *\", true),\n\t\t\t\tArguments.of(\"MATCH (a:A)-[:R]->(b:B), (b)-[:R2]->(c:C) RETURN *\",\n\t\t\t\t\t\t\"MATCH (v0:`A`)-[:`R`]->(v1:`B`), (v1)-[:`R2`]->(v2:`C`) RETURN *\", true),\n\t\t\t\tArguments.of(\"MATCH (a:A)<-[:R]-(b:B)-[:R2]->(c:C), (x) --> (y) RETURN *\",\n\t\t\t\t\t\t\"MATCH (v0:`B`)-[:`R`]->(v1:`A`), (v0)-[:`R2`]->(v2:`C`), (v3)-->(v4) RETURN *\", true),\n\t\t\t\tArguments.of(\"MATCH (u:U)<-[:R3]-(a:A)<-[:R]-(b:B)-[:R2]->(c:C), (x) --> (y) RETURN *\",\n\t\t\t\t\t\t\"MATCH (v0:`A`)-[:`R3`]->(v1:`U`), (v2:`B`)-[:`R`]->(v0), (v2)-[:`R2`]->(v3:`C`), (v4)-->(v5) RETURN *\",\n\t\t\t\t\t\ttrue),\n\t\t\t\tArguments.of(\"MATCH (a:A)<-[:FOO]-(b)-[:BAR]->(c) RETURN *\",\n\t\t\t\t\t\t\"MATCH (v0)-[:`FOO`]->(v1:`A`), (v0)-[:`BAR`]->(v2) RETURN *\", true),\n\t\t\t\tArguments.of(\"MATCH (a:A)<-[:FOO]-(b:B)<-[:BAR]-(c:C) RETURN *\",\n\t\t\t\t\t\t\"MATCH (v0:`B`)-[:`FOO`]->(v1:`A`), (v2:`C`)-[:`BAR`]->(v0) RETURN *\", true));\n\t}\n\n\tstatic Stream<Arguments> generatedNamesShouldBeConfigurable() {\n\t\treturn Stream.of(Arguments.of(EnumSet.allOf(Configuration.GeneratedNames.class), \"\"\"\n\t\t\t\tMATCH (v0:Movie)\n\t\t\t\tWHERE v0.released = $p0\n\t\t\t\tCALL (v0) {\n\t\t\t\t\tMATCH (v1:Actor)-[v2:ACTED_IN]->(v0)\n\t\t\t\t\tRETURN {\n\t\t\t\t\t\tmin: min(v2.screentime),\n\t\t\t\t\t\tmax: max(v2.screentime),\n\t\t\t\t\t\taverage: avg(v2.screentime),\n\t\t\t\t\t\tsum: sum(v2.screentime)\n\t\t\t\t\t} AS v3,\n\t\t\t\t\tany(v4 IN collect(v1.someBigInt) WHERE v4 = $p1) AS v5\n\t\t\t\t}\n\t\t\t\tRETURN v0 {\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tedge: {\n\t\t\t\t\t\t\tscreentime: v3\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} AS v0\n\t\t\t\t\"\"\"), Arguments.of(EnumSet.of(Configuration.GeneratedNames.ENTITY_NAMES), \"\"\"\n\t\t\t\tMATCH (v0:Movie)\n\t\t\t\tWHERE v0.released = $releaseYear\n\t\t\t\tCALL (v0) {\n\t\t\t\t\tMATCH (v1:Actor)-[v2:ACTED_IN]->(v0)\n\t\t\t\t\tRETURN {\n\t\t\t\t\t\tmin: min(v2.screentime),\n\t\t\t\t\t\tmax: max(v2.screentime),\n\t\t\t\t\t\taverage: avg(v2.screentime),\n\t\t\t\t\t\tsum: sum(v2.screentime)\n\t\t\t\t\t} AS this_actorsAggregate_var2,\n\t\t\t\t\tany(foo IN collect(v1.someBigInt) WHERE foo = $param0) AS blerg\n\t\t\t\t}\n\t\t\t\tRETURN v0 {\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tedge: {\n\t\t\t\t\t\t\tscreentime: this_actorsAggregate_var2\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} AS this\n\t\t\t\t\"\"\"), Arguments.of(EnumSet.of(Configuration.GeneratedNames.PARAMETER_NAMES), \"\"\"\n\t\t\t\tMATCH (this:Movie)\n\t\t\t\tWHERE this.released = $p0\n\t\t\t\tCALL (this) {\n\t\t\t\t\tMATCH (this_actorsAggregate_this1:Actor)-[this_actorsAggregate_this0:ACTED_IN]->(this)\n\t\t\t\t\tRETURN {\n\t\t\t\t\t\tmin: min(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tmax: max(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\taverage: avg(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tsum: sum(this_actorsAggregate_this0.screentime)\n\t\t\t\t\t} AS this_actorsAggregate_var2,\n\t\t\t\t\tany(foo IN collect(this_actorsAggregate_this1.someBigInt) WHERE foo = $p1) AS blerg\n\t\t\t\t}\n\t\t\t\tRETURN this {\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tedge: {\n\t\t\t\t\t\t\tscreentime: this_actorsAggregate_var2\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} AS this\n\t\t\t\t\"\"\"), Arguments.of(EnumSet.of(Configuration.GeneratedNames.ALL_ALIASES), \"\"\"\n\t\t\t\tMATCH (this:Movie)\n\t\t\t\tWHERE this.released = $releaseYear\n\t\t\t\tCALL (this) {\n\t\t\t\t\tMATCH (this_actorsAggregate_this1:Actor)-[this_actorsAggregate_this0:ACTED_IN]->(this)\n\t\t\t\t\tRETURN {\n\t\t\t\t\t\tmin: min(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tmax: max(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\taverage: avg(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tsum: sum(this_actorsAggregate_this0.screentime)\n\t\t\t\t\t} AS v0,\n\t\t\t\t\tany(foo IN collect(this_actorsAggregate_this1.someBigInt) WHERE foo = $param0) AS v1\n\t\t\t\t}\n\t\t\t\tRETURN this {\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tedge: {\n\t\t\t\t\t\t\tscreentime: v0\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} AS v2\n\t\t\t\t\"\"\"), Arguments.of(EnumSet.of(Configuration.GeneratedNames.INTERNAL_ALIASES_ONLY), \"\"\"\n\t\t\t\tMATCH (this:Movie)\n\t\t\t\tWHERE this.released = $releaseYear\n\t\t\t\tCALL (this) {\n\t\t\t\t\tMATCH (this_actorsAggregate_this1:Actor)-[this_actorsAggregate_this0:ACTED_IN]->(this)\n\t\t\t\t\tRETURN {\n\t\t\t\t\t\tmin: min(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tmax: max(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\taverage: avg(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tsum: sum(this_actorsAggregate_this0.screentime)\n\t\t\t\t\t} AS v0,\n\t\t\t\t\tany(foo IN collect(this_actorsAggregate_this1.someBigInt) WHERE foo = $param0) AS v1\n\t\t\t\t}\n\t\t\t\tRETURN this {\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tedge: {\n\t\t\t\t\t\t\tscreentime: v0\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} AS this\n\t\t\t\t\"\"\"), Arguments.of(EnumSet.complementOf(EnumSet.of(Configuration.GeneratedNames.ALL_ALIASES)), \"\"\"\n\t\t\t\tMATCH (v0:Movie)\n\t\t\t\tWHERE v0.released = $p0\n\t\t\t\tCALL (v0) {\n\t\t\t\t\tMATCH (v1:Actor)-[v2:ACTED_IN]->(v0)\n\t\t\t\t\tRETURN {\n\t\t\t\t\t\tmin: min(v2.screentime),\n\t\t\t\t\t\tmax: max(v2.screentime),\n\t\t\t\t\t\taverage: avg(v2.screentime),\n\t\t\t\t\t\tsum: sum(v2.screentime)\n\t\t\t\t\t} AS v3,\n\t\t\t\t\tany(v4 IN collect(v1.someBigInt) WHERE v4 = $p1) AS v5\n\t\t\t\t}\n\t\t\t\tRETURN v0 {\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tedge: {\n\t\t\t\t\t\t\tscreentime: v3\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} AS this\n\t\t\t\t\"\"\"));\n\t}\n\n\tstatic boolean areSemanticallyEquivalent(Statement statement1, Statement statement2) {\n\n\t\tvar cfg = Configuration.newConfig().withGeneratedNames(true).build();\n\t\tvar renderer = Renderer.getRenderer(cfg);\n\t\tvar cypher1 = renderer.render(statement1);\n\t\tvar cypher2 = renderer.render(statement2);\n\n\t\treturn cypher1.equals(cypher2);\n\t}\n\n\tstatic boolean areSemanticallyEquivalent(Statement statement1, Map<String, Object> args1, Statement statement2,\n\t\t\tMap<String, Object> args2) {\n\n\t\tif (!areSemanticallyEquivalent(statement1, statement2)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar mapping1 = statement1.getCatalog().getRenamedParameters();\n\t\tvar mapping2 = statement2.getCatalog().getRenamedParameters();\n\t\tfor (Map.Entry<String, String> entry : mapping1.entrySet()) {\n\t\t\tString key1 = entry.getKey();\n\t\t\tString mapped = entry.getValue();\n\n\t\t\tString key2 = mapping2.entrySet()\n\t\t\t\t.stream()\n\t\t\t\t.filter(e -> e.getValue().equals(mapped))\n\t\t\t\t.map(Map.Entry::getKey)\n\t\t\t\t.findFirst()\n\t\t\t\t.orElseThrow();\n\t\t\tif (!args1.get(key1).equals(args2.get(key2))) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource\n\tvoid generatedNamesShouldBeGood(String in, String expected, boolean alwaysCreateRelationshipsLTR) {\n\t\tvar stmt = Renderer.getRenderer(Configuration.newConfig().withGeneratedNames(true).build())\n\t\t\t.render(CypherParser.parseStatement(in,\n\t\t\t\t\tOptions.newOptions().alwaysCreateRelationshipsLTR(alwaysCreateRelationshipsLTR).build()));\n\t\tassertThat(stmt).isEqualTo(CypherParser.parseStatement(expected).getCypher());\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource\n\tvoid generatedNamesShouldBeConfigurable(Set<Configuration.GeneratedNames> config, String expected) {\n\n\t\tvar in = \"\"\"\n\t\t\t\tMATCH (this:Movie)\n\t\t\t\tWHERE this.released = $releaseYear\n\t\t\t\tCALL (*) {\n\t\t\t\t\tMATCH (this_actorsAggregate_this1:Actor)-[this_actorsAggregate_this0:ACTED_IN]->(this)\n\t\t\t\t\tRETURN {\n\t\t\t\t\t\tmin: min(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tmax: max(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\taverage: avg(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tsum: sum(this_actorsAggregate_this0.screentime)\n\t\t\t\t\t} AS this_actorsAggregate_var2,\n\t\t\t\t\tany(foo IN collect(this_actorsAggregate_this1.someBigInt) WHERE foo = $param0) AS blerg\n\t\t\t\t}\n\t\t\t\tRETURN this {\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tedge: {\n\t\t\t\t\t\t\tscreentime: this_actorsAggregate_var2\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} AS this\n\t\t\t\t\"\"\";\n\n\t\tvar stmt = Renderer.getRenderer(Configuration.newConfig().withGeneratedNames(config).build())\n\t\t\t.render(CypherParser.parseStatement(in));\n\t\tassertThat(stmt).isEqualTo(CypherParser.parseStatement(expected).getCypher());\n\t}\n\n\t@Test\n\tvoid shouldDetectEquivalentStatements() {\n\n\t\tvar stmt1 = CypherParser.parse(\"Match (x:Movie) where x.title = $param1 RETURN x\");\n\t\tvar stmt2 = Cypher.match(Cypher.node(\"Movie\").named(\"y\"))\n\t\t\t.where(Cypher.name(\"y\").property(\"title\").eq(Cypher.parameter(\"foo\")))\n\t\t\t.returning(Cypher.name(\"y\"))\n\t\t\t.build();\n\n\t\tassertThat(areSemanticallyEquivalent(stmt1, stmt2)).isTrue();\n\t}\n\n\t@Test\n\tvoid shouldDetectEquivalentStatementsWithAnonParameters() {\n\n\t\tvar stmt1 = Cypher.match(Cypher.node(\"Movie\").named(\"x\"))\n\t\t\t.where(Cypher.name(\"x\").property(\"title\").eq(Cypher.anonParameter(\"foo\")))\n\t\t\t.returning(Cypher.name(\"x\"))\n\t\t\t.build();\n\t\tvar stmt2 = Cypher.match(Cypher.node(\"Movie\").named(\"y\"))\n\t\t\t.where(Cypher.name(\"y\").property(\"title\").eq(Cypher.anonParameter(\"bar\")))\n\t\t\t.returning(Cypher.name(\"y\"))\n\t\t\t.build();\n\n\t\tassertThat(areSemanticallyEquivalent(stmt1, stmt2)).isTrue();\n\t}\n\n\t@Test\n\tvoid shouldDetectNonEquivalentStatements() {\n\n\t\tvar stmt1 = CypherParser.parse(\"Match (x:movie) where x.title = $param1 RETURN x\");\n\t\tvar stmt2 = Cypher.match(Cypher.node(\"Movie\").named(\"y\"))\n\t\t\t.where(Cypher.name(\"y\").property(\"title\").eq(Cypher.parameter(\"foo\")))\n\t\t\t.returning(Cypher.name(\"y\"))\n\t\t\t.build();\n\n\t\tassertThat(areSemanticallyEquivalent(stmt1, stmt2)).isFalse();\n\t}\n\n\t@Test\n\tvoid shouldDetectEquivalentStatementsWithArgs() {\n\n\t\tvar stmt1 = CypherParser.parse(\"Match (x:Movie) where x.title = $param1 RETURN x\");\n\t\tvar stmt2 = Cypher.match(Cypher.node(\"Movie\").named(\"y\"))\n\t\t\t.where(Cypher.name(\"y\").property(\"title\").eq(Cypher.parameter(\"foo\")))\n\t\t\t.returning(Cypher.name(\"y\"))\n\t\t\t.build();\n\n\t\tassertThat(areSemanticallyEquivalent(stmt1, Map.of(\"param1\", \"The Matrix\"), stmt2, Map.of(\"foo\", \"The Matrix\")))\n\t\t\t.isTrue();\n\t}\n\n\t@Test\n\tvoid shouldDetectNonEquivalentStatementsWithArgs() {\n\n\t\tvar stmt1 = CypherParser.parse(\"Match (x:Movie) where x.title = $param1 RETURN x\");\n\t\tvar stmt2 = Cypher.match(Cypher.node(\"Movie\").named(\"y\"))\n\t\t\t.where(Cypher.name(\"y\").property(\"title\").eq(Cypher.parameter(\"foo\")))\n\t\t\t.returning(Cypher.name(\"y\"))\n\t\t\t.build();\n\n\t\tassertThat(areSemanticallyEquivalent(stmt1, Map.of(\"param1\", \"The Matrix\"), stmt2,\n\t\t\t\tMap.of(\"foo\", \"Matrix Resurrections\")))\n\t\t\t.isFalse();\n\t}\n\n\t@Test\n\tvoid treeCanBeUsedToAnalyseStatements() {\n\n\t\tvar stmt = CypherParser.parse(\"\"\"\n\t\t\t\tMATCH (n:Person {name: 'Tom Hanks'})\n\t\t\t\tCALL {\n\t\t\t\t  WITH n\n\t\t\t\t  MATCH (m:Movie)<-[:ACTED_IN]-(n)\n\t\t\t\t  WHERE (m.released >= 1900\n\t\t\t\t\tAND n.born = 1956)\n\t\t\t\t  RETURN m\n\t\t\t\t}\n\t\t\t\tRETURN n.name, m.title\n\t\t\t\t\"\"\");\n\n\t\tvar target = new StringBuilder();\n\t\tTreeNode.from(stmt)\n\t\t\t.printTo(target::append,\n\t\t\t\t\tnode -> (node.getValue() instanceof Statement s) ? s.getCypher() : node.getValue().toString());\n\t\tassertThat(target).hasToString(\n\t\t\t\t\"\"\"\n\t\t\t\t\t\tMATCH (n:`Person` {name: 'Tom Hanks'}) CALL (n) {MATCH (m:`Movie`)<-[:`ACTED_IN`]-(n) WHERE (m.released >= 1900 AND n.born = 1956) RETURN m} RETURN n.name, m.title\n\t\t\t\t\t\t├── Match{cypher=MATCH (n:Person {name: 'Tom Hanks'})}\n\t\t\t\t\t\t│   └── Pattern{cypher=(n:Person {name: 'Tom Hanks'})}\n\t\t\t\t\t\t│       └── InternalNodeImpl{cypher=(n:Person {name: 'Tom Hanks'})}\n\t\t\t\t\t\t│           ├── SymbolicName{cypher=n}\n\t\t\t\t\t\t│           ├── NodeLabel{value='Person'}\n\t\t\t\t\t\t│           └── Properties{cypher={name: 'Tom Hanks'}}\n\t\t\t\t\t\t│               └── MapExpression{cypher={name: 'Tom Hanks'}}\n\t\t\t\t\t\t│                   └── KeyValueMapEntry{cypher=name: 'Tom Hanks'}\n\t\t\t\t\t\t│                       └── StringLiteral{cypher='Tom Hanks'}\n\t\t\t\t\t\t├── Subquery{cypher=CALL (n) {MATCH (m:Movie)<-[:ACTED_IN]-(n) WHERE (m.released >= 1900 AND n.born = 1956) RETURN m}}\n\t\t\t\t\t\t│   └── WITH n MATCH (m:`Movie`)<-[:`ACTED_IN`]-(n) WHERE (m.released >= 1900 AND n.born = 1956) RETURN m\n\t\t\t\t\t\t│       ├── With{cypher=WITH n}\n\t\t\t\t\t\t│       │   └── ReturnBody{cypher=n}\n\t\t\t\t\t\t│       │       └── ExpressionList{cypher=n}\n\t\t\t\t\t\t│       │           └── SymbolicName{cypher=n}\n\t\t\t\t\t\t│       ├── Match{cypher=MATCH (m:Movie)<-[:ACTED_IN]-(n) WHERE (m.released >= 1900 AND n.born = 1956)}\n\t\t\t\t\t\t│       │   ├── Pattern{cypher=(m:Movie)<-[:ACTED_IN]-(n)}\n\t\t\t\t\t\t│       │   │   └── InternalRelationshipImpl{cypher=(m:Movie)<-[:ACTED_IN]-(n)}\n\t\t\t\t\t\t│       │   │       ├── InternalNodeImpl{cypher=(m:Movie)}\n\t\t\t\t\t\t│       │   │       │   ├── SymbolicName{cypher=m}\n\t\t\t\t\t\t│       │   │       │   └── NodeLabel{value='Movie'}\n\t\t\t\t\t\t│       │   │       ├── Details{cypher=<-[:ACTED_IN]-}\n\t\t\t\t\t\t│       │   │       │   └── RelationshipTypes{values=[ACTED_IN]}\n\t\t\t\t\t\t│       │   │       └── InternalNodeImpl{cypher=(n)}\n\t\t\t\t\t\t│       │   │           └── SymbolicName{cypher=n}\n\t\t\t\t\t\t│       │   └── Where{cypher=WHERE (m.released >= 1900 AND n.born = 1956)}\n\t\t\t\t\t\t│       │       └── CompoundCondition{cypher=(m.released >= 1900 AND n.born = 1956)}\n\t\t\t\t\t\t│       │           ├── Comparison{cypher=m.released >= 1900}\n\t\t\t\t\t\t│       │           │   ├── InternalPropertyImpl{cypher=m.released}\n\t\t\t\t\t\t│       │           │   │   ├── SymbolicName{cypher=m}\n\t\t\t\t\t\t│       │           │   │   └── PropertyLookup{cypher=.released}\n\t\t\t\t\t\t│       │           │   │       └── SymbolicName{cypher=released}\n\t\t\t\t\t\t│       │           │   ├── Operator{cypher=>=}\n\t\t\t\t\t\t│       │           │   └── NumberLiteral{cypher=1900}\n\t\t\t\t\t\t│       │           ├── Operator{cypher=AND}\n\t\t\t\t\t\t│       │           └── Comparison{cypher=n.born = 1956}\n\t\t\t\t\t\t│       │               ├── InternalPropertyImpl{cypher=n.born}\n\t\t\t\t\t\t│       │               │   ├── SymbolicName{cypher=n}\n\t\t\t\t\t\t│       │               │   └── PropertyLookup{cypher=.born}\n\t\t\t\t\t\t│       │               │       └── SymbolicName{cypher=born}\n\t\t\t\t\t\t│       │               ├── Operator{cypher==}\n\t\t\t\t\t\t│       │               └── NumberLiteral{cypher=1956}\n\t\t\t\t\t\t│       └── Return{cypher=RETURN m}\n\t\t\t\t\t\t│           └── ReturnBody{cypher=m}\n\t\t\t\t\t\t│               └── ExpressionList{cypher=m}\n\t\t\t\t\t\t│                   └── SymbolicName{cypher=m}\n\t\t\t\t\t\t└── Return{cypher=RETURN n.name, m.title}\n\t\t\t\t\t\t    └── ReturnBody{cypher=n.name, m.title}\n\t\t\t\t\t\t        └── ExpressionList{cypher=n.name, m.title}\n\t\t\t\t\t\t            ├── InternalPropertyImpl{cypher=n.name}\n\t\t\t\t\t\t            │   ├── SymbolicName{cypher=n}\n\t\t\t\t\t\t            │   └── PropertyLookup{cypher=.name}\n\t\t\t\t\t\t            │       └── SymbolicName{cypher=name}\n\t\t\t\t\t\t            └── InternalPropertyImpl{cypher=m.title}\n\t\t\t\t\t\t                ├── SymbolicName{cypher=m}\n\t\t\t\t\t\t                └── PropertyLookup{cypher=.title}\n\t\t\t\t\t\t                    └── SymbolicName{cypher=title}\n\t\t\t\t\t\t\"\"\");\n\t}\n\n\t@Test // GH-963\n\tvoid scopingAndNormalizingShouldWork() {\n\t\tvar cypher = \"\"\"\n\t\t\t\tCALL {\n\t\t\t\t\tCREATE (this0:Movie)\n\t\t\t\t\tWITH *\n\t\t\t\t\tCALL {\n\t\t\t\t\t\tWITH this0\n\t\t\t\t\t\treturn true\n\t\t\t\t\t}\n\t\t\t\t\tRETURN this0\n\t\t\t\t} RETURN this0\n\t\t\t\t\"\"\";\n\t\tvar cfg = Configuration.newConfig()\n\t\t\t.withPrettyPrint(true)\n\t\t\t.withGeneratedNames(true)\n\t\t\t.withDialect(Dialect.NEO4J_4)\n\t\t\t.build();\n\t\tvar renderer = Renderer.getRenderer(cfg);\n\t\tvar parseOptions = Options.newOptions().createSortedMaps(true).build();\n\t\tvar normalized = renderer.render(CypherParser.parse(cypher, parseOptions));\n\t\tassertThat(normalized).isEqualTo(\"\"\"\n\t\t\t\tCALL {\n\t\t\t\t  CREATE (v0:Movie)\n\t\t\t\t  WITH *\n\t\t\t\t  CALL {\n\t\t\t\t    WITH v0\n\t\t\t\t    RETURN true\n\t\t\t\t  }\n\t\t\t\t  RETURN v0\n\t\t\t\t}\n\t\t\t\tRETURN v0\"\"\");\n\t}\n\n\t@Test // GH-1147\n\tvoid shouldNotRecognizeLocallyScopedElementsFromExistentialSubqueries() {\n\t\tvar cypher = \"\"\"\n\t\t\t\tMATCH (this:Series)\n\t\t\t\tWHERE ((EXISTS {\n\t\t\t\tMATCH (this)-[edge:MANUFACTURER]->(this0:Manufacturer)\n\t\t\t\t\tWHERE (this0.name = $param0 AND edge.current = $param1)\n\t\t\t\t}\n\t\t\t\tOR EXISTS {\n\t\t\t\t\tMATCH (this)-[edge:MANUFACTURER]->(this1:Manufacturer)\n\t\t\t\t\tWHERE (this1.name = $param2 AND edge.current = $param3)\n\t\t\t\t})\n\t\t\t\tAND EXISTS {\n\t\t\t\t\tMATCH (this)-[edge:BRAND]->(this2:Brand)\n\t\t\t\t\tWHERE (this2.name = $param4 AND edge.current = $param5)\n\t\t\t\t})\n\t\t\t\tRETURN this\"\"\";\n\t\tvar renderer = Renderer\n\t\t\t.getRenderer(Configuration.newConfig().withPrettyPrint(true).withGeneratedNames(true).build());\n\t\tvar normalized = renderer.render(CypherParser.parse(cypher));\n\t\tassertThat(normalized).isEqualTo(\"\"\"\n\t\t\t\tMATCH (v0:Series)\n\t\t\t\tWHERE ((EXISTS {\n\t\t\t\t      MATCH (v0)-[v1:MANUFACTURER]->(v2:Manufacturer)\n\t\t\t\t      WHERE (v2.name = $p0\n\t\t\t\t        AND v1.current = $p1)\n\t\t\t\t    }\n\t\t\t\t    OR EXISTS {\n\t\t\t\t      MATCH (v0)-[v1:MANUFACTURER]->(v2:Manufacturer)\n\t\t\t\t      WHERE (v2.name = $p2\n\t\t\t\t        AND v1.current = $p3)\n\t\t\t\t    })\n\t\t\t\t  AND EXISTS {\n\t\t\t\t    MATCH (v0)-[v1:BRAND]->(v2:Brand)\n\t\t\t\t    WHERE (v2.name = $p4\n\t\t\t\t      AND v1.current = $p5)\n\t\t\t\t  })\n\t\t\t\tRETURN v0\"\"\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/CypherChallengeTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.regex.Pattern;\nimport java.util.stream.Stream;\n\nimport com.opencsv.CSVReaderBuilder;\nimport com.opencsv.exceptions.CsvValidationException;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * See <a href=\n * \"https://github.com/tomasonjo/cypher-direction-competition\">cypher-direction-competition</a>.\n *\n * @author Michael J. Simons\n */\nclass CypherChallengeTests {\n\n\tstatic Stream<Arguments> cypherFixRelChallenge() throws IOException, CsvValidationException {\n\n\t\tList<Arguments> result = new ArrayList<>();\n\t\ttry (var csvReader = new CSVReaderBuilder(new InputStreamReader(\n\t\t\t\tObjects.requireNonNull(CypherChallengeTests.class.getResourceAsStream(\"/cypher-challenge.csv\"))))\n\t\t\t.withSkipLines(1)\n\t\t\t.build()) {\n\t\t\tString[] nextRecord;\n\n\t\t\tvar p = Pattern.compile(\"\\\\(.*?\\\\)\");\n\t\t\twhile ((nextRecord = csvReader.readNext()) != null) {\n\n\t\t\t\tvar builder = Configuration.newConfig();\n\t\t\t\tvar m = p.matcher(nextRecord[1]);\n\t\t\t\twhile (m.find()) {\n\t\t\t\t\tbuilder.withRelationshipDefinition(Configuration.relationshipDefinition(m.group(0)));\n\t\t\t\t}\n\n\t\t\t\tresult.add(Arguments.of(builder.withEnforceSchema(true).build(), nextRecord[0], nextRecord[2]));\n\t\t\t}\n\t\t}\n\n\t\treturn result.stream();\n\t}\n\n\t@ParameterizedTest(name = \"{1}\")\n\t@MethodSource\n\tvoid cypherFixRelChallenge(Configuration configuration, String input, String expected) {\n\n\t\tvar statement = CypherParser.parse(input);\n\t\tvar renderer = Renderer.getRenderer(configuration);\n\t\tvar cypher = renderer.render(statement);\n\t\tvar finalExpectation = expected.isBlank() ? \"\" : CypherParser.parse(expected).getCypher();\n\t\tassertThat(cypher).isEqualTo(finalExpectation);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/CypherDslASTFactoryTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.List;\n\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.ValueSource;\nimport org.neo4j.cypherdsl.core.Cypher;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatExceptionOfType;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\n\n/**\n * @author Michael J. Simons\n */\nclass CypherDslASTFactoryTests {\n\n\t@Test\n\tvoid isInstanceOfCheckShouldWork() {\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> CypherDslASTFactory.isInstanceOf(null, null, null))\n\t\t\t.withMessage(\"Type to check against must not be null\");\n\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> CypherDslASTFactory.isInstanceOf(String.class, 42, \"Not the answer\"))\n\t\t\t.withMessage(\"Not the answer\");\n\t}\n\n\t@Test\n\tvoid infinityLiteralShouldWork() {\n\n\t\tvar factory = CypherDslASTFactory.getInstance(null);\n\t\tassertThat(factory.newInfinityLiteral(null)).isEqualTo(InfinityLiteral.INSTANCE);\n\t}\n\n\t@Test\n\tvoid nanLiteralShouldWork() {\n\n\t\tvar factory = CypherDslASTFactory.getInstance(null);\n\t\tassertThat(factory.newNaNLiteral(null)).isEqualTo(NaNLiteral.INSTANCE);\n\t}\n\n\t@Test\n\tvoid parameterLiteralNullExpressionShouldWork() {\n\n\t\tvar factory = CypherDslASTFactory.getInstance(null);\n\t\tvar parameter = factory.parameterFromSymbolicName(null);\n\t\tassertThat(parameter).isNotNull();\n\t\tassertThat(parameter.isAnon()).isTrue();\n\t}\n\n\t@Test\n\tvoid parameterFromExpressionShouldWork() {\n\n\t\tvar factory = CypherDslASTFactory.getInstance(null);\n\t\tvar parameter = factory.parameterFromSymbolicName(CypherParser.parseExpression(\"a\"));\n\t\tassertThat(parameter).isNotNull();\n\t\tassertThat(parameter.isAnon()).isFalse();\n\t}\n\n\t@Test\n\tvoid databaseName() {\n\t\tvar factory = CypherDslASTFactory.getInstance(null);\n\t\tvar databaseName = factory.databaseName(null, List.of(\"x\"));\n\t\tassertThat(databaseName).isNotNull();\n\n\t\tdatabaseName = factory.databaseName(null, List.of(\"x\", \"y\"));\n\t\tassertThat(databaseName).isNotNull();\n\n\t\tvar parameter = Cypher.parameter(\"foo\");\n\t\tdatabaseName = factory.databaseName(parameter);\n\t\tassertThat(databaseName).isNotNull();\n\t\tassertThat(databaseName.value()).isEqualTo(parameter);\n\n\t\tvar empty = List.<String>of();\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> factory.databaseName(null, empty))\n\t\t\t.withMessage(\"No database name\");\n\t}\n\n\t@Nested\n\tclass HandleNewMethods {\n\n\t\t@ParameterizedTest\n\t\t@ValueSource(strings = { \"showAliases\", \"createLocalDatabaseAlias\", \"createRemoteDatabaseAlias\",\n\t\t\t\t\"alterLocalDatabaseAlias\", \"alterRemoteDatabaseAlias\", \"fixedPathQuantifier\", \"useGraph\",\n\t\t\t\t\"setOwnPassword\", \"showAllPrivileges\", \"showRolePrivileges\", \"showUserPrivileges\", \"createDatabase\",\n\t\t\t\t\"createCompositeDatabase\", \"dropDatabase\", \"showDatabase\", \"startDatabase\", \"stopDatabase\",\n\t\t\t\t\"createUser\", \"dropUser\", \"alterUser\", \"renameUser\", \"newSensitiveStringParameter\",\n\t\t\t\t\"passwordExpression\", \"showUsers\", \"showRolePrivileges\", \"labelWildcard\",\n\t\t\t\t\"subqueryInTransactionsBatchParameters\", \"subqueryInTransactionsErrorParameters\",\n\t\t\t\t\"subqueryInTransactionsReportParameters\", \"showTransactionsClause\", \"terminateTransactionsClause\",\n\t\t\t\t\"turnYieldToWith\", \"alterDatabase\", \"settingQualifier\", \"showSettingsClause\", \"repeatableElements\",\n\t\t\t\t\"differentRelationships\", \"createConstraint\", \"dropConstraint\", \"showSupportedPrivileges\", \"isTyped\",\n\t\t\t\t\"isNotTyped\", \"functionUseClause\", \"isNormalized\", \"isNotNormalized\", \"normalizeExpression\",\n\t\t\t\t\"insertClause\", \"insertPathPattern\", \"subqueryInTransactionsBatchParameters\",\n\t\t\t\t\"subqueryInTransactionsConcurrencyParameters\", \"subqueryInTransactionsErrorParameters\", \"grantRoles\",\n\t\t\t\t\"showRoles\", \"renameRole\", \"revokeRoles\", \"auth\", \"authId\", \"password\", \"passwordChangeRequired\",\n\t\t\t\t\"databasePrivilegeScope\" })\n\t\tvoid newMethodsShouldNotBeSupportedOOTB(String methodName) {\n\t\t\tvar factory = CypherDslASTFactory.getInstance(null);\n\t\t\tvar methods = factory.getClass().getMethods();\n\t\t\tfor (var method : methods) {\n\t\t\t\tif (method.getName().equals(methodName)) {\n\t\t\t\t\tObject[] args = new Object[method.getParameterCount()];\n\t\t\t\t\tint i = 0;\n\t\t\t\t\tfor (Class<?> type : method.getParameterTypes()) {\n\t\t\t\t\t\t// Other primitives needs to be dealt with, but right now, not in\n\t\t\t\t\t\t// the mood todo t his.\n\t\t\t\t\t\targs[i++] = (type == boolean.class) ? false : null;\n\t\t\t\t\t}\n\t\t\t\t\tassertThatExceptionOfType(InvocationTargetException.class)\n\t\t\t\t\t\t.isThrownBy(() -> method.invoke(factory, args))\n\t\t\t\t\t\t.withRootCauseInstanceOf(UnsupportedOperationException.class);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tAssertions.fail(\"Didn't find method \" + methodName + \" any more\");\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/CypherParserTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.Arrays;\nimport java.util.EnumSet;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicReference;\nimport java.util.function.Predicate;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.CsvSource;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.junit.jupiter.params.provider.ValueSource;\nimport org.neo4j.cypherdsl.core.AliasedExpression;\nimport org.neo4j.cypherdsl.core.Clause;\nimport org.neo4j.cypherdsl.core.Clauses;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.FunctionInvocation;\nimport org.neo4j.cypherdsl.core.Literal;\nimport org.neo4j.cypherdsl.core.Match;\nimport org.neo4j.cypherdsl.core.Node;\nimport org.neo4j.cypherdsl.core.Parameter;\nimport org.neo4j.cypherdsl.core.RelationshipPattern;\nimport org.neo4j.cypherdsl.core.Statement;\nimport org.neo4j.cypherdsl.core.Where;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatExceptionOfType;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\nimport static org.assertj.core.api.Assertions.assertThatNoException;\nimport static org.assertj.core.api.Assertions.assertThatRuntimeException;\n\n/**\n * @author Michael J. Simons\n */\nclass CypherParserTests {\n\n\tstatic Stream<Arguments> pathMatchingAndAssignment() {\n\t\treturn Stream.of(Arguments.of(\"\"\"\n\t\t\t\tMATCH p = SHORTEST 1 (wos:Station)-[:LINK]-+(bmv:Station)\n\t\t\t\tWHERE wos.name = \"Worcester Shrub Hill\" AND bmv.name = \"Bromsgrove\"\n\t\t\t\tRETURN length(p) AS result\n\t\t\t\t\"\"\",\n\t\t\t\t\"MATCH p = SHORTEST 1 (wos:`Station`)-[:`LINK`]-+(bmv:`Station`) WHERE (wos.name = 'Worcester Shrub Hill' AND bmv.name = 'Bromsgrove') RETURN length(p) AS result\"),\n\t\t\t\tArguments.of(\"\"\"\n\t\t\t\t\t\tMATCH p = SHORTEST 2 (wos:Station)-[:LINK]-+(bmv:Station)\n\t\t\t\t\t\tWHERE wos.name = \"Worcester Shrub Hill\" AND bmv.name = \"Bromsgrove\"\n\t\t\t\t\t\tRETURN [n in nodes(p) | n.name] AS stops\n\t\t\t\t\t\t\"\"\",\n\t\t\t\t\t\t\"MATCH p = SHORTEST 2 (wos:`Station`)-[:`LINK`]-+(bmv:`Station`) WHERE (wos.name = 'Worcester Shrub Hill' AND bmv.name = 'Bromsgrove') RETURN [n IN nodes(p) | n.name] AS stops\"),\n\t\t\t\tArguments.of(\"\"\"\n\t\t\t\t\t\tMATCH p = ALL SHORTEST (wos:Station)-[:LINK]-+(bmv:Station)\n\t\t\t\t\t\tWHERE wos.name = \"Worcester Shrub Hill\" AND bmv.name = \"Bromsgrove\"\n\t\t\t\t\t\tRETURN [n in nodes(p) | n.name] AS stops\n\t\t\t\t\t\t\"\"\",\n\t\t\t\t\t\t\"MATCH p = ALL SHORTEST (wos:`Station`)-[:`LINK`]-+(bmv:`Station`) WHERE (wos.name = 'Worcester Shrub Hill' AND bmv.name = 'Bromsgrove') RETURN [n IN nodes(p) | n.name] AS stops\"),\n\t\t\t\tArguments.of(\"\"\"\n\t\t\t\t\t\tMATCH p = SHORTEST 2 GROUPS (wos:Station)-[:LINK]-+(bmv:Station)\n\t\t\t\t\t\tWHERE wos.name = \"Worcester Shrub Hill\" AND bmv.name = \"Bromsgrove\"\n\t\t\t\t\t\tRETURN [n in nodes(p) | n.name] AS stops, length(p) AS pathLength\n\t\t\t\t\t\t\"\"\",\n\t\t\t\t\t\t\"MATCH p = SHORTEST 2 GROUPS (wos:`Station`)-[:`LINK`]-+(bmv:`Station`) WHERE (wos.name = 'Worcester Shrub Hill' AND bmv.name = 'Bromsgrove') RETURN [n IN nodes(p) | n.name] AS stops, length(p) AS pathLength\"),\n\t\t\t\tArguments.of(\n\t\t\t\t\t\t\"\"\"\n\t\t\t\t\t\t\t\tMATCH path = ANY (:Station {name: 'Pershore'})-[l:LINK WHERE l.distance < 10]-+(b:Station {name: 'Bromsgrove'})\n\t\t\t\t\t\t\t\tRETURN [r IN relationships(path) | r.distance] AS distances\n\t\t\t\t\t\t\t\t\"\"\",\n\t\t\t\t\t\t\"MATCH path = ANY (:`Station` {name: 'Pershore'})-[l:`LINK` WHERE l.distance < 10]-+(b:`Station` {name: 'Bromsgrove'}) RETURN [r IN relationships(path) | r.distance] AS distances\"));\n\t}\n\n\tstatic void assertExpression(String expression) {\n\t\tassertExpression(expression, expression);\n\t}\n\n\tstatic void assertExpression(String expression, String expected) {\n\n\t\tExpression e = CypherParser.parseExpression(expression);\n\t\tassertThat(Cypher.returning(e).build().getCypher()).isEqualTo(String.format(\"RETURN %s\", expected));\n\t}\n\n\tstatic void assertNode(Node node, String cypherDslRepresentation) {\n\n\t\tassertThat(Cypher.match(node).returning(Cypher.asterisk()).build().getCypher())\n\t\t\t.isEqualTo(String.format(\"MATCH %s RETURN *\", cypherDslRepresentation));\n\t}\n\n\tprivate static Stream<Arguments> inputAndIdentifiableExpressions() {\n\t\treturn Stream.of(Arguments.of(\"\"\"\n\t\t\t\tCALL {\n\t\t\t\t\tMATCH (p:Person)-[:LIKES]->(:Technology {type: \"Java\"})\n\t\t\t\t\tRETURN p\n\n\t\t\t\t\tUNION\n\n\t\t\t\t\tMATCH (p:Person)\n\t\t\t\t\tWHERE size((p)-[:IS_FRIENDS_WITH]->()) > 1\n\t\t\t\t\tRETURN p\n\t\t\t\t}\n\t\t\t\tRETURN p.name AS person, p.birthdate AS dob\n\t\t\t\tORDER BY dob DESC\"\"\", List.of(\"person\", \"dob\")), Arguments.of(\"\"\"\n\t\t\t\tMATCH p=(start)-[*]->(finish)\n\t\t\t\tWHERE start.name = 'A' AND finish.f = 'D'\n\t\t\t\tFOREACH (n IN nodes(p) | SET n.marked = true)\"\"\", List.of(\"finish\", \"start\", \"p\")), Arguments.of(\"\"\"\n\t\t\t\tMATCH (a)\n\t\t\t\tWHERE a.name = 'Eskil'\n\t\t\t\tRETURN a.array, [x IN a.array WHERE size(x) = 3]\"\"\", List.of(\"a.array\")));\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource\n\tvoid pathMatchingAndAssignment(String in, String expected) {\n\t\tassertThat(CypherParser.parse(in).getCypher()).isEqualTo(expected);\n\t}\n\n\t@Test\n\tvoid shouldProvideANiceErrorMessage() {\n\n\t\tassertThatExceptionOfType(UnsupportedCypherException.class)\n\t\t\t.isThrownBy(() -> CypherParser.parse(\"CREATE ROLE myrole\"))\n\t\t\t.withMessage(\"You used one Cypher construct not yet supported by the Cypher-DSL:\\n\" + \"\\n\"\n\t\t\t\t\t+ \"\\tCREATE ROLE myrole\\n\" + \"\\n\"\n\t\t\t\t\t+ \"Feel free to open an issue so that we might add support for it at https://github.com/neo4j-contrib/cypher-dsl/issues/new\");\n\t}\n\n\t@Test\n\tvoid shouldParseCount() {\n\t\tassertExpression(\"Count(*)\", \"count(*)\");\n\t}\n\n\t@Test\n\tvoid shouldParseIn() {\n\t\tassertExpression(\"n in [1,2,3]\", \"n IN [1, 2, 3]\");\n\t}\n\n\t@ParameterizedTest\n\t@CsvSource(value = { \"f()| f()\", \"foo.bar()| foo.bar()\", \"foo.bar(e)| foo.bar(e)\", \"foo.bar(e,f)| foo.bar(e, f)\",\n\t\t\t\"count(distinct e,f)| count(DISTINCT e, f)\" }, delimiterString = \"|\")\n\tvoid shouldParseFunctionInvocation(String input, String expected) {\n\t\tassertExpression(input, expected);\n\t}\n\n\t@Test\n\tvoid onNewReturnItemCallbacksShouldBeApplied() {\n\n\t\tvar cnt = new AtomicInteger(0);\n\t\tvar options = Options.newOptions()\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_RETURN_ITEM, AliasedExpression.class, e -> {\n\t\t\t\tassertThat(cnt.compareAndSet(0, 1)).isTrue();\n\t\t\t\tif (e instanceof AliasedExpression) {\n\t\t\t\t\treturn (AliasedExpression) e;\n\t\t\t\t}\n\t\t\t\treturn e.as(\"foo\");\n\t\t\t})\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_RETURN_ITEM, Expression.class, e -> {\n\t\t\t\tassertThat(cnt.compareAndSet(1, 2)).isTrue();\n\t\t\t\treturn e;\n\t\t\t})\n\t\t\t.build();\n\n\t\tvar statement = CypherParser.parseStatement(\"RETURN 1\", options);\n\t\tassertThat(cnt.get()).isEqualTo(2);\n\t\tassertThat(statement.getCypher()).isEqualTo(\"RETURN 1 AS foo\");\n\t}\n\n\t@Test\n\tvoid shouldParseReturnAll() {\n\t\tvar statement1 = CypherParser.parseStatement(\"WITH 1 AS foo WITH *, 2 AS bar RETURN *\");\n\t\tassertThat(statement1.getCypher()).isEqualTo(\"WITH 1 AS foo WITH *, 2 AS bar RETURN *\");\n\n\t\tvar statement2 = CypherParser.parseStatement(\"WITH 1 AS foo WITH *, 2 AS bar RETURN foo\");\n\t\tassertThat(statement2.getCypher()).isEqualTo(\"WITH 1 AS foo WITH *, 2 AS bar RETURN foo\");\n\t}\n\n\t@ParameterizedTest\n\t@ValueSource(strings = { \"CREATE\", \"MERGE\", \"MATCH\" })\n\tvoid patternElementCallBacksShouldBeApplied(String clause) {\n\n\t\tvar builder = Options.newOptions();\n\t\tEnumSet.allOf(PatternElementCreatedEventType.class).forEach(et -> builder.withCallback(et, patternElement -> {\n\t\t\tif (patternElement instanceof Node) {\n\t\t\t\tvar existing = ((Node) patternElement).getLabels().get(0).getValue();\n\t\t\t\treturn Cypher.node(existing, \"FirstLabelAdded\");\n\t\t\t}\n\t\t\treturn patternElement;\n\t\t}).withCallback(et, patternElement -> {\n\t\t\tif (patternElement instanceof Node) {\n\t\t\t\tvar l1 = ((Node) patternElement).getLabels().get(0).getValue();\n\t\t\t\tvar l2 = ((Node) patternElement).getLabels().get(1).getValue();\n\t\t\t\treturn Cypher.node(l1, l2, \"SecondLabelAdded\");\n\t\t\t}\n\t\t\treturn patternElement;\n\t\t}));\n\n\t\tvar options = builder.build();\n\t\tvar statement = CypherParser.parseStatement(clause + \" (n:Movie) RETURN n\", options);\n\t\tassertThat(statement.getCypher())\n\t\t\t.isEqualTo(clause + \" (:`Movie`:`FirstLabelAdded`:`SecondLabelAdded`) RETURN n\");\n\t}\n\n\t@Test\n\tvoid shouldNotAllowInvalidCallbacks() {\n\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> Options.newOptions()\n\t\t\t\t.withCallback(ExpressionCreatedEventType.ON_SET_PROPERTY, Expression.class, e -> e)\n\t\t\t\t.build())\n\t\t\t.withMessage(\n\t\t\t\t\t\"The type that is produced by 'ON_SET_PROPERTY' is not compatible with interface org.neo4j.cypherdsl.core.Expression\");\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource(\"inputAndIdentifiableExpressions\")\n\tvoid parseAndIdentifyShouldWork(String cypher, List<String> expected) {\n\n\t\tvar identifiables = CypherParser.parse(cypher).getCatalog().getIdentifiableExpressions();\n\t\tassertThat(identifiables.stream().map(Cypher::format)).containsExactlyInAnyOrderElementsOf(expected);\n\t}\n\n\t@Test\n\tvoid transformingWhereShouldWork() {\n\n\t\tvar query = \"MATCH (m:Movie {title: 'The Matrix'}) WHERE m.releaseYear IS NOT NULL OR false RETURN m\";\n\t\tvar options = Options.newOptions()\n\t\t\t.withMatchClauseFactory(matchDefinition -> (Match) Clauses.match(matchDefinition.optional(),\n\t\t\t\t\tmatchDefinition.patternElements(), Where.from(Cypher.isFalse()), matchDefinition.optionalHints()))\n\t\t\t.build();\n\t\tvar cypher = CypherParser.parse(query, options).getCypher();\n\t\tassertThat(cypher).isEqualTo(\"MATCH (m:`Movie` {title: 'The Matrix'}) WHERE false RETURN m\");\n\t}\n\n\t@ParameterizedTest\n\t@CsvSource(delimiterString = \"@\",\n\t\t\ttextBlock = \"\"\"\n\t\t\t\t\tWITH ['x'] AS l MATCH (n) SET n:$(l) RETURN n@WITH ['x'] AS l MATCH (n) SET n:$(l) RETURN n\n\t\t\t\t\tWITH ['x'] AS l, ['y'] AS l2 MATCH (n) SET n:$(l):$(l2) RETURN n@WITH ['x'] AS l, ['y'] AS l2 MATCH (n) SET n:$(l):$(l2) RETURN n\n\t\t\t\t\t\"\"\")\n\tvoid labelColonConjunctionSet(String in, String expected) {\n\t\tassertThat(CypherParser.parse(in).getCypher()).isEqualTo(expected);\n\t}\n\n\t@Test\n\tvoid labelColonConjunction() {\n\t\tassertThat(CypherParser.parse(\"MATCH (a:A:B:C) RETURN a\").getCypher())\n\t\t\t.isEqualTo(\"MATCH (a:`A`:`B`:`C`) RETURN a\");\n\t}\n\n\t@Test\n\tvoid labelColonConjunctionMixed() {\n\t\tvar options = Options.newOptions()\n\t\t\t.withLabelFilter(\n\t\t\t\t\t(labelParsedEventType, strings) -> strings.stream().filter(Predicate.not(\"B\"::equals)).toList())\n\t\t\t.build();\n\t\tassertThat(CypherParser.parse(\"MATCH (a:A:B:$($trolololo):C) RETURN a\", options).getCypher())\n\t\t\t.isEqualTo(\"MATCH (a:`A`:$($trolololo):`C`) RETURN a\");\n\t}\n\n\t@Test\n\tvoid labelColonConjunction0Element() {\n\t\tvar options = Options.newOptions()\n\t\t\t.withLabelFilter((labelParsedEventType, strings) -> strings.stream().filter(s -> false).toList())\n\t\t\t.build();\n\t\tassertThat(CypherParser.parse(\"MATCH (a:A:B) RETURN a\", options).getCypher()).isEqualTo(\"MATCH (a) RETURN a\");\n\t}\n\n\t@Test\n\tvoid labelColonConjunction1Element() {\n\t\tvar options = Options.newOptions()\n\t\t\t.withLabelFilter(\n\t\t\t\t\t(labelParsedEventType, strings) -> strings.stream().filter(Predicate.not(\"B\"::equals)).toList())\n\t\t\t.build();\n\t\tassertThat(CypherParser.parse(\"MATCH (a:A:B) RETURN a\", options).getCypher())\n\t\t\t.isEqualTo(\"MATCH (a:`A`) RETURN a\");\n\t}\n\n\t@Test\n\tvoid labelColonDisjunction() {\n\t\tassertThat(CypherParser\n\t\t\t.parse(\"MATCH (wallstreet {title: 'Wall Street'})<-[:ACTED_IN|:DIRECTED]-(person) RETURN person.name\")\n\t\t\t.getCypher()).isEqualTo(\n\t\t\t\t\t\"MATCH (wallstreet {title: 'Wall Street'})<-[:`ACTED_IN`|`DIRECTED`]-(person) RETURN person.name\");\n\t}\n\n\t@Test\n\tvoid newOrEdLabels() {\n\t\tString statement = \"MATCH (:`Human`|`Occupation`)-[:`OCCUPATION`*0..1]-(h:`Human`) RETURN h\";\n\t\tStatement parsed = CypherParser.parseStatement(statement);\n\t\tvar result = parsed.getCypher();\n\t\tassertThat(result).isEqualTo(\"MATCH (:`Human`|`Occupation`)-[:`OCCUPATION`*0..1]-(h:`Human`) RETURN h\");\n\t}\n\n\t@ParameterizedTest\n\t@ValueSource(strings = { \"MATCH (h:A&B&C) RETURN h\", \"MATCH (h:!A&!B&!C) RETURN h\", \"MATCH (h:A|B|C) RETURN h\",\n\t\t\t\"MATCH (h:!A|!B|!C) RETURN h\", \"MATCH (h:A|B&C|D) RETURN h\", \"MATCH (h:A|!(B&C)|D) RETURN h\",\n\t\t\t\"MATCH (h:(A|B)&!(C|D)) RETURN h\", \"MATCH (h:(A|B)&(C|D)) RETURN h\", \"MATCH (h:!(A|B)&(C|D)) RETURN h\",\n\t\t\t\"MATCH (h:!(!(A|B)&(C|D))) RETURN h\", \"MATCH (h:A&B|C&D) RETURN h\",\n\t\t\t\"MATCH (h:(Human|Occupation|X)&!A|B|C) RETURN h\" })\n\tvoid labelExpressions(String statement) {\n\n\t\tassertParsedStatement(statement, statement);\n\t}\n\n\t@ParameterizedTest\n\t@CsvSource(textBlock = \"\"\"\n\t\t\tMATCH (h:(A&B)) RETURN h,MATCH (h:A&B) RETURN h\n\t\t\tMATCH (h:A|(B&C)|D) RETURN h,MATCH (h:A|B&C|D) RETURN h\n\t\t\tMATCH (h:(A&B)|C&D) RETURN h,MATCH (h:A&B|C&D) RETURN h\n\t\t\tMATCH (h:((A&B)|C&D)) RETURN h,MATCH (h:A&B|C&D) RETURN h\n\t\t\tMATCH (h:!!(A|B)&(C|D)) RETURN h,MATCH (h:(A|B)&(C|D)) RETURN h\n\t\t\tMATCH (h:!(!(A|B))&(C|D)) RETURN h,MATCH (h:(A|B)&(C|D)) RETURN h\n\t\t\t\"\"\")\n\tvoid optimizedLabelExpressions(String statement, String expected) {\n\n\t\tassertParsedStatement(statement, expected);\n\t}\n\n\t@ParameterizedTest\n\t@CsvSource(\n\t\t\ttextBlock = \"\"\"\n\t\t\t\t\tMATCH (n:Person WHERE n.name = 'Tom Hanks') RETURN n,MATCH (n:Person WHERE n.name = 'Tom Hanks') RETURN n\n\t\t\t\t\tMATCH (n:Person WHERE n.name = 'Tom Hanks' OR n.name = 'Bud Spencer') RETURN n,MATCH (n:Person WHERE (n.name = 'Tom Hanks' OR n.name = 'Bud Spencer')) RETURN n\n\t\t\t\t\tMATCH (n:Person WHERE n.name = 'Tom Hanks') WHERE n.born <= 2000 RETURN n,MATCH (n:Person WHERE n.name = 'Tom Hanks') WHERE n.born <= 2000 RETURN n\n\t\t\t\t\tMATCH (n:Person WHERE n.name = 'Tom Hanks' OR n.name = 'Bud Spencer') WHERE n.born <= 2000 RETURN n,MATCH (n:Person WHERE (n.name = 'Tom Hanks' OR n.name = 'Bud Spencer')) WHERE n.born <= 2000 RETURN n\n\t\t\t\t\t\"\"\")\n\tvoid whereInMatch(String statement, String expected) {\n\n\t\tassertParsedStatement(statement, expected);\n\t}\n\n\t@ParameterizedTest\n\t@CsvSource(delimiterString = \"@\",\n\t\t\ttextBlock = \"\"\"\n\t\t\t\t\tWITH ['Person', 'Director'] AS labels MATCH (directors:$(labels)) RETURN directors@WITH ['Person', 'Director'] AS labels MATCH (directors:$(labels)) RETURN directors\n\t\t\t\t\tMATCH (n:$any(['Movie', 'Actor'])) RETURN n AS nodes@MATCH (n:$any(['Movie', 'Actor'])) RETURN n AS nodes\n\t\t\t\t\tMATCH (n:$any(['Movie', 'Actor'])&`Foo`|`Bar`&$($IWantToDie)) RETURN n AS nodes@MATCH (n:$any(['Movie', 'Actor'])&Foo|Bar&$($IWantToDie)) RETURN n AS nodes\n\t\t\t\t\tMATCH (n:$($a)|$any($b)) RETURN n AS nodes@MATCH (n:$($a)|$any($b)) RETURN n AS nodes\n\t\t\t\t\t\"\"\")\n\tvoid dynamicLabelExpressions(String statement, String expected) {\n\n\t\tassertParsedStatement(statement, expected);\n\t}\n\n\tprivate static void assertParsedStatement(String statement, String expected) {\n\t\tStatement parsed = CypherParser.parseStatement(statement);\n\t\tString cypher = Renderer.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).build()).render(parsed);\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@Test\n\tvoid nodePatternInCall() {\n\n\t\tvar statement = \"\"\"\n\t\t\t\tmatch (n:Person)\n\t\t\t\tcall {\n\t\t\t\tmatch (n:Movie {title: 'The Matrix'}) where n.released >= 1900 return n as m\n\t\t\t\t}\n\t\t\t\treturn n.name\n\t\t\t\t\"\"\";\n\t\tassertParsedStatement(statement,\n\t\t\t\t\"MATCH (n:Person) CALL (*) {MATCH (n:Movie {title: 'The Matrix'}) WHERE n.released >= 1900 RETURN n AS m} RETURN n.name\");\n\t}\n\n\t@Test\n\tvoid shouldBeAbleToParseIntoSortedMaps() {\n\n\t\tvar in = \"\"\"\n\t\t\t\tMATCH (this:Movie)\n\t\t\t\tWHERE this.released = $releaseYear\n\t\t\t\tCALL {\n\t\t\t\t\tWITH this\n\t\t\t\t\tMATCH (this_actorsAggregate_this1:Actor)-[this_actorsAggregate_this0:ACTED_IN]->(this)\n\t\t\t\t\tRETURN {\n\t\t\t\t\t\tmin: min(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tmax: max(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\taverage: avg(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tsum: sum(this_actorsAggregate_this0.screentime)\n\t\t\t\t\t} AS this_actorsAggregate_var2\n\t\t\t\t}\n\t\t\t\tRETURN this {\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tedge: {\n\t\t\t\t\t\t\tscreentime: this_actorsAggregate_var2\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} AS this\n\t\t\t\t\"\"\";\n\n\t\tvar parsed = CypherParser.parse(in, Options.newOptions().createSortedMaps(true).build());\n\t\tvar cypher = Renderer.getRenderer(\n\t\t\t\tConfiguration.newConfig().withPrettyPrint(true).withIndentStyle(Configuration.IndentStyle.TAB).build())\n\t\t\t.render(parsed);\n\t\tassertThat(cypher).isEqualTo(\"\"\"\n\t\t\t\tMATCH (this:Movie)\n\t\t\t\tWHERE this.released = $releaseYear\n\t\t\t\tCALL (this) {\n\t\t\t\t\tMATCH (this_actorsAggregate_this1:Actor)-[this_actorsAggregate_this0:ACTED_IN]->(this)\n\t\t\t\t\tRETURN {\n\t\t\t\t\t\taverage: avg(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tmax: max(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tmin: min(this_actorsAggregate_this0.screentime),\n\t\t\t\t\t\tsum: sum(this_actorsAggregate_this0.screentime)\n\t\t\t\t\t} AS this_actorsAggregate_var2\n\t\t\t\t}\n\t\t\t\tRETURN this {\n\t\t\t\t\tactorsAggregate: {\n\t\t\t\t\t\tedge: {\n\t\t\t\t\t\t\tscreentime: this_actorsAggregate_var2\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} AS this\"\"\");\n\t}\n\n\t@Test // GH-729\n\tvoid fillingParametersOfParsedCypherManual() {\n\n\t\tvar oidValue = \"look ma, no Cypher injection'}) MATCH (n) DETACH DELETE n --\";\n\t\tString userProvidedCypher = \"MATCH (p:`confignode` {oid: $oid}) \"\n\t\t\t\t+ \"CALL apoc.path.subgraphAll(p, {relationshipFilter: 'BELONGS_TO_ARRAY|IN|IN_ARRAY', minLevel: 1, maxLevel: 3}) \"\n\t\t\t\t+ \"YIELD nodes, relationships \" + \"FOREACH(node in nodes |detach delete node)\" + \"RETURN nodes\";\n\n\t\tvar options = Options.newOptions()\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_NEW_PARAMETER, Parameter.class, newExpression -> {\n\t\t\t\tvar p = (Parameter<?>) newExpression;\n\t\t\t\tif (\"oid\".equals(p.getName())) {\n\t\t\t\t\treturn Cypher.parameter(p.getName(), oidValue);\n\t\t\t\t}\n\t\t\t\treturn p;\n\t\t\t})\n\t\t\t.build();\n\n\t\tvar userStatement = CypherParser.parse(userProvidedCypher, options);\n\n\t\tvar prettyPrintingRenderer = Renderer.getRenderer(Configuration.prettyPrinting());\n\t\tassertThat(prettyPrintingRenderer.render(userStatement)).isEqualTo(\"\"\"\n\t\t\t\tMATCH (p:confignode {\n\t\t\t\t  oid: $oid\n\t\t\t\t}) CALL apoc.path.subgraphAll(p, {\n\t\t\t\t  relationshipFilter: 'BELONGS_TO_ARRAY|IN|IN_ARRAY',\n\t\t\t\t  minLevel: 1,\n\t\t\t\t  maxLevel: 3\n\t\t\t\t}) YIELD nodes, relationships FOREACH (node IN nodes | DETACH DELETE node)\n\t\t\t\tRETURN nodes\"\"\");\n\n\t\tassertThat(userStatement.getCatalog().getParameters()).containsEntry(\"oid\",\n\t\t\t\t\"look ma, no Cypher injection'}) MATCH (n) DETACH DELETE n --\");\n\t}\n\n\t@Test // GH-729\n\tvoid fillingParametersOfParsedCypher() {\n\n\t\tvar oidValue = \"look ma, no Cypher injection'}) MATCH (n) DETACH DELETE n --\";\n\t\tString userProvidedCypher = \"MATCH (p:`confignode` {oid: $oid}) \"\n\t\t\t\t+ \"CALL apoc.path.subgraphAll(p, {relationshipFilter: 'BELONGS_TO_ARRAY|IN|IN_ARRAY', minLevel: 1, maxLevel: 3}) \"\n\t\t\t\t+ \"YIELD nodes, relationships \" + \"FOREACH(node in nodes |detach delete node)\" + \"RETURN nodes\";\n\n\t\tvar options = Options.newOptions().withParameterValues(Map.of(\"oid\", oidValue)).build();\n\t\tvar userStatement = CypherParser.parse(userProvidedCypher, options);\n\t\tassertThat(userStatement.getCatalog().getParameters()).containsEntry(\"oid\",\n\t\t\t\t\"look ma, no Cypher injection'}) MATCH (n) DETACH DELETE n --\");\n\t}\n\n\t@Test // GH-739\n\tvoid literalCallbacks() {\n\n\t\tvar literals = new LinkedHashSet<Literal<?>>();\n\t\tvar options = Options.newOptions()\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_NEW_LITERAL, Expression.class, l -> {\n\t\t\t\tliterals.add((Literal<?>) l);\n\t\t\t\treturn l;\n\t\t\t})\n\t\t\t.build();\n\n\t\tCypherParser.parse(\n\t\t\t\t\"RETURN NULL, 1.0 as d, 100 as l, 0x13af as h, 0o1372 as o, 'Hallo' as s, true, false, Inf, NaN\",\n\t\t\t\toptions);\n\n\t\tassertThat(literals.stream().map(Literal::getClass).distinct()).hasSize(6);\n\t\tassertThat(literals).map(Literal::asString)\n\t\t\t.containsExactly(\"NULL\", \"1.0\", \"100\", \"5039\", \"762\", \"'Hallo'\", \"true\", \"false\", \"Infinity\", \"NaN\");\n\t}\n\n\t@ParameterizedTest\n\t@CsvSource(delimiterString = \"%%\",\n\t\t\ttextBlock = \"\"\"\n\t\t\t\t\tMATCH (statement) WHERE EXISTS { MATCH (statement)-[:FOO WHERE true]->(m) WHERE false } RETURN statement %% MATCH (statement) WHERE EXISTS { MATCH (statement)-[:FOO WHERE true]->(m) WHERE false } RETURN statement\n\t\t\t\t\tMATCH (patternWithWhere) WHERE EXISTS { (patternWithWhere)-[:FOO WHERE true]->(m) WHERE false } RETURN statement %% MATCH (patternWithWhere) WHERE EXISTS { (patternWithWhere)-[:FOO WHERE true]->(m) WHERE false } RETURN statement\n\t\t\t\t\tMATCH (person:Person) WHERE COUNT { (person)-[:HAS_DOG]->(:Dog) } > 1 RETURN person.name AS name %% MATCH (person:Person) WHERE COUNT { (person)-[:HAS_DOG]->(:Dog) } > 1 RETURN person.name AS name\n\t\t\t\t\tMATCH (person:Person) WHERE COUNT { MATCH (person)-[:HAS_DOG]->(:Dog) } > 1 RETURN person.name AS name %% MATCH (person:Person) WHERE COUNT { MATCH (person)-[:HAS_DOG]->(:Dog) } > 1 RETURN person.name AS name\n\t\t\t\t\tMATCH (person:Person) WHERE COUNT { MATCH (person)-[d:HAS_DOG WHERE d.since > 10]->(:Dog) } > 1 RETURN person.name AS name %% MATCH (person:Person) WHERE COUNT { MATCH (person)-[d:HAS_DOG WHERE d.since > 10]->(:Dog) } > 1 RETURN person.name AS name\n\t\t\t\t\tMATCH (person:Person) WHERE COUNT { MATCH (person)-[d:HAS_DOG WHERE d.since > 10]->(:Dog) WHERE false} > 1 RETURN person.name AS name %% MATCH (person:Person) WHERE COUNT { MATCH (person)-[d:HAS_DOG WHERE d.since > 10]->(:Dog) WHERE false } > 1 RETURN person.name AS name\n\t\t\t\t\t\"\"\")\n\tvoid existAndCountSubqueriesWithPatternOrStatements(String input, String expected) {\n\t\tvar renderer = Renderer.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).build());\n\t\tvar cypher = renderer.render(CypherParser.parse(input));\n\t\tAssertions.assertThat(cypher).isEqualTo(expected.trim());\n\t}\n\n\t@Test // GH-903\n\tvoid variablesOfListPredicatesMustNotBeScoped() {\n\n\t\tvar cypher = \"\"\"\n\t\t\t\tMATCH (this:Movie)\n\t\t\t\tWHERE single(this0 IN [(this)-[this1:IN_GENRE]->(this0:Genre) WHERE this0.name = $param0 | 1] WHERE true)\n\t\t\t\tRETURN this { .actorCount } AS this\"\"\";\n\n\t\tvar cfg = Configuration.newConfig().withPrettyPrint(true).withGeneratedNames(true).build();\n\t\tvar renderer = Renderer.getRenderer(cfg);\n\t\tvar parseOptions = Options.newOptions().createSortedMaps(true).build();\n\t\tvar normalized = renderer.render(CypherParser.parse(cypher, parseOptions));\n\t\tassertThat(normalized).isEqualTo(\"\"\"\n\t\t\t\tMATCH (v0:Movie)\n\t\t\t\tWHERE single(v1 IN [(v0)-[v2:IN_GENRE]->(v3:Genre)\n\t\t\t\tWHERE v3.name = $p0 | 1]\n\t\t\t\tWHERE true)\n\t\t\t\tRETURN v0 {\n\t\t\t\t  .actorCount\n\t\t\t\t} AS v0\"\"\");\n\t}\n\n\t@Test // GH-999\n\tvoid subQueryFromParserScope() {\n\t\tvar cypher = \"\"\"\n\t\t\t\tCALL {\n\t\t\t\t\tCREATE (m:Movie)\n\t\t\t\t\tRETURN m\n\t\t\t\t}\n\t\t\t\tCALL {\n\t\t\t\t\tWITH m\n\t\t\t\t\tRETURN m { .title } AS movies\n\t\t\t\t}\n\t\t\t\tRETURN movies\"\"\";\n\t\tvar cfg = Configuration.newConfig().withPrettyPrint(true).withGeneratedNames(true).build();\n\t\tvar renderer = Renderer.getRenderer(cfg);\n\t\tvar parseOptions = Options.newOptions().createSortedMaps(true).build();\n\t\tvar normalized = renderer.render(CypherParser.parse(cypher, parseOptions));\n\n\t\tassertThat(normalized).isEqualTo(\"\"\"\n\t\t\t\tCALL () {\n\t\t\t\t  CREATE (v0:Movie)\n\t\t\t\t  RETURN v0\n\t\t\t\t}\n\t\t\t\tCALL (v0) {\n\t\t\t\t  RETURN v0 {\n\t\t\t\t    .title\n\t\t\t\t  } AS v1\n\t\t\t\t}\n\t\t\t\tRETURN v1\"\"\");\n\t}\n\n\t@Test\n\tvoid newConcatenate() {\n\t\tvar cypher = \"RETURN 'a' || 'B'\";\n\t\tvar cfg = Configuration.newConfig().withPrettyPrint(true).build();\n\t\tvar renderer = Renderer.getRenderer(cfg);\n\t\tvar normalized = renderer.render(CypherParser.parse(cypher));\n\t\tassertThat(normalized).isEqualTo(\"RETURN ('a' + 'B')\");\n\t}\n\n\t@Test // GH-1059\n\tvoid patternListAsLTRMustBeUnwrappedIntoRelPattern() {\n\t\tvar cypher = \"\"\"\n\t\t\t\t\tMATCH (movie:Movie)\n\t\t\t\t\tRETURN size((movie)<-[:REVIEWED]-(:Person)) AS movieReviewedByEveryTotal\n\t\t\t\t\"\"\";\n\n\t\tvar cfg = Configuration.newConfig().withGeneratedNames(true).build();\n\t\tvar renderer = Renderer.getRenderer(cfg);\n\t\tvar parseOptions = Options.newOptions().createSortedMaps(true).alwaysCreateRelationshipsLTR(true).build();\n\t\tvar normalized = renderer.render(CypherParser.parse(cypher, parseOptions));\n\t\tassertThat(normalized).isEqualTo(\"MATCH (v0:`Movie`) RETURN size((:`Person`)-[:`REVIEWED`]->(v0)) AS v1\");\n\t}\n\n\t@ParameterizedTest\n\t@CsvSource(delimiterString = \"|\", textBlock = \"\"\"\n\t\t\tRETURN trim(' asd ')               | RETURN trim(' asd ')\n\t\t\tRETURN trim(BOTH ' ' FROM ' asd ') | RETURN trim(' asd ', ' ')\n\t\t\tRETURN trim(LEADING ' ' FROM ' asd ') | RETURN ltrim(' asd ', ' ')\n\t\t\tRETURN trim(TRAILING ' ' FROM ' asd ') | RETURN rtrim(' asd ', ' ')\n\t\t\tRETURN btrim(' asd ') | RETURN btrim(' asd ')\n\t\t\tRETURN btrim(' asd ', ' ') | RETURN btrim(' asd ', ' ')\n\t\t\tRETURN ltrim(' asd ') | RETURN ltrim(' asd ')\n\t\t\tRETURN ltrim(' asd ', ' ') | RETURN ltrim(' asd ', ' ')\n\t\t\tRETURN rtrim(' asd ') | RETURN rtrim(' asd ')\n\t\t\tRETURN rtrim(' asd ', ' ') | RETURN rtrim(' asd ', ' ')\n\t\t\t\"\"\")\n\tvoid trimShouldWork(String in, String out) {\n\n\t\tvar renderer = Renderer.getRenderer(Configuration.defaultConfig());\n\t\tvar normalized = renderer.render(CypherParser.parse(in));\n\t\tassertThat(normalized).isEqualTo(out);\n\t}\n\n\t@Test\n\tvoid optionalCall() {\n\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> CypherParser.parse(\"OPTIONAL call db.awaitIndexes()\"))\n\t\t\t.withMessage(\"Cannot render optional call clause\");\n\t}\n\n\t@Test\n\tvoid optionalSubquery() {\n\t\tassertThatIllegalArgumentException()\n\t\t\t.isThrownBy(() -> CypherParser.parse(\"MATCH (n) OPTIONAL CALL() {MATCH (m)}\"))\n\t\t\t.withMessage(\"Cannot render optional subquery clause\");\n\t}\n\n\t@Test\n\tvoid unescapedThings() {\n\t\tassertThat(CypherParser.parse(\"RETURN 1 AS v$_id\").getCypher()).isEqualTo(\"RETURN 1 AS `v$_id`\");\n\t}\n\n\t@ParameterizedTest // GH-1341\n\t@CsvSource(delimiterString = \"|\",\n\t\t\ttextBlock = \"\"\"\n\t\t\t\t\t\tMATCH (c:Content) ORDER BY c.publishedDate RETURN c | MATCH (c:`Content`) ORDER BY c.publishedDate ASC RETURN c\n\t\t\t\t\t\tMATCH (c:Content) ORDER BY c.publishedDate SKIP 1 RETURN c | MATCH (c:`Content`) ORDER BY c.publishedDate ASC SKIP 1 RETURN c\n\t\t\t\t\t\tMATCH (c:Content) ORDER BY c.publishedDate LIMIT 1 RETURN c | MATCH (c:`Content`) ORDER BY c.publishedDate ASC LIMIT 1 RETURN c\n\t\t\t\t\t\tMATCH (c:Content) ORDER BY c.publishedDate SKIP 1 LIMIT 2 RETURN c | MATCH (c:`Content`) ORDER BY c.publishedDate ASC SKIP 1 LIMIT 2 RETURN c\n\t\t\t\t\t\tMATCH (c:Content) WITH c WHERE c.prop = 3 ORDER BY c.publishedDate RETURN c | MATCH (c:`Content`) WITH c WHERE c.prop = 3 ORDER BY c.publishedDate ASC RETURN c\n\t\t\t\t\t\"\"\")\n\tvoid orderByMidwayShouldWork(String in, String expected) {\n\t\tvar statement = CypherParser.parse(in);\n\t\tassertThat(statement.getCypher()).isEqualTo(expected);\n\t}\n\n\t@Nested\n\tclass RelationshipPatterns {\n\n\t\t@ParameterizedTest\n\t\t@CsvSource(nullValues = \"N/A\", value = { \"N/A, N/A\", \"N/A, 5\", \"5, N/A\", \"5, 10\", \"-,-\" })\n\t\tvoid simplePatternWithVariousLengths(String minimum, String maximum) {\n\t\t\tStringBuilder simplePattern = new StringBuilder(\"(n)-\");\n\t\t\tif (minimum != null || maximum != null) {\n\t\t\t\tsimplePattern.append(\"[*\");\n\t\t\t\tif (minimum != null && !\"-\".equals(minimum)) {\n\t\t\t\t\tsimplePattern.append(minimum);\n\t\t\t\t}\n\t\t\t\tif (!\"-\".equals(maximum)) {\n\t\t\t\t\tsimplePattern.append(\"..\");\n\t\t\t\t\tif (maximum != null) {\n\t\t\t\t\t\tsimplePattern.append(maximum);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsimplePattern.append(\"]\");\n\t\t\t}\n\t\t\tsimplePattern.append(\"->(m)\");\n\t\t\tvar rel = CypherParser.parseRelationship(simplePattern.toString());\n\t\t\tassertThat(Cypher.match(rel).returning(Cypher.asterisk()).build().getCypher())\n\t\t\t\t.isEqualTo(String.format(\"MATCH %s RETURN *\", simplePattern));\n\t\t}\n\n\t\t@ParameterizedTest\n\t\t@ValueSource(strings = { \"T\", \"T1|T2\", \"T1|T2|T3\" })\n\t\tvoid types(String types) {\n\t\t\tvar rel = CypherParser.parseRelationship(String.format(\"(n)-[:%s]->(m)\", types));\n\t\t\tassertThat(Cypher.match(rel).returning(Cypher.asterisk()).build().getCypher())\n\t\t\t\t.isEqualTo(String.format(\"MATCH (n)-[:%s]->(m) RETURN *\",\n\t\t\t\t\t\tArrays.stream(types.split(\"\\\\|\"))\n\t\t\t\t\t\t\t.map(v -> String.format(\"`%s`\", v))\n\t\t\t\t\t\t\t.collect(Collectors.joining(\"|\"))));\n\t\t}\n\n\t\t@ParameterizedTest\n\t\t@CsvSource({ \"-,-\", \"<-,-\", \"-,->\" })\n\t\tvoid direction(String left, String right) {\n\t\t\tStringBuilder simplePattern = new StringBuilder(\"(n)\").append(left).append(right).append(\"(m)\");\n\t\t\tvar rel = CypherParser.parseRelationship(simplePattern.toString());\n\t\t\tassertThat(Cypher.match(rel).returning(Cypher.asterisk()).build().getCypher())\n\t\t\t\t.isEqualTo(String.format(\"MATCH %s RETURN *\", simplePattern));\n\t\t}\n\n\t\t@Test\n\t\tvoid pointyThingAtBothSidesIsNotSupported() {\n\t\t\tassertThatIllegalArgumentException().isThrownBy(() -> CypherParser.parseRelationship(\"(n)<-->(m)\"))\n\t\t\t\t.withMessage(\"Only left-to-right, right-to-left or unidirectional path elements are supported.\");\n\t\t}\n\n\t\t@Test\n\t\tvoid chain() {\n\t\t\tRelationshipPattern rel = CypherParser.parseRelationship(\"(n)-->()-->(o)\");\n\t\t\tassertThat(Cypher.match(rel).returning(Cypher.asterisk()).build().getCypher())\n\t\t\t\t.isEqualTo(\"MATCH (n)-->()-->(o) RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shortestPath() {\n\t\t\tExpression ex = CypherParser.parseExpression(\"shortestPath((n:A)-->(o:B))\");\n\t\t\tassertThat(Cypher.returning(ex).build().getCypher()).isEqualTo(\"RETURN shortestPath((n:`A`)-->(o:`B`))\");\n\t\t}\n\n\t\t@Test\n\t\tvoid allShortestPaths() {\n\t\t\tExpression ex = CypherParser.parseExpression(\"allShortestPaths((n:A)-->(o:B))\");\n\t\t\tassertThat(Cypher.returning(ex).build().getCypher())\n\t\t\t\t.isEqualTo(\"RETURN allShortestPaths((n:`A`)-->(o:`B`))\");\n\t\t}\n\n\t\t@Test\n\t\tvoid names() {\n\t\t\tRelationshipPattern rel = CypherParser.parseRelationship(\"(n)-[r1]->()-[r2]->(o)\");\n\t\t\tassertThat(Cypher.match(rel).returning(Cypher.asterisk()).build().getCypher())\n\t\t\t\t.isEqualTo(\"MATCH (n)-[r1]->()-[r2]->(o) RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid properties() {\n\t\t\tRelationshipPattern rel = CypherParser.parseRelationship(\"(n)-[{a: 'b', c: 'd'}]->(o)\");\n\t\t\tassertThat(Cypher.match(rel).returning(Cypher.asterisk()).build().getCypher())\n\t\t\t\t.isEqualTo(\"MATCH (n)-[ {a: 'b', c: 'd'}]->(o) RETURN *\");\n\t\t}\n\n\t\t@Test\n\t\tvoid propertiesOnAChain() {\n\t\t\tRelationshipPattern rel = CypherParser\n\t\t\t\t.parseRelationship(\"(n)-[r:TYPE{x:'x'}]->(m)-[{a: 'b', c: 'd'}]->(o)\");\n\t\t\tassertThat(Cypher.match(rel).returning(Cypher.asterisk()).build().getCypher())\n\t\t\t\t.isEqualTo(\"MATCH (n)-[r:`TYPE` {x: 'x'}]->(m)-[ {a: 'b', c: 'd'}]->(o) RETURN *\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass Literals {\n\n\t\t@Test\n\t\tvoid shouldParseListLiteral() {\n\t\t\tassertExpression(\"[1,2,a, 'b']\", \"[1, 2, a, 'b']\");\n\t\t}\n\n\t\t@Test\n\t\tvoid shouldParseLookups() {\n\t\t\tassertExpression(\"n[23]\", \"n[23]\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass Parameters {\n\n\t\t@Test\n\t\tvoid newParameterShouldWork() {\n\t\t\tassertExpression(\"$foo\", \"$foo\");\n\t\t}\n\n\t\t@Test\n\t\tvoid newNumberedParameterShouldWork() {\n\t\t\tassertExpression(\"$1\", \"$1\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass Predicates {\n\n\t\t@Test\n\t\tvoid any() {\n\n\t\t\tassertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> CypherParser.parseExpression(\"any(color IN n.liked_colors)\"))\n\t\t\t\t.withMessage(\"any(...) requires a WHERE predicate\");\n\t\t\tassertExpression(\"any(color IN n.liked_colors WHERE color = 'yellow')\");\n\t\t}\n\n\t\t@Test\n\t\tvoid none() {\n\n\t\t\tassertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> CypherParser.parseExpression(\"none(color IN n.liked_colors)\"))\n\t\t\t\t.withMessage(\"none(...) requires a WHERE predicate\");\n\t\t\tassertExpression(\"none(color IN n.liked_colors WHERE color = 'yellow')\");\n\t\t}\n\n\t\t@Test\n\t\tvoid single() {\n\n\t\t\tassertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> CypherParser.parseExpression(\"single(color IN n.liked_colors)\"))\n\t\t\t\t.withMessage(\"single(...) requires a WHERE predicate\");\n\t\t\tassertExpression(\"single(color IN n.liked_colors WHERE color = 'yellow')\");\n\t\t}\n\n\t\t@Test\n\t\tvoid all() {\n\n\t\t\tassertThatIllegalArgumentException()\n\t\t\t\t.isThrownBy(() -> CypherParser.parseExpression(\"all(color IN n.liked_colors)\"))\n\t\t\t\t.withMessage(\"all(...) requires a WHERE predicate\");\n\t\t\tassertExpression(\"all(color IN n.liked_colors WHERE color = 'yellow')\");\n\t\t}\n\n\t}\n\n\t@Nested\n\tclass InvocationCallbacks {\n\n\t\t@Test\n\t\tvoid onNewFunctionCallbacksShouldBeInvoked() {\n\n\t\t\tvar functions = new AtomicInteger(0);\n\t\t\tvar options = Options.newOptions()\n\t\t\t\t// The best: doing nothing\n\t\t\t\t.withCallback(InvocationCreatedEventType.ON_INVOCATION, Expression.class, e -> {\n\t\t\t\t\tassertThat(functions.compareAndSet(0, 1)).isTrue();\n\t\t\t\t\treturn e;\n\t\t\t\t})\n\t\t\t\t// Example of rewriting a function\n\t\t\t\t.withCallback(InvocationCreatedEventType.ON_INVOCATION, FunctionInvocation.class, e -> {\n\t\t\t\t\tassertThat(functions.compareAndSet(1, 2)).isTrue();\n\t\t\t\t\tif (\"asString\".equals(e.getFunctionName())) {\n\t\t\t\t\t\tAtomicReference<Expression> args = new AtomicReference<>();\n\t\t\t\t\t\te.accept(segment -> {\n\t\t\t\t\t\t\tif (!(segment instanceof FunctionInvocation) && segment instanceof Expression expression) {\n\t\t\t\t\t\t\t\targs.compareAndSet(null, expression);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn (FunctionInvocation) Cypher.call(\"toString\").withArgs(args.get()).asFunction();\n\t\t\t\t\t}\n\t\t\t\t\treturn e;\n\t\t\t\t})\n\t\t\t\t.build();\n\n\t\t\tvar statement = CypherParser.parseStatement(\"RETURN asString(1) AS x\", options);\n\t\t\tassertThat(functions.get()).isEqualTo(2);\n\t\t\tassertThat(statement.getCypher()).isEqualTo(\"RETURN toString(1) AS x\");\n\t\t}\n\n\t\t@Test\n\t\tvoid onNewProcedureCallbacksShouldBeInvoked() {\n\n\t\t\tvar procedures = new AtomicInteger(0);\n\t\t\tvar options = Options.newOptions().withCallback(InvocationCreatedEventType.ON_CALL, Clause.class, e -> {\n\t\t\t\tassertThat(procedures.compareAndSet(0, 1)).isTrue();\n\t\t\t\treturn e;\n\t\t\t}).withCallback(InvocationCreatedEventType.ON_CALL, Clause.class, e -> {\n\t\t\t\tassertThat(procedures.compareAndSet(1, 2)).isTrue();\n\t\t\t\treturn e;\n\t\t\t}).build();\n\n\t\t\tvar statement = CypherParser.parseStatement(\n\t\t\t\t\t\"call { call dbms.showCurrentUser() yield username return username} return username\", options);\n\t\t\tassertThat(procedures.get()).isEqualTo(2);\n\t\t\tassertThat(statement.getCypher())\n\t\t\t\t.isEqualTo(\"CALL () {CALL dbms.showCurrentUser() YIELD username RETURN username} RETURN username\");\n\t\t}\n\n\t\t@Test\n\t\tvoid preventingProcedureCalls() {\n\t\t\tvar options = Options.newOptions().withCallback(InvocationCreatedEventType.ON_CALL, Clause.class, e -> {\n\t\t\t\tthrow new RuntimeException(\"Procedure calls are not allowed!\");\n\t\t\t}).build();\n\n\t\t\tassertThatRuntimeException()\n\t\t\t\t.isThrownBy(() -> CypherParser.parseStatement(\n\t\t\t\t\t\t\"call { call dbms.showCurrentUser() yield username return username} return username\", options))\n\t\t\t\t.withRootCauseInstanceOf(RuntimeException.class)\n\t\t\t\t.withStackTraceContaining(\"Procedure calls are not allowed!\");\n\n\t\t\tassertThatNoException().isThrownBy(() -> CypherParser\n\t\t\t\t.parseStatement(\"call {match (n:Movie) return n.title as title} return title\", options));\n\t\t}\n\n\t\t@Test\n\t\tvoid preventingFunctionCalls() {\n\t\t\tvar options = Options.newOptions()\n\t\t\t\t.withCallback(InvocationCreatedEventType.ON_INVOCATION, FunctionInvocation.class,\n\t\t\t\t\t\tfunctionInvocation -> {\n\t\t\t\t\t\t\tif (\"id\".equals(functionInvocation.getFunctionName())) {\n\t\t\t\t\t\t\t\tthrow new RuntimeException(\"id must not be used anymore\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn functionInvocation;\n\t\t\t\t\t\t})\n\t\t\t\t.build();\n\n\t\t\tfor (String invalidQuery : List.of(\"MATCH (n) RETURN id(n)\",\n\t\t\t\t\t\"MATCH (n) WHERE id(n) = $id RETURN n, {__id: id(n), __labels: labels(n)} AS __node__\")) {\n\t\t\t\tCypherParser.parseExpression(invalidQuery, options);\n\t\t\t\tassertThatRuntimeException().isThrownBy(() -> CypherParser.parseStatement(invalidQuery, options))\n\t\t\t\t\t.withRootCauseInstanceOf(RuntimeException.class)\n\t\t\t\t\t.withStackTraceContaining(\"id must not be used anymore\");\n\t\t\t}\n\n\t\t\tassertThatNoException()\n\t\t\t\t.isThrownBy(() -> CypherParser.parseStatement(\"MATCH (n) RETURN elementId(n)\", options));\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/ExtractionIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.List;\nimport java.util.Set;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.Operator;\nimport org.neo4j.cypherdsl.core.Statement;\nimport org.neo4j.cypherdsl.core.StatementCatalog.Clause;\nimport org.neo4j.cypherdsl.core.StatementCatalog.Property;\nimport org.neo4j.cypherdsl.core.StatementCatalog.Token;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.GeneralizedRenderer;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * The test does really not belong here, as the core is under test, not the parser, but as\n * Christophe already was so kind providing the test queries… ¯\\_(ツ)_/¯\n *\n * @author Michael J. Simons\n * @author Christophe Willemsen\n */\nclass ExtractionIT {\n\n\tprivate static final Configuration CYPHER_RENDERER_CONFIGURATION = Configuration.newConfig()\n\t\t.alwaysEscapeNames(false)\n\t\t.build();\n\n\tprivate static final GeneralizedRenderer RENDERER = Renderer.getRenderer(CYPHER_RENDERER_CONFIGURATION,\n\t\t\tGeneralizedRenderer.class);\n\n\tprivate static final Token FOLLOWS = Token.type(\"FOLLOWS\");\n\n\tprivate static final Token TRANSACTS_WITH = Token.type(\"TRANSACTS_WITH\");\n\n\tprivate static final Token PERSON = Token.label(\"Person\");\n\n\tprivate static final Token ACTIVE = Token.label(\"Active\");\n\n\tprivate static final Token EVENT = Token.label(\"Event\");\n\n\tprivate static final Token CHECKED_IN_EVENT = Token.type(\"CHECKED_IN_EVENT\");\n\n\tprivate static final Token OFFICER = Token.label(\"Officer\");\n\n\tprivate static final Token MOVIE = Token.label(\"Movie\");\n\n\tprivate static final Property PERSON_NAME = new Property(PERSON, \"name\");\n\n\tprivate static final Property DATE = new Property(\"date\");\n\n\tprivate static final Property LAST_SEEN_DATE = new Property(\"lastSeenDate\");\n\n\tprivate static final Property NAME = new Property(\"name\");\n\n\tprivate static final Property FOLLOWS_ID = new Property(FOLLOWS, \"id\");\n\n\tprivate static final Property PERSON_ID = new Property(PERSON, \"id\");\n\n\tprivate static final Property EVENT_POSITION = new Property(EVENT, \"position\");\n\n\tprivate static final Property OFFICER_NAME = new Property(OFFICER, \"name\");\n\n\tprivate static final Property PERSON_BORN = new Property(PERSON, \"born\");\n\n\tprivate static final Property MOVIE_RELEASED = new Property(MOVIE, \"released\");\n\n\tprivate static final Property MOVIE_TITLE = new Property(MOVIE, \"title\");\n\tstatic final List<TestData> TEST_DATA = List.of(\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (n:Person {name: $name})\n\t\t\t\t\tRETURN n, COUNT { (n)--() } AS degree\n\t\t\t\t\t\"\"\", List.of(PERSON), List.of(), List.of(PERSON_NAME),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, PERSON_NAME, \"n.name\", Operator.EQUALITY, \"$name\",\n\t\t\t\t\t\t\tSet.of(\"name\")))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (n:Person) WHERE n.name = $name\n\t\t\t\t\tRETURN n, COUNT { (n)--() } AS degree\n\t\t\t\t\t\"\"\", List.of(PERSON), List.of(), List.of(PERSON_NAME),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, PERSON_NAME, \"n.name\", Operator.EQUALITY, \"$name\",\n\t\t\t\t\t\t\tSet.of(\"name\")))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (n) WHERE id(n) = $id\n\t\t\t\t\tMATCH (n)-[:CHECKED_IN_EVENT]->(e)\n\t\t\t\t\tWHERE e.date CONTAINS \"-\"\n\t\t\t\t\tWITH n, e, date(e.date) AS date\n\t\t\t\t\tWITH n, e ORDER BY date\n\t\t\t\t\tWITH n, head(collect(e)) AS event\n\t\t\t\t\tRETURN datetime(event.date + 'T23:59:59Z') AS lastSeenDate, $id AS id\n\t\t\t\t\t\"\"\", List.of(), List.of(CHECKED_IN_EVENT), List.of(DATE),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, DATE, \"e.date\", Operator.CONTAINS, \"'-'\", Set.of()))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (n) WHERE id(n) = $id\n\t\t\t\t\tWITH n\n\t\t\t\t\tMATCH (n)-[:CHECKED_IN_EVENT]->(e)\n\t\t\t\t\tWHERE e.date CONTAINS \"-\"\n\t\t\t\t\tWITH n, e, date(e.date) AS date\n\t\t\t\t\tWITH n, e ORDER BY date\n\t\t\t\t\tWITH n, head(collect(e)) AS event\n\t\t\t\t\tRETURN datetime(event.date + 'T23:59:59Z') AS lastSeenDate, $id AS id\n\t\t\t\t\t\"\"\", List.of(), List.of(CHECKED_IN_EVENT), List.of(DATE),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, DATE, \"e.date\", Operator.CONTAINS, \"'-'\", Set.of()))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (n) WHERE n.name = $name\n\t\t\t\t\tAND n.lastSeenDate > datetime() - duration({hours: 12})\n\t\t\t\t\tRETURN n\n\t\t\t\t\t\"\"\", List.of(), List.of(), List.of(NAME, LAST_SEEN_DATE), List.of(\n\t\t\t\t\tnew TestDataComparison(Clause.MATCH, NAME, \"n.name\", Operator.EQUALITY, \"$name\", Set.of(\"name\")),\n\t\t\t\t\tnew TestDataComparison(Clause.MATCH, LAST_SEEN_DATE, \"n.lastSeenDate\", Operator.GREATER_THAN,\n\t\t\t\t\t\t\t\"(datetime() - duration({hours: 12}))\", Set.of()))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (n)-[r:FOLLOWS]->(v)\n\t\t\t\t\tWHERE r.id < 25\n\t\t\t\t\tMATCH (v)-[r2]->(x)\n\t\t\t\t\tWHERE r2.computed = false\n\t\t\t\t\tRETURN count(*) AS matches\n\t\t\t\t\t\"\"\", List.of(), List.of(FOLLOWS), List.of(FOLLOWS_ID, new Property(\"computed\")), List.of(\n\t\t\t\t\tnew TestDataComparison(Clause.MATCH, FOLLOWS_ID, \"r.id\", Operator.LESS_THAN, \"25\", Set.of()),\n\t\t\t\t\tnew TestDataComparison(Clause.MATCH, new Property(\"computed\"), \"r2.computed\", Operator.EQUALITY,\n\t\t\t\t\t\t\t\"false\", Set.of()))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (n)-[r:FOLLOWS]->(v)\n\t\t\t\t\tMATCH (v)-[r2:TRANSACTS_WITH]->(x)\n\t\t\t\t\tWHERE r2.computed = false\n\t\t\t\t\tRETURN count(*) AS matches\n\t\t\t\t\t\"\"\", List.of(), List.of(FOLLOWS, TRANSACTS_WITH), List.of(new Property(TRANSACTS_WITH, \"computed\")),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, new Property(TRANSACTS_WITH, \"computed\"),\n\t\t\t\t\t\t\t\"r2.computed\", Operator.EQUALITY, \"false\", Set.of()))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (n:Person {name: \"John Doe\"})\n\t\t\t\t\tWHERE n:Active\n\t\t\t\t\tRETURN n\n\t\t\t\t\t\"\"\", List.of(PERSON, ACTIVE), List.of(), List.of(PERSON_NAME),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, PERSON_NAME, \"n.name\", Operator.EQUALITY, \"'John Doe'\",\n\t\t\t\t\t\t\tSet.of()))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (n:Person)\n\t\t\t\t\tWHERE 12 > n.id\n\t\t\t\t\tRETURN n\n\t\t\t\t\t\"\"\", List.of(PERSON), List.of(), List.of(PERSON_ID),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, PERSON_ID, \"12\", Operator.GREATER_THAN, \"n.id\",\n\t\t\t\t\t\t\tSet.of()))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (n:Event)\n\t\t\t\t\tWHERE point.distance($point, n.position) < 1000\n\t\t\t\t\tRETURN n\n\t\t\t\t\t\"\"\", List.of(EVENT), List.of(), List.of(EVENT_POSITION),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, EVENT_POSITION, \"point.distance($point, n.position)\",\n\t\t\t\t\t\t\tOperator.LESS_THAN, \"1000\", Set.of(\"point\")))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (n:Event)\n\t\t\t\t\tWHERE point.withinBox(n.position, $lowerLeft, $upperRight)\n\t\t\t\t\tRETURN n\n\t\t\t\t\t\"\"\", List.of(EVENT), List.of(), List.of(EVENT_POSITION),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, EVENT_POSITION,\n\t\t\t\t\t\t\t\"point.withinBox(n.position, $lowerLeft, $upperRight)\", null, null,\n\t\t\t\t\t\t\tSet.of(\"lowerLeft\", \"upperRight\")))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tUNWIND $names AS name\n\t\t\t\t\tMATCH (n:Person {name: name})\n\t\t\t\t\tRETURN n\n\t\t\t\t\t\"\"\", List.of(PERSON), List.of(), List.of(PERSON_NAME),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, PERSON_NAME, \"n.name\", Operator.EQUALITY, \"name\",\n\t\t\t\t\t\t\tSet.of()))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (a:Officer),(b:Officer)\n\t\t\t\t\tWHERE a.name CONTAINS 'MR. ISAAC ELBAZ'\n\t\t\t\t\tAND b.name CONTAINS 'Stephanie J. Bridges'\n\t\t\t\t\tMATCH (a)-[r:OFFICER_OF|INTERMEDIARY_OF|REGISTERED_ADDRESS*..10]-(b)\n\t\t\t\t\tWHERE r.isActive = $activeFlag\n\t\t\t\t\tRETURN p\n\t\t\t\t\tLIMIT 50\n\t\t\t\t\t\"\"\", List.of(OFFICER),\n\t\t\t\t\tList.of(Token.type(\"OFFICER_OF\"), Token.type(\"INTERMEDIARY_OF\"), Token.type(\"REGISTERED_ADDRESS\")),\n\t\t\t\t\tList.of(OFFICER_NAME,\n\t\t\t\t\t\t\tnew Property(Set.of(Token.type(\"OFFICER_OF\"), Token.type(\"INTERMEDIARY_OF\"),\n\t\t\t\t\t\t\t\t\tToken.type(\"REGISTERED_ADDRESS\")), \"isActive\")),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, OFFICER_NAME, \"a.name\", Operator.CONTAINS,\n\t\t\t\t\t\t\t\"'MR. ISAAC ELBAZ'\", Set.of()),\n\t\t\t\t\t\t\tnew TestDataComparison(Clause.MATCH, OFFICER_NAME, \"b.name\", Operator.CONTAINS,\n\t\t\t\t\t\t\t\t\t\"'Stephanie J. Bridges'\", Set.of()),\n\t\t\t\t\t\t\tnew TestDataComparison(Clause.MATCH,\n\t\t\t\t\t\t\t\t\tnew Property(Set.of(Token.type(\"OFFICER_OF\"), Token.type(\"INTERMEDIARY_OF\"),\n\t\t\t\t\t\t\t\t\t\t\tToken.type(\"REGISTERED_ADDRESS\")), \"isActive\"),\n\t\t\t\t\t\t\t\t\t\"r.isActive\", Operator.EQUALITY, \"$activeFlag\", Set.of(\"activeFlag\")))),\n\t\t\tnew TestData(\" MATCH (p:Person) -[:ACTED_IN {as: 'Neo'}] -> (m:Movie)\", List.of(PERSON, MOVIE),\n\t\t\t\t\tList.of(Token.type(\"ACTED_IN\")), List.of(new Property(Token.type(\"ACTED_IN\"), \"as\")),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, new Property(Token.type(\"ACTED_IN\"), \"as\"), \".as\",\n\t\t\t\t\t\t\tOperator.EQUALITY, \"'Neo'\", Set.of()))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tmatch (n:Person)\n\t\t\t\t\tcall {\n\t\t\t\t\tmatch (n:Movie {title: 'The Matrix'}) where n.released >= 1900 return n as m\n\t\t\t\t\t}\n\t\t\t\t\treturn n.name\n\t\t\t\t\t\"\"\", List.of(PERSON, MOVIE), List.of(), List.of(PERSON_NAME, MOVIE_TITLE, MOVIE_RELEASED),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, MOVIE_TITLE, \"n.title\", Operator.EQUALITY,\n\t\t\t\t\t\t\t\"'The Matrix'\", Set.of()),\n\t\t\t\t\t\t\tnew TestDataComparison(Clause.MATCH, MOVIE_RELEASED, \"n.released\",\n\t\t\t\t\t\t\t\t\tOperator.GREATER_THAN_OR_EQUAL_TO, \"1900\", Set.of()))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (n:Person {name: 'Tom Hanks'})\n\t\t\t\t\tCALL {\n\t\t\t\t\t  WITH n\n\t\t\t\t\t  MATCH (m:Movie)<-[:ACTED_IN]-(n)\n\t\t\t\t\t  WHERE (m.released >= 1900\n\t\t\t\t\t    AND n.born = 1956)\n\t\t\t\t\t  RETURN m\n\t\t\t\t\t}\n\t\t\t\t\tRETURN n.name, m.title\n\t\t\t\t\t\"\"\", List.of(PERSON, MOVIE), List.of(Token.type(\"ACTED_IN\")),\n\t\t\t\t\tList.of(PERSON_NAME, PERSON_BORN, MOVIE_RELEASED, MOVIE_TITLE),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, PERSON_NAME, \"n.name\", Operator.EQUALITY,\n\t\t\t\t\t\t\t\"'Tom Hanks'\", Set.of()),\n\t\t\t\t\t\t\tnew TestDataComparison(Clause.MATCH, PERSON_BORN, \"n.born\", Operator.EQUALITY, \"1956\",\n\t\t\t\t\t\t\t\t\tSet.of()),\n\t\t\t\t\t\t\tnew TestDataComparison(Clause.MATCH, MOVIE_RELEASED, \"m.released\",\n\t\t\t\t\t\t\t\t\tOperator.GREATER_THAN_OR_EQUAL_TO, \"1900\", Set.of()))),\n\t\t\tnew TestData(null, Cypher\n\t\t\t\t.match(Cypher.node(\"Person\").named(\"n\").withProperties(\"name\", Cypher.literalOf(\"Tom Hanks\")))\n\t\t\t\t.call(Cypher.match(Cypher.node(\"Movie\").named(\"m\").relationshipFrom(Cypher.anyNode(\"n\"), \"ACTED_IN\"))\n\t\t\t\t\t.where(Cypher.anyNode(\"m\")\n\t\t\t\t\t\t.property(\"released\")\n\t\t\t\t\t\t.gte(Cypher.literalOf(1900))\n\t\t\t\t\t\t.and(Cypher.anyNode(\"n\").property(\"born\").eq(Cypher.literalOf(1956))))\n\t\t\t\t\t.returning(Cypher.anyNode(\"m\"))\n\t\t\t\t\t.build(), Cypher.anyNode(\"n\"))\n\t\t\t\t.returning(Cypher.anyNode(\"n\").property(\"name\"), Cypher.anyNode(\"m\").property(\"title\"))\n\t\t\t\t.build(), List.of(PERSON, MOVIE), List.of(Token.type(\"ACTED_IN\")),\n\t\t\t\t\tList.of(PERSON_NAME, PERSON_BORN, MOVIE_RELEASED, MOVIE_TITLE),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, PERSON_NAME, \"n.name\", Operator.EQUALITY,\n\t\t\t\t\t\t\t\"'Tom Hanks'\", Set.of()),\n\t\t\t\t\t\t\tnew TestDataComparison(Clause.MATCH, PERSON_BORN, \"n.born\", Operator.EQUALITY, \"1956\",\n\t\t\t\t\t\t\t\t\tSet.of()),\n\t\t\t\t\t\t\tnew TestDataComparison(Clause.MATCH, MOVIE_RELEASED, \"m.released\",\n\t\t\t\t\t\t\t\t\tOperator.GREATER_THAN_OR_EQUAL_TO, \"1900\", Set.of()))),\n\t\t\tnew TestData(\"\"\"\n\t\t\t\t\tMATCH (n:Person WHERE n.name = 'Tom Hanks')\n\t\t\t\t\tCALL {\n\t\t\t\t\t  WITH n\n\t\t\t\t\t  MATCH (m:Movie)<-[:ACTED_IN]-(n)\n\t\t\t\t\t  WHERE (m.released >= 1900\n\t\t\t\t\t    AND n.born = 1956)\n\t\t\t\t\t  RETURN m\n\t\t\t\t\t}\n\t\t\t\t\tWITH n, m\n\t\t\t\t\tWHERE m.title = 'Apollo 13'\n\t\t\t\t\tRETURN n, m\n\t\t\t\t\t\"\"\", List.of(PERSON, MOVIE), List.of(Token.type(\"ACTED_IN\")),\n\t\t\t\t\tList.of(PERSON_NAME, PERSON_BORN, MOVIE_RELEASED, MOVIE_TITLE),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, PERSON_NAME, \"n.name\", Operator.EQUALITY,\n\t\t\t\t\t\t\t\"'Tom Hanks'\", Set.of()),\n\t\t\t\t\t\t\tnew TestDataComparison(Clause.MATCH, PERSON_BORN, \"n.born\", Operator.EQUALITY, \"1956\",\n\t\t\t\t\t\t\t\t\tSet.of()),\n\t\t\t\t\t\t\tnew TestDataComparison(Clause.MATCH, MOVIE_RELEASED, \"m.released\",\n\t\t\t\t\t\t\t\t\tOperator.GREATER_THAN_OR_EQUAL_TO, \"1900\", Set.of()),\n\t\t\t\t\t\t\tnew TestDataComparison(Clause.WITH, MOVIE_TITLE, \"m.title\", Operator.EQUALITY,\n\t\t\t\t\t\t\t\t\t\"'Apollo 13'\", Set.of()))),\n\t\t\tnew TestData(\"CREATE (n:Foo {m: 'Bar'})\", List.of(Token.label(\"Foo\")), List.of(),\n\t\t\t\t\tList.of(new Property(Token.label(\"Foo\"), \"m\")),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.CREATE, new Property(Token.label(\"Foo\"), \"m\"), \"n.m\",\n\t\t\t\t\t\t\tOperator.EQUALITY, \"'Bar'\", Set.of()))),\n\t\t\tnew TestData(\"MATCH (n:Foo {m: 'Bar'}) DELETE n\", List.of(Token.label(\"Foo\")), List.of(),\n\t\t\t\t\tList.of(new Property(Token.label(\"Foo\"), \"m\")),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, new Property(Token.label(\"Foo\"), \"m\"), \"n.m\",\n\t\t\t\t\t\t\tOperator.EQUALITY, \"'Bar'\", Set.of()))),\n\t\t\tnew TestData(\"MERGE (n:Foo {m: 'Bar'})\", List.of(Token.label(\"Foo\")), List.of(),\n\t\t\t\t\tList.of(new Property(Token.label(\"Foo\"), \"m\")),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MERGE, new Property(Token.label(\"Foo\"), \"m\"), \"n.m\",\n\t\t\t\t\t\t\tOperator.EQUALITY, \"'Bar'\", Set.of()))),\n\t\t\tnew TestData(\n\t\t\t\t\t\"MATCH (m:`Movie` {title: 'The Matrix'})<-[a:`ACTED_IN`]-(p:`Person`) WHERE p.born >= $born RETURN p\",\n\t\t\t\t\tList.of(MOVIE, PERSON), List.of(Token.type(\"ACTED_IN\")), List.of(MOVIE_TITLE, PERSON_BORN),\n\t\t\t\t\tList.of(new TestDataComparison(Clause.MATCH, MOVIE_TITLE, \"m.title\", Operator.EQUALITY,\n\t\t\t\t\t\t\t\"'The Matrix'\", Set.of()),\n\t\t\t\t\t\t\tnew TestDataComparison(Clause.MATCH, PERSON_BORN, \"p.born\",\n\t\t\t\t\t\t\t\t\tOperator.GREATER_THAN_OR_EQUAL_TO, \"$born\", Set.of(\"born\")))));\n\n\tstatic Stream<Arguments> extractionShouldWork() {\n\t\treturn TEST_DATA.stream().map(Arguments::of);\n\t}\n\n\t@SuppressWarnings(\"removal\")\n\t@ParameterizedTest\n\t@MethodSource\n\tvoid extractionShouldWork(TestData testData) {\n\t\tvar statement = (testData.statement() == null) ? CypherParser.parse(testData.query()) : testData.statement();\n\t\tvar catalog = statement.getCatalog();\n\n\t\tassertThat(catalog.getNodeLabels()).containsExactlyInAnyOrderElementsOf(testData.expectedLabels());\n\t\tassertThat(catalog.getRelationshipTypes()).containsExactlyInAnyOrderElementsOf(testData.expectedTypes());\n\t\tassertThat(catalog.getProperties()).containsExactlyInAnyOrderElementsOf(testData.expectedProperties());\n\t\tif (testData.expectedComparisons != null) {\n\t\t\tfor (TestDataComparison expectedComparison : testData.expectedComparisons()) {\n\t\t\t\tassertThat(catalog.getFilters(expectedComparison.property()))\n\t\t\t\t\t.allMatch(v -> testData.expectedComparisons()\n\t\t\t\t\t\t.contains(new TestDataComparison(v.clause(), expectedComparison.property,\n\t\t\t\t\t\t\t\t(v.left() == null) ? null : RENDERER.render(v.left()), v.operator(),\n\t\t\t\t\t\t\t\t(v.right() == null) ? null : RENDERER.render(v.right()), v.parameterNames())));\n\t\t\t}\n\t\t}\n\t}\n\n\trecord TestDataComparison(Clause clause, Property property, String left, Operator operator, String right,\n\t\t\tSet<String> parameterNames) {\n\t}\n\n\trecord TestData(String query, Statement statement, List<Token> expectedLabels, List<Token> expectedTypes,\n\t\t\tList<Property> expectedProperties, List<TestDataComparison> expectedComparisons) {\n\n\t\tTestData(String query, List<Token> expectedLabels, List<Token> expectedTypes,\n\t\t\t\tList<Property> expectedProperties) {\n\t\t\tthis(query, null, expectedLabels, expectedTypes, expectedProperties, null);\n\t\t}\n\n\t\tTestData(String query, List<Token> expectedLabels, List<Token> expectedTypes, List<Property> expectedProperties,\n\t\t\t\tList<TestDataComparison> expectedComparisons) {\n\t\t\tthis(query, null, expectedLabels, expectedTypes, expectedProperties, expectedComparisons);\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn (this.query == null) ? \"(Statement based)\" : this.query;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/IdentifiableExpressionsTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.List;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.AliasedExpression;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * More of a test for the core itself, but it's easier to just parse the already existing\n * queries here and use that AST than recreate them manually.\n *\n * @author Christophe Willemsen\n * @author Michael J. Simons\n */\nclass IdentifiableExpressionsTests {\n\n\tstatic final List<TestData> TEST_DATA = List.of(new TestData(\"\"\"\n\t\t\tMATCH (n)-[:PING_EVENT]->(e)\n\t\t\tWITH n, e WHERE e.date CONTAINS \"-\"\n\t\t\tWITH n, e, date(e.date) AS date\n\t\t\tWITH n, e ORDER BY date\n\t\t\tWITH n, head(collect(e)) AS event\n\t\t\tRETURN id(n) AS id, datetime(event.date + 'T23:59:59Z') AS lastSeenDate\n\t\t\t\"\"\", List.of(\"id\", \"lastSeenDate\")), new TestData(\"\"\"\n\t\t\tMATCH (p:Person)\n\t\t\twhere id(p) = $id\n\t\t\twith p\n\t\t\tMATCH (p)-[:KNOWS]-(kp:Person)\n\t\t\tWITH p, count(distinct kp) AS knows_people_count\n\t\t\tMATCH (p)-[:KNOWS]-(kpc:Person)-[:PARTY_TO]->(:Crime)\n\t\t\tWITH p, knows_people_count, count(distinct kpc) as knows_criminals_count\n\t\t\tWITH p, toInteger((100*knows_criminals_count/toFloat(knows_people_count))) as score\n\t\t\tCALL apoc.when(\n\t\t\tEXISTS((p)-[:PARTY_TO]->(:Crime)),\n\t\t\t'RETURN 100 as score',\n\t\t\t'RETURN score as score',\n\t\t\t{p:p, score: score}) YIELD value\n\t\t\treturn id(p) as id,  value.score as criminalRiskScore\n\t\t\t\"\"\", List.of(\"id\", \"criminalRiskScore\")), new TestData(\"\"\"\n\t\t\tMATCH (p:Person)\n\t\t\twhere id(p) = $id\n\t\t\twith p\n\t\t\tMATCH (p)-[:KNOWS]-(kp:Person)\n\t\t\tWITH p, count(distinct kp) AS knows_people_count\n\t\t\tMATCH (p)-[:KNOWS]-(kpc:Person)-[:PARTY_TO]->(:Crime)\n\t\t\tWITH p, knows_people_count, count(distinct kpc) as knows_criminals_count\n\t\t\tWITH p, toInteger((100*knows_criminals_count/toFloat(knows_people_count))) as score\n\t\t\treturn id(p) as id,  score as criminalRiskScore\n\t\t\t\"\"\", List.of(\"id\", \"criminalRiskScore\")), new TestData(\"\"\"\n\t\t\tMATCH (p:Person)-[:PARTY_TO]->(c:Crime)\n\t\t\tWHERE id(p) = $id\n\t\t\tRETURN $id AS id, True AS criminal\n\t\t\t\"\"\", List.of(\"id\", \"criminal\")), new TestData(\"\"\"\n\t\t\tmatch (l:Location)<-[]-(c:Crime)<-[]-(v:Vehicle)\n\t\t\twhere id(v) = $id\n\t\t\treturn id(v) as id, l.geospatial as location\n\t\t\t\"\"\", List.of(\"id\", \"location\")), new TestData(\"\"\"\n\t\t\tMATCH (n) WHERE id(n) = $id\n\t\t\tRETURN n.name STARTS WITH 'Ar' AS badLink, $id AS id\n\t\t\t\"\"\", List.of(\"badLink\", \"id\")), new TestData(\"\"\"\n\t\t\tMATCH (k:Keyword)-[:DESCRIBES]->(a)\n\t\t\tWHERE id(k) = $id\n\t\t\tWITH k, collect(DISTINCT a.time) AS timestamps\n\t\t\tRETURN timestamps, id(k) as id\n\t\t\t\"\"\", List.of(\"timestamps\", \"id\")), new TestData(\"\"\"\n\t\t\tMATCH (k:Keyword)-[:DESCRIBES]->(a)\n\t\t\tWHERE id(k) = $id\n\t\t\tWITH k, size(collect(DISTINCT a.time)) AS numberOfRoles, [1, 2, 3] AS roles\n\t\t\tRETURN apoc.coll.randomItems(roles, numberOfRoles, true) AS roles, id(k) AS id\n\t\t\t\"\"\", List.of(\"roles\", \"id\")), new TestData(\"\"\"\n\t\t\tMATCH (n) WHERE id(n) = $id + 10000\n\t\t\tRETURN id(n) AS id, 'Reviewed' IN labels(n) AS reviewed\n\t\t\t\"\"\", List.of(\"id\", \"reviewed\")), new TestData(\"\"\"\n\t\t\tMATCH (n) WHERE id(n) = $id\n\t\t\tRETURN $id AS id, COUNT { (n)-[:INVESTED]->() } AS totalInvestments\n\t\t\t\"\"\", List.of(\"id\", \"totalInvestments\")), new TestData(\"\"\"\n\t\t\tMATCH (n:Person)-[:HAS_PHONE]->(p:Phone)\n\t\t\twhere id(p) = $id\n\t\t\treturn id(p) as id, n.full_name as owner\n\t\t\t\"\"\", List.of(\"id\", \"owner\")), new TestData(\"\"\"\n\t\t\tMATCH (e:Entity)-[:IN_CLUSTER]->(c)\n\t\t\tWHERE id(c) = $id\n\t\t\tRETURN $id as id, point({latitude: avg(e.latitude), longitude:avg(e.longitude)}) as coordinates_cluster\n\t\t\t\"\"\", List.of(\"id\", \"coordinates_cluster\")), new TestData(\"\"\"\n\t\t\tMATCH (o)<-[:ORG_GROUP]-(:Organization)<-[:AWARDED_TO]-(g:Grant)\n\t\t\tWHERE id(o)= $id\n\t\t\tWITH distinct g, o\n\t\t\tRETURN id(o) as id, sum(g.amount) as `grant_amount`\n\t\t\t\"\"\", List.of(\"id\", \"grant_amount\")), new TestData(\"\"\"\n\t\t\tMATCH (p:Person)-[:LIVES_IN]->(l:Location)\n\t\t\tWHERE id(p) = $id\n\t\t\tRETURN $id AS id, p.pleasant_temperature_threshold <= l.ga_day_temp as IsTemperatureOK\n\t\t\t\"\"\", List.of(\"id\", \"IsTemperatureOK\")), new TestData(\"\"\"\n\t\t\tMATCH (p:Person) WHERE p.email = $node.values.email\n\t\t\tMATCH (c:Certification) WHERE c.name=\"Neo4j Certified Professional\"\n\t\t\tRETURN $id as id, exists((p)-[:HAS_CERTIFICATION]->(c)) as neoCertified\n\t\t\t\"\"\", List.of(\"id\", \"neoCertified\")), new TestData(\"\"\"\n\t\t\tMATCH (n) WHERE id(n) = $id\n\t\t\tRETURN 'https://www.google.com/search?q=' + replace(n.name,' ','+') AS googleSearchUrl, $id AS id\n\t\t\t\"\"\", List.of(\"googleSearchUrl\", \"id\")));\n\n\tstatic Stream<Arguments> testGetIdentifiableElementsFromQuery() {\n\t\treturn TEST_DATA.stream().map(Arguments::of);\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource\n\tvoid testGetIdentifiableElementsFromQuery(TestData testData) {\n\t\tvar statement = CypherParser.parse(testData.query());\n\t\tvar elements = statement.getCatalog().getIdentifiableExpressions().stream().map(e -> {\n\t\t\tif (e instanceof AliasedExpression) {\n\t\t\t\treturn ((AliasedExpression) e).getAlias();\n\t\t\t}\n\t\t\treturn ((SymbolicName) e).getValue();\n\t\t}).toList();\n\t\tassertThat(elements).hasSameElementsAs(testData.expected());\n\t}\n\n\trecord TestData(String query, List<String> expected) {\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/OptionsTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.function.UnaryOperator;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatNoException;\n\n/**\n * @author Michael J. Simons\n */\nclass OptionsTests {\n\n\t@Test // GH-299\n\tvoid patternElementCallBacksShouldBeConfigurable() {\n\n\t\tvar builder = Options.newOptions()\n\t\t\t.withCallback(PatternElementCreatedEventType.ON_CREATE, UnaryOperator.identity());\n\t\tvar options = builder.build();\n\t\tassertThat(options.getOnNewPatternElementCallbacks()).containsKey(PatternElementCreatedEventType.ON_CREATE);\n\t\tassertThat(options.getOnNewPatternElementCallbacks().get(PatternElementCreatedEventType.ON_CREATE)).hasSize(1);\n\n\t\tbuilder.withCallback(PatternElementCreatedEventType.ON_CREATE, UnaryOperator.identity());\n\t\toptions = builder.build();\n\t\tassertThat(options.getOnNewPatternElementCallbacks()).containsKey(PatternElementCreatedEventType.ON_CREATE);\n\t\tassertThat(options.getOnNewPatternElementCallbacks().get(PatternElementCreatedEventType.ON_CREATE)).hasSize(2);\n\t}\n\n\t@Test // GH-785\n\tvoid optionsMustAllowNullParameterValues() {\n\t\tMap<String, Object> wurst = new HashMap<>();\n\t\twurst.put(\"salat\", null);\n\t\tvar builder = Options.newOptions();\n\t\tassertThatNoException().isThrownBy(() -> builder.withParameterValues(wurst));\n\t}\n\n\t@Test // Grrr aaargh sonar, that code was there before, but alas, here's your 75%.\n\tvoid nullParameterShouldResetThings() {\n\n\t\tMap<String, Object> wurst = new HashMap<>();\n\t\twurst.put(\"salat\", null);\n\t\tvar builder = Options.newOptions();\n\t\tbuilder.withParameterValues(wurst);\n\t\tOptions options = builder.build();\n\t\tassertThat(options.getParameterValues()).containsEntry(\"salat\", null);\n\t\tbuilder.withParameterValues(null);\n\t\toptions = builder.build();\n\t\tassertThat(options.getParameterValues()).isEmpty();\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/ParserIssuesIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.EnumSource;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Dialect;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\nclass ParserIssuesIT {\n\n\tprivate final Configuration rendererConfig = Configuration.newConfig()\n\t\t.withPrettyPrint(true)\n\t\t.withGeneratedNames(true)\n\t\t.withDialect(Dialect.NEO4J_4)\n\t\t.build();\n\n\t@Test // GH-1076\n\tvoid parsingDeeplyNestedSubqueriesThenNormalizeShouldWork() {\n\t\tvar cypher = \"\"\"\n\t\t\t\tMATCH (this:Movie)\n\t\t\t\tWHERE this.title = $param0\n\t\t\t\tCALL {\n\t\t\t\t\tWITH this\n\t\t\t\t\tMATCH (this)<-[this0:ACTED_IN]-(this1:Actor)\n\t\t\t\t\tWITH collect( {\n\t\t\t\t\t\tnode: this1,\n\t\t\t\t\t\trelationship: this0\n\t\t\t\t\t}) AS edges\n\t\t\t\t\tWITH edges, size(edges) AS totalCount\n\t\t\t\t\tCALL {\n\t\t\t\t\t\tWITH edges\n\t\t\t\t\t\tUNWIND edges AS edge\n\t\t\t\t\t\tWITH edge.node AS this1, edge.relationship AS this0\n\t\t\t\t\t\tCALL {\n\t\t\t\t\t\t\tWITH this1\n\t\t\t\t\t\t\tMATCH (this1)-[this2:ACTED_IN]->(this3:Movie)\n\t\t\t\t\t\t\tWITH collect( {\n\t\t\t\t\t\t\t\tnode: this3,\n\t\t\t\t\t\t\t\trelationship: this2\n\t\t\t\t\t\t\t}) AS edges\n\t\t\t\t\t\t\tWITH edges, size(edges) AS totalCount\n\t\t\t\t\t\t\tRETURN {\n\t\t\t\t\t\t\t\ttotalCount: totalCount\n\t\t\t\t\t\t\t} AS var9\n\t\t\t\t\t\t}\n\t\t\t\t\t\tRETURN collect( {\n\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\tscreenTime: this0.screenTime,\n\t\t\t\t\t\t\t\t__resolveType: 'ActedIn'\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tnode: {\n\t\t\t\t\t\t\t\tname: this1.name,\n\t\t\t\t\t\t\t\tmoviesConnection: var9,\n\t\t\t\t\t\t\t\t__resolveType: 'Actor'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}) AS var10\n\t\t\t\t\t}\n\t\t\t\t\tRETURN {\n\t\t\t\t\t\tedges: var10,\n\t\t\t\t\t\ttotalCount: totalCount\n\t\t\t\t\t} AS var11\n\t\t\t\t}\n\t\t\t\tRETURN this {\n\t\t\t\t\t.title,\n\t\t\t\t\tactorsConnection: var11\n\t\t\t\t} AS this\n\t\t\t\t\"\"\";\n\t\tvar renderer = Renderer.getRenderer(this.rendererConfig);\n\t\tvar normalized = renderer.render(CypherParser.parse(cypher, Options.defaultOptions()));\n\t\tassertThat(normalized).isEqualTo(\"\"\"\n\t\t\t\tMATCH (v0:Movie)\n\t\t\t\tWHERE v0.title = $p0\n\t\t\t\tCALL {\n\t\t\t\t  WITH v0\n\t\t\t\t  MATCH (v0)<-[v1:ACTED_IN]-(v2:Actor)\n\t\t\t\t  WITH collect( {\n\t\t\t\t    node: v2,\n\t\t\t\t    relationship: v1\n\t\t\t\t  }) AS v3\n\t\t\t\t  WITH v3, size(v3) AS v4\n\t\t\t\t  CALL {\n\t\t\t\t    WITH v3\n\t\t\t\t    UNWIND v3 AS v5\n\t\t\t\t    WITH v5.node AS v6, v5.relationship AS v7\n\t\t\t\t    CALL {\n\t\t\t\t      WITH v6\n\t\t\t\t      MATCH (v6)-[v0:ACTED_IN]->(v1:Movie)\n\t\t\t\t      WITH collect( {\n\t\t\t\t        node: v1,\n\t\t\t\t        relationship: v0\n\t\t\t\t      }) AS v2\n\t\t\t\t      WITH v2, size(v2) AS v4\n\t\t\t\t      RETURN {\n\t\t\t\t        totalCount: v4\n\t\t\t\t      } AS v8\n\t\t\t\t    }\n\t\t\t\t    RETURN collect( {\n\t\t\t\t      properties: {\n\t\t\t\t        screenTime: v7.screenTime,\n\t\t\t\t        __resolveType: 'ActedIn'\n\t\t\t\t      },\n\t\t\t\t      node: {\n\t\t\t\t        name: v6.name,\n\t\t\t\t        moviesConnection: v8,\n\t\t\t\t        __resolveType: 'Actor'\n\t\t\t\t      }\n\t\t\t\t    }) AS v9\n\t\t\t\t  }\n\t\t\t\t  RETURN {\n\t\t\t\t    edges: v9,\n\t\t\t\t    totalCount: v4\n\t\t\t\t  } AS v10\n\t\t\t\t}\n\t\t\t\tRETURN v0 {\n\t\t\t\t  .title,\n\t\t\t\t  actorsConnection: v10\n\t\t\t\t} AS v0\"\"\");\n\t}\n\n\t@Test // GH-1075\n\tvoid unionPartsMustBeExportedToScope() {\n\n\t\tvar cypher = \"\"\"\n\t\t\t\tMATCH (this:Actor)\n\t\t\t\tCALL {\n\t\t\t\t\tWITH this\n\t\t\t\t\tCALL {\n\t\t\t\t\t\tWITH this\n\t\t\t\t\t\tMATCH (this)-[this0:ACTED_IN]->(this1:Movie)\n\t\t\t\t\t\tWITH {\n\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\tscreenTime: this0.screenTime\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tnode: {\n\t\t\t\t\t\t\t\t__resolveType: 'Movie',\n\t\t\t\t\t\t\t\t\ttitle: this1.title\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} AS edge\n\t\t\t\t\t\tRETURN edge\n\t\t\t\t\t\tUNION\n\t\t\t\t\t\tWITH this\n\t\t\t\t\t\tMATCH (this)-[this2:ACTED_IN]->(this3:Series)\n\t\t\t\t\t\tWITH {\n\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\tscreenTime: this2.screenTime\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tnode: {\n\t\t\t\t\t\t\t\t__resolveType: 'Series',\n\t\t\t\t\t\t\t\t\tepisodes: this3.episodes,\n\t\t\t\t\t\t\t\t\ttitle: this3.title\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} AS edge\n\t\t\t\t\t\tRETURN edge\n\t\t\t\t\t}\n\t\t\t\t\tWITH collect(edge) AS edges\n\t\t\t\t\tRETURN {\n\t\t\t\t\t\tedges: edges\n\t\t\t\t\t} AS var4\n\t\t\t\t}\n\t\t\t\tRETURN this {\n\t\t\t\t\t.name,\n\t\t\t\t\tactedInConnection: var4\n\t\t\t\t} AS this\n\t\t\t\t\"\"\";\n\t\tvar renderer = Renderer.getRenderer(this.rendererConfig);\n\t\tvar normalized = renderer.render(CypherParser.parse(cypher));\n\n\t\tassertThat(normalized).isEqualTo(\"\"\"\n\t\t\t\tMATCH (v0:Actor)\n\t\t\t\tCALL {\n\t\t\t\t  WITH v0\n\t\t\t\t  CALL {\n\t\t\t\t    WITH v0\n\t\t\t\t    MATCH (v0)-[v1:ACTED_IN]->(v2:Movie)\n\t\t\t\t    WITH {\n\t\t\t\t      properties: {\n\t\t\t\t        screenTime: v1.screenTime\n\t\t\t\t      },\n\t\t\t\t      node: {\n\t\t\t\t        __resolveType: 'Movie',\n\t\t\t\t        title: v2.title\n\t\t\t\t      }\n\t\t\t\t    } AS v3\n\t\t\t\t    RETURN v3 UNION\n\t\t\t\t    WITH v0\n\t\t\t\t    MATCH (v0)-[v4:ACTED_IN]->(v5:Series)\n\t\t\t\t    WITH {\n\t\t\t\t      properties: {\n\t\t\t\t        screenTime: v4.screenTime\n\t\t\t\t      },\n\t\t\t\t      node: {\n\t\t\t\t        __resolveType: 'Series',\n\t\t\t\t        episodes: v5.episodes,\n\t\t\t\t        title: v5.title\n\t\t\t\t      }\n\t\t\t\t    } AS v3\n\t\t\t\t    RETURN v3\n\t\t\t\t  }\n\t\t\t\t  WITH collect(v3) AS v1\n\t\t\t\t  RETURN {\n\t\t\t\t    edges: v1\n\t\t\t\t  } AS v2\n\t\t\t\t}\n\t\t\t\tRETURN v0 {\n\t\t\t\t  .name,\n\t\t\t\t  actedInConnection: v2\n\t\t\t\t} AS v0\"\"\");\n\t}\n\n\t@Test\n\tvoid projectionsShouldBeSortedToo() {\n\t\tvar cypher = \"\"\"\n\t\t\t\tMATCH (user:User)\n\t\t\t\treturn user {\n\t\t\t\t   .title,\n\t\t\t\t   b: 'B',\n\t\t\t\t   .*,\n\t\t\t\t   a: 'A'\n\t\t\t\t } AS user\n\t\t\t\t\"\"\";\n\n\t\tvar statement = CypherParser.parse(cypher, Options.newOptions().createSortedMaps(true).build());\n\n\t\tvar renderer = Renderer.getRenderer(this.rendererConfig);\n\t\tvar normalized = renderer.render(statement);\n\t\tassertThat(normalized).isEqualTo(\"\"\"\n\t\t\t\tMATCH (v0:User)\n\t\t\t\tRETURN v0 {\n\t\t\t\t  a: 'A',\n\t\t\t\t  b: 'B',\n\t\t\t\t  .*,\n\t\t\t\t  .title\n\t\t\t\t} AS v0\"\"\");\n\t}\n\n\t@Test\n\tvoid aliasesShouldBeReusedToo() {\n\t\tvar q1 = \"\"\"\n\t\t\t\tMATCH (this:Film:Multimedia)\n\t\t\t\tCALL {\n\t\t\t\t\tWITH this\n\t\t\t\t\tMATCH (this_actors:Actor:Person)-[this0:ACTED_IN]->(this)\n\t\t\t\t\tWITH this_actors {\n\t\t\t\t\t\t.name\n\t\t\t\t\t} AS this_actors\n\t\t\t\t\tRETURN collect(this_actors) AS this_actors\n\t\t\t\t}\n\t\t\t\tRETURN this {\n\t\t\t\t\t.title,\n\t\t\t\t\tactors: this_actors\n\t\t\t\t} AS this\n\t\t\t\t\"\"\";\n\n\t\tvar q2 = \"\"\"\n\t\t\t\tMATCH (this:Film:Multimedia)\n\t\t\t\tCALL {\n\t\t\t\t\tWITH this\n\t\t\t\t\tMATCH (actor0:Actor:Person)-[actedIn0:ACTED_IN]->(this)\n\t\t\t\t\tWITH actor0 {\n\t\t\t\t\t\t.name\n\t\t\t\t\t} AS actors\n\t\t\t\t\tRETURN collect(actors) AS actors\n\t\t\t\t}\n\t\t\t\tRETURN this {\n\t\t\t\t\t.title,\n\t\t\t\t\tactors: actors\n\t\t\t\t} AS this\n\t\t\t\t\"\"\";\n\n\t\tvar parserConfig = Options.newOptions().createSortedMaps(true).alwaysCreateRelationshipsLTR(true).build();\n\t\tvar renderer = Renderer.getRenderer(this.rendererConfig);\n\n\t\tvar s1 = renderer.render(CypherParser.parse(q1, parserConfig));\n\t\tvar s2 = renderer.render(CypherParser.parse(q2, parserConfig));\n\n\t\tvar expected1 = \"\"\"\n\t\t\t\tMATCH (v0:Film:Multimedia)\n\t\t\t\tCALL {\n\t\t\t\t  WITH v0\n\t\t\t\t  MATCH (v1:Actor:Person)-[v2:ACTED_IN]->(v0)\n\t\t\t\t  WITH v1 {\n\t\t\t\t    .name\n\t\t\t\t  } AS v1\n\t\t\t\t  RETURN collect(v1) AS v1\n\t\t\t\t}\n\t\t\t\tRETURN v0 {\n\t\t\t\t  actors: v1,\n\t\t\t\t  .title\n\t\t\t\t} AS v0\"\"\";\n\n\t\tvar expected2 = \"\"\"\n\t\t\t\tMATCH (v0:Film:Multimedia)\n\t\t\t\tCALL {\n\t\t\t\t  WITH v0\n\t\t\t\t  MATCH (v1:Actor:Person)-[v2:ACTED_IN]->(v0)\n\t\t\t\t  WITH v1 {\n\t\t\t\t    .name\n\t\t\t\t  } AS v3\n\t\t\t\t  RETURN collect(v3) AS v3\n\t\t\t\t}\n\t\t\t\tRETURN v0 {\n\t\t\t\t  actors: v3,\n\t\t\t\t  .title\n\t\t\t\t} AS v0\"\"\";\n\n\t\tassertThat(s1).isEqualTo(expected1);\n\t\tassertThat(s2).isEqualTo(expected2);\n\t}\n\n\t@Test // GH-1235\n\tvoid caseParsingAndRenderingShouldWork() {\n\t\tfinal var node = Cypher.node(\"Node\").named(\"n\");\n\t\tfinal var query = Cypher.match(node)\n\t\t\t.returning(Cypher.caseExpression(node.property(\"prop\"))\n\t\t\t\t.when(Cypher.literalOf(\"A\"))\n\t\t\t\t.then(Cypher.literalOf(1))\n\t\t\t\t.elseDefault(Cypher.literalOf(2)))\n\t\t\t.build();\n\n\t\tassertThat(query.getCypher()).isEqualTo(\"MATCH (n:`Node`) RETURN CASE n.prop WHEN 'A' THEN 1 ELSE 2 END\");\n\t\tvar renderedParsedAndRendered = CypherParser.parse(query.getCypher()).getCypher();\n\t\tassertThat(renderedParsedAndRendered)\n\t\t\t.isEqualTo(\"MATCH (n:`Node`) RETURN CASE n.prop WHEN 'A' THEN 1 ELSE 2 END\");\n\t\trenderedParsedAndRendered = CypherParser.parse(renderedParsedAndRendered).getCypher();\n\t\tassertThat(renderedParsedAndRendered)\n\t\t\t.isEqualTo(\"MATCH (n:`Node`) RETURN CASE n.prop WHEN 'A' THEN 1 ELSE 2 END\");\n\t}\n\n\t@Test // GH-1235\n\tvoid genericCase() {\n\t\tvar cypher = \"\"\"\n\t\t\t\tMATCH (n:Person)\n\t\t\t\tRETURN\n\t\t\t\tCASE\n\t\t\t\t  WHEN n.eyes = 'blue' THEN 1\n\t\t\t\t  WHEN n.age < 40      THEN 2\n\t\t\t\t  ELSE 3\n\t\t\t\tEND AS result, n.eyes, n.age\n\t\t\t\t\"\"\";\n\t\tassertThat(CypherParser.parse(cypher).getCypher()).isEqualTo(\n\t\t\t\t\"MATCH (n:`Person`) RETURN CASE WHEN n.eyes = 'blue' THEN 1 WHEN n.age < 40 THEN 2 ELSE 3 END AS result, n.eyes, n.age\");\n\t}\n\n\t@ParameterizedTest // GH-1404\n\t@EnumSource(Dialect.class)\n\tvoid shouldRenderWithoutDroppingColons(Dialect dialect) {\n\t\tString cypher = \"MATCH (:PurchaseOrder|TollerOrder)-[:PLACED_IN]->(:Site), (po:Purchase_orders)<-[:IS_PURCHASED]-(m:Material)\\nRETURN *\";\n\t\tvar statement = CypherParser.parse(cypher);\n\t\tConfiguration rendererConfig = Configuration.newConfig()\n\t\t\t.alwaysEscapeNames(false)\n\t\t\t.withPrettyPrint(true)\n\t\t\t.withDialect(dialect)\n\t\t\t.build();\n\t\tvar renderer = Renderer.getRenderer(rendererConfig);\n\n\t\tString result = renderer.render(statement);\n\t\tassertThat(result).endsWith(cypher);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/PathLengthTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.CsvSource;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass PathLengthTests {\n\n\t@ParameterizedTest\n\t@CsvSource(nullValues = \"N/A\", value = { \"N/A, N/A\", \"N/A, 5\", \"5, N/A\", \"5, 10\" })\n\tvoid length1(String minimum, String maximimum) {\n\t\tPathLength pathLength = PathLength.of(minimum, maximimum);\n\t\tif (minimum == null && maximimum == null) {\n\t\t\tassertThat(pathLength.isUnbounded()).isTrue();\n\t\t}\n\n\t\tif (minimum != null) {\n\t\t\tassertThat(pathLength.getMinimum()).isEqualTo(Integer.parseInt(minimum));\n\t\t}\n\n\t\tif (maximimum != null) {\n\t\t\tassertThat(pathLength.getMaximum()).isEqualTo(Integer.parseInt(maximimum));\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/QPPPrimerIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Stream;\n\nimport com.opencsv.CSVReaderBuilder;\nimport com.opencsv.exceptions.CsvValidationException;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.TestInstance;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\nimport org.neo4j.harness.Neo4j;\nimport org.neo4j.harness.Neo4jBuilders;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\n@TestInstance(TestInstance.Lifecycle.PER_CLASS)\nclass QPPPrimerIT {\n\n\tprivate static final Renderer RENDERER = Renderer\n\t\t.getRenderer(Configuration.newConfig().alwaysEscapeNames(false).build());\n\n\tprivate final Neo4j neo4j = Neo4jBuilders.newInProcessBuilder()\n\t\t.withDisabledServer()\n\t\t.withFixture(\n\t\t\t\t\"\"\"\n\t\t\t\t\t\tCREATE (n1:Station {name: 'Denmark Hill'}),\n\t\t\t\t\t\t(n5:Station {name: 'Battersea Park'}),\n\t\t\t\t\t\t(n6:Station {name: 'Wandsworth Road'}),\n\t\t\t\t\t\t(n15:Station {name: 'Clapham High Street'}),\n\t\t\t\t\t\t(n16:Station {name: 'Peckham Rye'}),\n\t\t\t\t\t\t(n17:Station {name: 'Brixton'}),\n\t\t\t\t\t\t(n14:Station {name: 'London Victoria'}),\n\t\t\t\t\t\t(n18:Station {name: 'Clapham Junction'}),\n\t\t\t\t\t\t(p10:Stop {departs: time('22:37'), arrives: time('22:36')}),\n\t\t\t\t\t\t(p0:Stop {departs: time('22:41'), arrives: time('22:41')}),\n\t\t\t\t\t\t(p2:Stop {departs: time('22:43'), arrives: time('22:43')}),\n\t\t\t\t\t\t(p17:Stop {arrives: time('22:50'), departs: time('22:50')}),\n\t\t\t\t\t\t(p18:Stop {arrives: time('22:46'), departs: time('22:46')}),\n\t\t\t\t\t\t(p19:Stop {departs: time('22:33'), arrives: time('22:31')}),\n\t\t\t\t\t\t(p21:Stop {arrives: time('22:55')}),\n\t\t\t\t\t\t(p20:Stop {departs: time('22:44'), arrives: time('22:43')}),\n\t\t\t\t\t\t(p22:Stop {arrives: time('22:55')}),\n\t\t\t\t\t\t(p23:Stop {arrives: time('22:48')}),\n\t\t\t\t\t\t(n15)-[:LINK {distance: 1.96}]->(n1)-[:LINK {distance: 0.86}]->(n16),\n\t\t\t\t\t\t(n15)-[:LINK {distance: 0.39}]->(n6)<-[:LINK {distance: 0.7}]-(n5)-[:LINK {distance: 1.24}]->(n14), (n5)-[:LINK {distance: 1.45}]->(n18),\n\t\t\t\t\t\t(n14)<-[:LINK {distance: 3.18}]-(n17)-[:LINK {distance: 1.11}]->(n1),\n\t\t\t\t\t\t(p2)-[:CALLS_AT]->(n6), (p17)-[:CALLS_AT]->(n5), (p19)-[:CALLS_AT]->(n16),\n\t\t\t\t\t\t(p22)-[:CALLS_AT]->(n14), (p18)-[:CALLS_AT]->(n18), (p0)-[:CALLS_AT]->(n15), (p23)-[:CALLS_AT]->(n5), (p20)-[:CALLS_AT]->(n1),\n\t\t\t\t\t\t(p21)-[:CALLS_AT]->(n14), (p10)-[:CALLS_AT]->(n1), (p19)-[:NEXT]->(p10)-[:NEXT]->(p0)-[:NEXT]->(p2)-[:NEXT]->(p23),\n\t\t\t\t\t\t(p22)<-[:NEXT]-(p17)<-[:NEXT]-(p18), (p21)<-[:NEXT]-(p20)\n\t\t\t\t\t\t\"\"\")\n\t\t.build();\n\n\tstatic Stream<Arguments> primerStatementsShouldBeParsedAndProduceCorrectResults()\n\t\t\tthrows CsvValidationException, IOException {\n\n\t\tList<Arguments> result = new ArrayList<>();\n\t\ttry (var csvReader = new CSVReaderBuilder(new InputStreamReader(\n\t\t\t\tObjects.requireNonNull(CypherChallengeTests.class.getResourceAsStream(\"/qpp-primer.csv\"))))\n\t\t\t.withSkipLines(1)\n\t\t\t.build()) {\n\t\t\tString[] nextRecord;\n\n\t\t\twhile ((nextRecord = csvReader.readNext()) != null) {\n\t\t\t\tresult.add(Arguments.of(nextRecord[0], nextRecord[1].trim().replaceAll(\"\\\\s{2,}\", \" \"),\n\t\t\t\t\t\tInteger.parseInt(nextRecord[2]), Boolean.parseBoolean(nextRecord[3])));\n\t\t\t}\n\t\t}\n\t\treturn result.stream();\n\t}\n\n\t@AfterAll\n\tvoid shutdownNeo4j() {\n\t\tthis.neo4j.close();\n\t}\n\n\t@ParameterizedTest\n\t@MethodSource\n\tvoid primerStatementsShouldBeParsedAndProduceCorrectResults(String in, String expected, int expectedNumResults,\n\t\t\tboolean isCountQuery) {\n\t\tvar cypher = RENDERER.render(CypherParser.parse(in));\n\n\t\tassertThat(cypher).isEqualTo(expected);\n\t\tassertThat(RENDERER.render(CypherParser.parse(cypher))).isEqualTo(cypher);\n\t\ttry (var tx = this.neo4j.defaultDatabaseService().beginTx(); var result = tx.execute(cypher)) {\n\t\t\tif (isCountQuery) {\n\t\t\t\tvar cnt = (long) result.next().get(result.columns().get(0));\n\t\t\t\tassertThat(cnt).isEqualTo(expectedNumResults);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tassertThat(result.stream().count()).isEqualTo(expectedNumResults);\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/RewriteTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.Collection;\nimport java.util.LinkedHashSet;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.function.BiFunction;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.Expression;\nimport org.neo4j.cypherdsl.core.Parameter;\nimport org.neo4j.cypherdsl.core.SymbolicName;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass RewriteTests {\n\n\t// tag::enforcing-labels-function[]\n\tfinal BiFunction<LabelParsedEventType, Collection<String>, Collection<String>> makeSureALabelIsPresent = (e, c) -> {\n\n\t\tvar finalLabels = new LinkedHashSet<>(c);\n\t\tswitch (e) { // <.>\n\t\t\tcase ON_NODE_PATTERN:\n\t\t\t\tfinalLabels.add(\"ForcedLabel\");\n\t\t\t\treturn finalLabels;\n\t\t\tcase ON_SET:\n\t\t\t\tfinalLabels.add(\"Modified\");\n\t\t\t\treturn finalLabels;\n\t\t\tcase ON_REMOVE:\n\t\t\t\tfinalLabels.remove(\"ForcedLabel\");\n\t\t\t\treturn finalLabels;\n\t\t\tdefault:\n\t\t\t\treturn c;\n\t\t}\n\t};\n\n\t// end::enforcing-labels-function[]\n\n\t@Test\n\t@SuppressWarnings(\"squid:S5976\") // About making it a parameterized test. Used in the\n\t\t\t\t\t\t\t\t\t\t// docs.\n\tvoid shouldRewriteLabelsOnParseNode() {\n\n\t\t// tag::enforcing-on-parse[]\n\t\tvar options = Options.newOptions().withLabelFilter(this.makeSureALabelIsPresent).build();\n\t\tvar statement = CypherParser.parseStatement(\"MATCH (n:Movie) RETURN n\", options).getCypher();\n\n\t\tassertThat(statement).isEqualTo(\"MATCH (n:`Movie`:`ForcedLabel`) RETURN n\");\n\t\t// end::enforcing-on-parse[]\n\t}\n\n\t@Test\n\t@SuppressWarnings(\"squid:S5976\") // Used in the docs\n\tvoid shouldRewriteLabelsOnSetLabels() {\n\n\t\t// tag::enforcing-on-set[]\n\t\tvar options = Options.newOptions().withLabelFilter(this.makeSureALabelIsPresent).build();\n\t\tvar statement = CypherParser.parseStatement(\"MATCH (n:Movie) SET n:`Comedy` RETURN n\", options).getCypher();\n\n\t\tassertThat(statement).isEqualTo(\"MATCH (n:`Movie`:`ForcedLabel`) SET n:`Comedy`:`Modified` RETURN n\");\n\t\t// end::enforcing-on-set[]\n\t}\n\n\t@Test\n\t@SuppressWarnings(\"squid:S5976\") // Used in the docs\n\tvoid shouldRewriteLabelsOnRemoveLabels() {\n\n\t\t// tag::enforcing-on-remove[]\n\t\tvar options = Options.newOptions().withLabelFilter(this.makeSureALabelIsPresent).build();\n\t\tvar statement = CypherParser.parseStatement(\"MATCH (n:Movie) REMOVE n:`Comedy`:`ForcedLabel` RETURN n\", options)\n\t\t\t.getCypher();\n\n\t\tassertThat(statement).isEqualTo(\"MATCH (n:`Movie`:`ForcedLabel`) REMOVE n:`Comedy` RETURN n\");\n\t\t// end::enforcing-on-remove[]\n\t}\n\n\t@Test\n\tvoid shouldRewriteTypes() {\n\n\t\tvar statement = CypherParser\n\t\t\t.parseStatement(\"MATCH (p:Person) -[:HAT_GESPIELT_IN] -> (n:Movie) RETURN n\",\n\t\t\t\t\tOptions.newOptions()\n\t\t\t\t\t\t.withTypeFilter(\n\t\t\t\t\t\t\t\t(e, t) -> ((t.size() == 1) && t.contains(\"HAT_GESPIELT_IN\")) ? Set.of(\"ACTED_IN\") : t)\n\t\t\t\t\t\t.build())\n\t\t\t.getCypher();\n\t\tassertThat(statement).isEqualTo(\"MATCH (p:`Person`)-[:`ACTED_IN`]->(n:`Movie`) RETURN n\");\n\t}\n\n\t@Test\n\tvoid shouldRewriteVariables() {\n\n\t\tvar p = Cypher.node(\"Person\").named(\"p\");\n\t\tvar parserOptions = Options.newOptions()\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_NEW_VARIABLE, Expression.class,\n\t\t\t\t\te -> p.property(((SymbolicName) e).getValue()))\n\t\t\t.build();\n\t\tvar statement = Cypher.match(p)\n\t\t\t.where(CypherParser.parseExpression(\"name = 'Foobar'\", parserOptions).asCondition())\n\t\t\t.returning(p)\n\t\t\t.build()\n\t\t\t.getCypher();\n\t\tassertThat(statement).isEqualTo(\"MATCH (p:`Person`) WHERE p.name = 'Foobar' RETURN p\");\n\t}\n\n\t@Test\n\tvoid shouldRewriteParameters() {\n\t\tvar counter = new AtomicInteger(1);\n\t\tvar parserOptions = Options.newOptions()\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_NEW_PARAMETER, Expression.class,\n\t\t\t\t\te -> Cypher.parameter(String.format(\"%d\", counter.getAndIncrement())))\n\t\t\t.build();\n\t\tvar statement = CypherParser.parse(\n\t\t\t\t\"CREATE (p:Person {name: $name, height: $height, birthDate: $birthDate, templateEmail: 'Welcome $name!'})\",\n\t\t\t\tparserOptions)\n\t\t\t.getCypher();\n\t\tassertThat(statement)\n\t\t\t.isEqualTo(\"CREATE (p:`Person` {name: $1, height: $2, birthDate: $3, templateEmail: 'Welcome $name!'})\");\n\t}\n\n\t@Test\n\tvoid shouldRewriteParameters2() {\n\n\t\tvar mapping = Map.of(\"param1\", \"foo\", \"x\", \"y\");\n\t\tvar parserOptions = Options.newOptions()\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_NEW_PARAMETER, Expression.class, e -> {\n\t\t\t\tif (e instanceof Parameter<?> p) {\n\t\t\t\t\treturn Cypher.parameter(mapping.getOrDefault(p.getName(), p.getName()), p.getValue());\n\t\t\t\t}\n\t\t\t\treturn e;\n\t\t\t})\n\t\t\t.withCallback(ExpressionCreatedEventType.ON_NEW_VARIABLE, Expression.class, e -> {\n\t\t\t\tif (e instanceof SymbolicName s) {\n\t\t\t\t\treturn Cypher.name(mapping.getOrDefault(s.getValue(), s.getValue()));\n\t\t\t\t}\n\t\t\t\treturn e;\n\t\t\t})\n\t\t\t.build();\n\t\tvar statement = CypherParser.parse(\"Match (x:Movie) where x.title = $param1 RETURN x\", parserOptions)\n\t\t\t.getCypher();\n\t\tassertThat(statement).isEqualTo(\"MATCH (y:`Movie`) WHERE y.title = $foo RETURN y\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/StatementsTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.util.ArrayList;\n\nimport org.junit.jupiter.api.Test;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.Statement;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\nclass StatementsTests {\n\n\t@Test\n\tvoid shouldSupportNullIst() {\n\t\tvar statements = new Statements(null);\n\t\tassertThat(statements.value()).isEmpty();\n\t}\n\n\t@Test\n\tvoid shouldCopy() {\n\t\tvar hlp = new ArrayList<Statement>();\n\t\thlp.add(Cypher.returning(Cypher.literalTrue()).build());\n\t\tvar statements = new Statements(hlp);\n\t\thlp.clear();\n\t\tassertThat(statements.value()).hasSize(1);\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/TckTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport java.io.IOException;\nimport java.lang.reflect.InvocationTargetException;\nimport java.net.URISyntaxException;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.AbstractMap;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport org.asciidoctor.Asciidoctor;\nimport org.asciidoctor.Options;\nimport org.asciidoctor.ast.Block;\nimport org.asciidoctor.ast.Document;\nimport org.asciidoctor.extension.Treeprocessor;\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.DynamicContainer;\nimport org.junit.jupiter.api.DynamicNode;\nimport org.junit.jupiter.api.DynamicTest;\nimport org.junit.jupiter.api.TestFactory;\nimport org.junit.jupiter.api.TestInstance;\nimport org.neo4j.cypherdsl.core.Cypher;\nimport org.neo4j.cypherdsl.core.Statement;\nimport org.neo4j.cypherdsl.core.renderer.Configuration;\nimport org.neo4j.cypherdsl.core.renderer.Dialect;\nimport org.neo4j.cypherdsl.core.renderer.Renderer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatExceptionOfType;\n\n/**\n * This tests reads and parses the README.adoc and verifies the defined content.\n *\n * @author Michael J. Simons\n */\n@TestInstance(TestInstance.Lifecycle.PER_CLASS)\nclass TckTests {\n\n\tprivate final Map<String, TestData> testData = new HashMap<>();\n\n\t@BeforeAll\n\tvoid init() throws IOException, URISyntaxException {\n\n\t\tvar asciidoctor = Asciidoctor.Factory.create();\n\t\tvar collector = new TestDataExtractor();\n\t\tasciidoctor.javaExtensionRegistry().treeprocessor(collector);\n\n\t\tvar content = Files.readString(Paths.get(getClass().getResource(\"/README.adoc\").toURI()));\n\t\tasciidoctor.load(content, Options.builder().build());\n\n\t\tthis.testData.putAll(collector.content);\n\t}\n\n\t@TestFactory\n\tStream<DynamicNode> tck() {\n\n\t\treturn this.testData.entrySet().stream().map(entry -> {\n\t\t\ttry {\n\t\t\t\tStream<DynamicNode> entries;\n\n\t\t\t\tvar type = entry.getKey().split(\"-\")[0];\n\t\t\t\tvar method = this.getClass()\n\t\t\t\t\t.getDeclaredMethod(type + \"ShouldWork\", Renderer.class, String.class, String.class);\n\n\t\t\t\tvar renderer = Renderer.getRenderer(Configuration.newConfig()\n\t\t\t\t\t.withDialect(Dialect.NEO4J_4)\n\t\t\t\t\t.alwaysEscapeNames(entry.getValue().alwaysEscape)\n\t\t\t\t\t.build());\n\n\t\t\t\tentries = entry.getValue()\n\t\t\t\t\t.asArguments()\n\t\t\t\t\t.map(arguments -> DynamicTest.dynamicTest(arguments.getKey(), () -> {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tmethod.invoke(this, renderer, arguments.getKey(), arguments.getValue());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (InvocationTargetException ex) {\n\t\t\t\t\t\t\tthrow ex.getCause();\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\n\t\t\t\tvar name = type;\n\t\t\t\tif (!entry.getValue().alwaysEscape) {\n\t\t\t\t\tname += \" (Only escaping when necessary)\";\n\t\t\t\t}\n\t\t\t\treturn DynamicContainer.dynamicContainer(name, entries);\n\t\t\t}\n\t\t\tcatch (NoSuchMethodException ex) {\n\t\t\t\tthrow new RuntimeException(ex);\n\t\t\t}\n\t\t});\n\t}\n\n\t@SuppressWarnings(\"unused\")\n\tvoid nodesShouldWork(Renderer renderer, String input, String expected) {\n\n\t\tvar node = CypherParser.parseNode(input);\n\t\tassertThat(renderer.render(Cypher.match(node).returning(Cypher.asterisk()).build()))\n\t\t\t.isEqualTo(String.format(\"MATCH %s RETURN *\", expected));\n\t}\n\n\t@SuppressWarnings(\"unused\")\n\tvoid expressionsShouldWork(Renderer renderer, String input, String expected) {\n\n\t\tvar e = CypherParser.parseExpression(input);\n\t\tassertThat(renderer.render(Cypher.returning(e).build())).isEqualTo(String.format(\"RETURN %s\", expected));\n\t}\n\n\t@SuppressWarnings(\"unused\")\n\tvoid clausesShouldWork(Renderer renderer, String input, String expected) {\n\n\t\tvar cypher = renderer.render(Statement.of(List.of(CypherParser.parseClause(input))));\n\t\tAssertions.assertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@SuppressWarnings(\"unused\")\n\tvoid statementsShouldWork(Renderer renderer, String input, String expected) {\n\n\t\tvar cypher = renderer.render(CypherParser.parseStatement(input));\n\t\tassertThat(cypher).isEqualTo(expected);\n\t}\n\n\t@SuppressWarnings(\"unused\")\n\tvoid qppShouldWork(Renderer renderer, String input, String expected) {\n\n\t\tvar cypher = renderer.render(CypherParser.parseStatement(input));\n\t\tassertThat(cypher).isEqualTo(expected.replaceAll(\"\\\\s{2,}|\\n\", \" \"));\n\t}\n\n\t@SuppressWarnings(\"unused\")\n\tvoid unsupportedShouldWork(Renderer renderer, String input, String expected) {\n\n\t\tassertThatExceptionOfType(UnsupportedCypherException.class).isThrownBy(() -> CypherParser.parse(input))\n\t\t\t.withMessageStartingWith(\"You used one Cypher construct not yet supported by the Cypher-DSL\")\n\t\t\t.withMessageContaining(input);\n\t}\n\n\tprivate static class TestDataExtractor extends Treeprocessor {\n\n\t\tprivate final Map<String, TestData> content = new HashMap<>();\n\n\t\tTestDataExtractor() {\n\t\t\tsuper(new HashMap<>()); // Must be mutable\n\t\t}\n\n\t\t@Override\n\t\tpublic Document process(Document document) {\n\t\t\tdocument.findBy(Map.of(\"context\", \":listing\", \"style\", \"source\"))\n\t\t\t\t.stream()\n\t\t\t\t.map(Block.class::cast)\n\t\t\t\t.filter(b -> \"cypher\".equals(b.getAttribute(\"language\")))\n\t\t\t\t.forEach(block -> {\n\t\t\t\t\tvar id = block.getId().split(\"-\");\n\t\t\t\t\tvar type = id[0];\n\t\t\t\t\tvar alwaysEscape = !block.hasAttribute(\"alwaysEscape\")\n\t\t\t\t\t\t\t|| Boolean.parseBoolean((String) block.getAttribute(\"alwaysEscape\"));\n\t\t\t\t\ttype = type + \"-\" + alwaysEscape;\n\t\t\t\t\tvar test = this.content.computeIfAbsent(type, key -> new TestData(alwaysEscape));\n\t\t\t\t\tvar separated = block.getAttribute(\"separated\");\n\t\t\t\t\tvar lines = Boolean.parseBoolean((String) separated) ? Arrays.asList(block.getSource().split(\";\"))\n\t\t\t\t\t\t\t: block.getLines();\n\t\t\t\t\tswitch (id[1]) {\n\t\t\t\t\t\tcase \"input\" -> test.input.addAll(lines);\n\t\t\t\t\t\tcase \"output\" -> test.expected.addAll(lines);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\treturn document;\n\t\t}\n\n\t}\n\n\tprivate static class TestData {\n\n\t\tprivate final boolean alwaysEscape;\n\n\t\tprivate final List<String> input = new ArrayList<>();\n\n\t\tprivate final List<String> expected = new ArrayList<>();\n\n\t\tTestData(boolean alwaysEscape) {\n\t\t\tthis.alwaysEscape = alwaysEscape;\n\t\t}\n\n\t\tStream<Map.Entry<String, String>> asArguments() {\n\t\t\tif (this.input.size() == this.expected.size()) {\n\t\t\t\tvar result = Stream.<Map.Entry<String, String>>builder();\n\t\t\t\tfor (int i = 0; i < this.input.size(); i++) {\n\t\t\t\t\tresult.add(new AbstractMap.SimpleImmutableEntry<>(this.input.get(i).trim(),\n\t\t\t\t\t\t\tthis.expected.get(i).trim()));\n\t\t\t\t}\n\t\t\t\treturn result.build();\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn this.input.stream().collect(Collectors.toMap(Function.identity(), k -> \"\")).entrySet().stream();\n\t\t\t}\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/java/org/neo4j/cypherdsl/parser/UnsupportedCypherExceptionTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.parser;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\nclass UnsupportedCypherExceptionTests {\n\n\t@Test\n\tvoid causeShouldBePresent() {\n\t\tvar cause = new UnsupportedOperationException(\"booms\");\n\t\tvar unsupportedCypherException = new UnsupportedCypherException(\"This is invalid cypher\", cause);\n\t\tassertThat(unsupportedCypherException.getCause()).isEqualTo(cause);\n\t}\n\n\t@Test\n\tvoid inputShouldBeRetrievable() {\n\t\tvar cause = new UnsupportedOperationException(\"booms\");\n\t\tvar input = \"This is invalid cypher\";\n\t\tvar unsupportedCypherException = new UnsupportedCypherException(input, cause);\n\t\tassertThat(unsupportedCypherException.getInput()).isEqualTo(input);\n\t}\n\n\t@Test\n\tvoid messageShouldBeFormatted() {\n\t\tvar cause = new UnsupportedOperationException(\"booms\");\n\t\tvar input = \"This is invalid cypher\";\n\t\tvar unsupportedCypherException = new UnsupportedCypherException(input, cause);\n\n\t\tassertThat(unsupportedCypherException.getMessage()).isEqualTo(\n\t\t\t\t\"\"\"\n\t\t\t\t\t\tYou used one Cypher construct not yet supported by the Cypher-DSL:\n\n\t\t\t\t\t\t\\tThis is invalid cypher\n\n\t\t\t\t\t\tFeel free to open an issue so that we might add support for it at https://github.com/neo4j-contrib/cypher-dsl/issues/new\"\"\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/resources/cypher-challenge.csv",
    "content": "statement,schema,correct_query\n\"MATCH (p:Person)-[:KNOWS]->(:Person) RETURN p, count(*) AS count\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person)-[:KNOWS]->(:Person) RETURN p, count(*) AS count\"\n\"MATCH (p:Person)<-[:KNOWS]-(:Person) RETURN p, count(*) AS count\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person)<-[:KNOWS]-(:Person) RETURN p, count(*) AS count\"\n\"MATCH (p:Person {id:\"\"Foo\"\"})<-[:WORKS_AT]-(o:Organization) RETURN o.name AS name\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person {id:\"\"Foo\"\"})-[:WORKS_AT]->(o:Organization) RETURN o.name AS name\"\n\"MATCH (o:Organization)-[:WORKS_AT]->(p:Person {id:\"\"Foo\"\"}) RETURN o.name AS name\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (o:Organization)<-[:WORKS_AT]-(p:Person {id:\"\"Foo\"\"}) RETURN o.name AS name\"\n\"MATCH (o:Organization {name:\"\"Bar\"\"})-[:WORKS_AT]->(p:Person {id:\"\"Foo\"\"}) RETURN o.name AS name\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (o:Organization {name:\"\"Bar\"\"})<-[:WORKS_AT]-(p:Person {id:\"\"Foo\"\"}) RETURN o.name AS name\"\n\"MATCH (o:Organization)-[:WORKS_AT]->(p:Person {id:\"\"Foo\"\"})-[:WORKS_AT]->(o1:Organization) RETURN o.name AS name\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (o:Organization)<-[:WORKS_AT]-(p:Person {id:\"\"Foo\"\"})-[:WORKS_AT]->(o1:Organization) RETURN o.name AS name\"\n\"MATCH (o:`Organization` {name:\"\"Foo\"\"})-[:WORKS_AT]->(p:Person {id:\"\"Foo\"\"})-[:WORKS_AT]-(o1:Organization {name:\"\"b\"\"})\nWHERE id(o) > id(o1)\nRETURN o.name AS name\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (o:`Organization` {name:\"\"Foo\"\"})<-[:WORKS_AT]-(p:Person {id:\"\"Foo\"\"})-[:WORKS_AT]-(o1:Organization {name:\"\"b\"\"})\nWHERE id(o) > id(o1)\nRETURN o.name AS name\"\n\"MATCH (p:Person)\nRETURN p,\n       [(p)-[:WORKS_AT]->(o:Organization) | o.name] AS op\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person)\nRETURN p,\n       [(p)-[:WORKS_AT]->(o:Organization) | o.name] AS op\"\n\"MATCH (p:Person)\nRETURN p,\n       [(p)<-[:WORKS_AT]-(o:Organization) | o.name] AS op\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person)\nRETURN p,\n       [(p)-[:WORKS_AT]->(o:Organization) | o.name] AS op\"\n\"MATCH (p:Person {name:\"\"John\"\"}) MATCH (p)-[:WORKS_AT]->(:Organization) RETURN p, count(*)\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person {name:\"\"John\"\"}) MATCH (p)-[:WORKS_AT]->(:Organization) RETURN p, count(*)\"\n\"MATCH (p:Person) MATCH (p)<-[:WORKS_AT]-(:Organization) RETURN p, count(*)\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person) MATCH (p)-[:WORKS_AT]->(:Organization) RETURN p, count(*)\"\n\"MATCH (p:Person), (p)<-[:WORKS_AT]-(:Organization) RETURN p, count(*)\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person), (p)-[:WORKS_AT]->(:Organization) RETURN p, count(*)\"\n\"MATCH (o:Organization)-[:WORKS_AT]->(p:Person {id:\"\"Foo\"\"})-[:WORKS_AT]->(o1:Organization)\nWHERE id(o) < id(o1) RETURN o.name AS name\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (o:Organization)<-[:WORKS_AT]-(p:Person {id:\"\"Foo\"\"})-[:WORKS_AT]->(o1:Organization)\nWHERE id(o) < id(o1) RETURN o.name AS name\"\n\"MATCH (o:Organization)-[:WORKS_AT]-(p:Person {id:\"\"Foo\"\"})-[:WORKS_AT]-(o1:Organization)\nWHERE id(o) < id(o1) RETURN o.name AS name\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (o:Organization)-[:WORKS_AT]-(p:Person {id:\"\"Foo\"\"})-[:WORKS_AT]-(o1:Organization)\nWHERE id(o) < id(o1) RETURN o.name AS name\"\n\"MATCH (p:Person)--(:Organization)--(p1:Person)\nRETURN p1\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person)--(:Organization)--(p1:Person)\nRETURN p1\"\n\"MATCH (p:Person)<--(:Organization)--(p1:Person)\nRETURN p1\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person)-->(:Organization)--(p1:Person)\nRETURN p1\"\n\"MATCH (p:Person)<-[r]-(:Organization)--(p1:Person)\nRETURN p1, r\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person)-[r]->(:Organization)--(p1:Person)\nRETURN p1, r\"\n\"MATCH (person:Person)\nCALL {\n   WITH person\n   MATCH (person)-->(o:Organization)\n   RETURN o LIMIT 3\n}\nRETURN person, o\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (person:Person)\nCALL {\n   WITH person\n   MATCH (person)-->(o:Organization)\n   RETURN o LIMIT 3\n}\nRETURN person, o\"\n\"MATCH (person:Person)\nCALL {\n   WITH person\n   MATCH (person)<--(o:Organization)\n   RETURN o LIMIT 3\n}\nRETURN person, o\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (person:Person)\nCALL {\n   WITH person\n   MATCH (person)-->(o:Organization)\n   RETURN o LIMIT 3\n}\nRETURN person, o\"\n\"MATCH (person:Person)\nCALL {\n   WITH person\n   MATCH (person)-[:KNOWS]->(o:Organization)\n   RETURN o LIMIT 3\n}\nRETURN person, o\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\n\"MATCH (person:Person)\nCALL {\n   WITH person\n   MATCH (person)<-[:WORKS_AT|INVESTOR]-(o:Organization)\n   RETURN o LIMIT 3\n}\nRETURN person, o\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization), (Person, INVESTOR, Organization)\",\"MATCH (person:Person)\nCALL {\n   WITH person\n   MATCH (person)-[:WORKS_AT|INVESTOR]->(o:Organization)\n   RETURN o LIMIT 3\n}\nRETURN person, o\"\n\"MATCH (p:Person)\nWHERE EXISTS { (p)<-[:KNOWS]-()}\nRETURN p\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person)\nWHERE EXISTS { (p)<-[:KNOWS]-()}\nRETURN p\"\n\"MATCH (p:Person)\nWHERE EXISTS { (p)-[:KNOWS]->()}\nRETURN p\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person)\nWHERE EXISTS { (p)-[:KNOWS]->()}\nRETURN p\"\n\"MATCH (p:Person)\nWHERE EXISTS { (p)<-[:WORKS_AT]-()}\nRETURN p\",\"(Person, KNOWS, Person), (Person, WORKS_AT, Organization)\",\"MATCH (p:Person)\nWHERE EXISTS { (p)-[:WORKS_AT]->()}\nRETURN p\"\n\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie)\nWHERE p.name = 'Tom Hanks'\nAND m.year = 2013\nRETURN m.title\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie)\nWHERE p.name = 'Tom Hanks'\nAND m.year = 2013\nRETURN m.title\"\n\"MATCH (p:Person)-[:ACTED_IN]-(m:Movie)\nWHERE p.name = 'Tom Hanks'\nAND m.year = 2013\nRETURN m.title\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN]-(m:Movie)\nWHERE p.name = 'Tom Hanks'\nAND m.year = 2013\nRETURN m.title\"\n\"MATCH (p:Person)<-[:ACTED_IN]-(m:Movie)\nWHERE p.name = 'Tom Hanks'\nAND m.year = 2013\nRETURN m.title\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie)\nWHERE p.name = 'Tom Hanks'\nAND m.year = 2013\nRETURN m.title\"\n\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie)\nWHERE p.name <> 'Tom Hanks'\nAND m.title = 'Captain Phillips'\nRETURN p.name\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie)\nWHERE p.name <> 'Tom Hanks'\nAND m.title = 'Captain Phillips'\nRETURN p.name\"\n\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie)\nWHERE p.name <> 'Tom Hanks'\nAND m.title = 'Captain Phillips'\nAND m.year > 2019\nAND m.year < 2030\nRETURN p.name\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie)\nWHERE p.name <> 'Tom Hanks'\nAND m.title = 'Captain Phillips'\nAND m.year > 2019\nAND m.year < 2030\nRETURN p.name\"\n\"MATCH (p:Person)<-[:ACTED_IN]-(m:Movie)\nWHERE p.name <> 'Tom Hanks'\nAND m.title = 'Captain Phillips'\nAND m.year > 2019\nAND m.year < 2030\nRETURN p.name\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie)\nWHERE p.name <> 'Tom Hanks'\nAND m.title = 'Captain Phillips'\nAND m.year > 2019\nAND m.year < 2030\nRETURN p.name\"\n\"MATCH (p:Person)<-[:FOLLOWS]-(m:Movie)\nWHERE p.name <> 'Tom Hanks'\nAND m.title = 'Captain Phillips'\nAND m.year > 2019\nAND m.year < 2030\nRETURN p.name\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\n\"MATCH (p:Person)-[:`ACTED_IN`]->(m:Movie)<-[:DIRECTED]-(p)\nWHERE  p.born.year > 1960\nRETURN p.name, p.born, labels(p), m.title\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:`ACTED_IN`]->(m:Movie)<-[:DIRECTED]-(p)\nWHERE  p.born.year > 1960\nRETURN p.name, p.born, labels(p), m.title\"\n\"MATCH (p:Person)-[:ACTED_IN]-(m:Movie)<-[:DIRECTED]-(p)\nWHERE  p.born.year > 1960\nRETURN p.name, p.born, labels(p), m.title\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN]-(m:Movie)<-[:DIRECTED]-(p)\nWHERE  p.born.year > 1960\nRETURN p.name, p.born, labels(p), m.title\"\n\"MATCH (p:Person)-[:ACTED_IN]-(m:Movie)-[:DIRECTED]->(p)\nWHERE  p.born.year > 1960\nRETURN p.name, p.born, labels(p), m.title\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN]-(m:Movie)<-[:DIRECTED]-(p)\nWHERE  p.born.year > 1960\nRETURN p.name, p.born, labels(p), m.title\"\n\"MATCH (p:`Person`)<-[r]-(m:Movie)\nWHERE  p.name = 'Tom Hanks'\nRETURN m.title AS movie, type(r) AS relationshipType\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:`Person`)-[r]->(m:Movie)\nWHERE  p.name = 'Tom Hanks'\nRETURN m.title AS movie, type(r) AS relationshipType\"\n\"MATCH (d:Person)-[:DIRECTED]->(m:Movie)-[:IN_GENRE]->(g:Genre)\nWHERE m.year = 2000 AND g.name = \"\"Horror\"\"\nRETURN d.name\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (d:Person)-[:DIRECTED]->(m:Movie)-[:IN_GENRE]->(g:Genre)\nWHERE m.year = 2000 AND g.name = \"\"Horror\"\"\nRETURN d.name\"\n\"MATCH (d:Person)-[:DIRECTED]->(m:Movie)<--(g:Genre)\nWHERE m.year = 2000 AND g.name = \"\"Horror\"\"\nRETURN d.name\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (d:Person)-[:DIRECTED]->(m:Movie)-->(g:Genre)\nWHERE m.year = 2000 AND g.name = \"\"Horror\"\"\nRETURN d.name\"\n\"MATCH (d:Person)<--(m:Movie)<--(g:Genre)\nWHERE m.year = 2000 AND g.name = \"\"Horror\"\"\nRETURN d.name\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (d:Person)-->(m:Movie)-->(g:Genre)\nWHERE m.year = 2000 AND g.name = \"\"Horror\"\"\nRETURN d.name\"\n\"MATCH (d:Person)-[:DIRECTED]-(m:Movie)<-[:IN_GENRE]-(g:Genre)\nWHERE m.year = 2000 AND g.name = \"\"Horror\"\"\nRETURN d.name\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (d:Person)-[:DIRECTED]-(m:Movie)-[:IN_GENRE]->(g:Genre)\nWHERE m.year = 2000 AND g.name = \"\"Horror\"\"\nRETURN d.name\"\n\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie)\nWHERE  p.name = 'Tom Hanks'\nAND exists {(p)-[:DIRECTED]->(m)}\nRETURN p.name, labels(p), m.title\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie)\nWHERE  p.name = 'Tom Hanks'\nAND exists {(p)-[:DIRECTED]->(m)}\nRETURN p.name, labels(p), m.title\"\n\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie)\nWHERE  p.name = 'Tom Hanks'\nAND exists {(p)<-[:DIRECTED]-(m)}\nRETURN p.name, labels(p), m.title\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie)\nWHERE  p.name = 'Tom Hanks'\nAND exists {(p)-[:DIRECTED]->(m)}\nRETURN p.name, labels(p), m.title\"\n\"MATCH (a:Person)-[:ACTED_IN]->(m:Movie)\nWHERE m.year > 2000\nMATCH (m)<-[:DIRECTED]-(d:Person)\nRETURN a.name, m.title, d.name\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (a:Person)-[:ACTED_IN]->(m:Movie)\nWHERE m.year > 2000\nMATCH (m)<-[:DIRECTED]-(d:Person)\nRETURN a.name, m.title, d.name\"\n\"MATCH (a:Person)-[:ACTED_IN]-(m:Movie)\nWHERE m.year > 2000\nMATCH (m)-[:DIRECTED]->(d:Person)\nRETURN a.name, m.title, d.name\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (a:Person)-[:ACTED_IN]-(m:Movie)\nWHERE m.year > 2000\nMATCH (m)<-[:DIRECTED]-(d:Person)\nRETURN a.name, m.title, d.name\"\n\"MATCH (m:Movie) WHERE m.title = \"\"Kiss Me Deadly\"\"\nMATCH (m)-[:IN_GENRE]-(g:Genre)-[:IN_GENRE]->(rec:Movie)\nMATCH (m)-[:ACTED_IN]->(a:Person)-[:ACTED_IN]-(rec)\nRETURN rec.title, a.name\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (m:Movie) WHERE m.title = \"\"Kiss Me Deadly\"\"\nMATCH (m)-[:IN_GENRE]-(g:Genre)<-[:IN_GENRE]-(rec:Movie)\nMATCH (m)<-[:ACTED_IN]-(a:Person)-[:ACTED_IN]-(rec)\nRETURN rec.title, a.name\"\n\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie),\n(coActors:Person)-[:ACTED_IN]->(m)\nWHERE p.name = 'Eminem'\nRETURN m.title AS movie ,collect(coActors.name) AS coActors\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie),\n(coActors:Person)-[:ACTED_IN]->(m)\nWHERE p.name = 'Eminem'\nRETURN m.title AS movie ,collect(coActors.name) AS coActors\"\n\"MATCH (p:Person)<-[:ACTED_IN]-(m:Movie),\n(coActors:Person)-[:ACTED_IN]->(m)\nWHERE p.name = 'Eminem'\nRETURN m.title AS movie ,collect(coActors.name) AS coActors\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN]->(m:Movie),\n(coActors:Person)-[:ACTED_IN]->(m)\nWHERE p.name = 'Eminem'\nRETURN m.title AS movie ,collect(coActors.name) AS coActors\"\n\"MATCH p = ((person:Person)<-[]-(movie:Movie))\nWHERE person.name = 'Walt Disney'\nRETURN p\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH p = ((person:Person)-[]->(movie:Movie))\nWHERE person.name = 'Walt Disney'\nRETURN p\"\n\"MATCH p = ((person:Person)<-[:DIRECTED]-(movie:Movie))\nWHERE person.name = 'Walt Disney'\nRETURN p\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH p = ((person:Person)-[:DIRECTED]->(movie:Movie))\nWHERE person.name = 'Walt Disney'\nRETURN p\"\n\"MATCH p = shortestPath((p1:Person)-[*]-(p2:Person))\nWHERE p1.name = \"\"Eminem\"\"\nAND p2.name = \"\"Charlton Heston\"\"\nRETURN  p\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH p = shortestPath((p1:Person)-[*]-(p2:Person))\nWHERE p1.name = \"\"Eminem\"\"\nAND p2.name = \"\"Charlton Heston\"\"\nRETURN  p\"\n\"MATCH p = ((person:Person)-[:DIRECTED*]->(:Person))\nWHERE person.name = 'Walt Disney'\nRETURN p\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH p = ((person:Person)-[:DIRECTED*]->(:Person))\nWHERE person.name = 'Walt Disney'\nRETURN p\"\n\"MATCH p = ((person:Person)-[:DIRECTED*1..4]->(:Person))\nWHERE person.name = 'Walt Disney'\nRETURN p\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH p = ((person:Person)-[:DIRECTED*1..4]->(:Person))\nWHERE person.name = 'Walt Disney'\nRETURN p\"\n\"MATCH (p:Person {name: 'Eminem'})-[:ACTED_IN*2]-(others:Person)\nRETURN  others.name\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person {name: 'Eminem'})-[:ACTED_IN*2]-(others:Person)\nRETURN  others.name\"\n\"MATCH (u:User {name: \"\"Misty Williams\"\"})-[r:RATED]->(:Movie)\nWITH u, avg(r.rating) AS average\nMATCH (u)-[r:RATED]->(m:Movie)\nWHERE r.rating > average\nRETURN average , m.title AS movie,\nr.rating as rating\nORDER BY rating DESC\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (User, RATED, Movie)\",\"MATCH (u:User {name: \"\"Misty Williams\"\"})-[r:RATED]->(:Movie)\nWITH u, avg(r.rating) AS average\nMATCH (u)-[r:RATED]->(m:Movie)\nWHERE r.rating > average\nRETURN average , m.title AS movie,\nr.rating as rating\nORDER BY rating DESC\"\n\"MATCH (u:User {name: \"\"Misty Williams\"\"})-[r:RATED]->(:Movie)\nWITH u, avg(r.rating) AS average\nMATCH (u)<-[r:RATED]-(m:Movie)\nWHERE r.rating > average\nRETURN average , m.title AS movie,\nr.rating as rating\nORDER BY rating DESC\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (User, RATED, Movie)\",\"MATCH (u:User {name: \"\"Misty Williams\"\"})-[r:RATED]->(:Movie)\nWITH u, avg(r.rating) AS average\nMATCH (u)-[r:RATED]->(m:Movie)\nWHERE r.rating > average\nRETURN average , m.title AS movie,\nr.rating as rating\nORDER BY rating DESC\"\n\"MATCH (p:`Person`)\nWHERE p.born.year = 1980\nWITH p  LIMIT 3\nMATCH (p)<-[:ACTED_IN]-(m:Movie)\nWITH p, collect(m.title) AS movies\nRETURN p.name AS actor,  movies\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:`Person`)\nWHERE p.born.year = 1980\nWITH p  LIMIT 3\nMATCH (p)-[:ACTED_IN]->(m:Movie)\nWITH p, collect(m.title) AS movies\nRETURN p.name AS actor,  movies\"\n\"MATCH (p:Person)\nWHERE p.born.year = 1980\nWITH p  LIMIT 3\nMATCH (p)-[:ACTED_IN]->(m:Movie)<-[:IN_GENRE]-(g)\nWITH p, collect(DISTINCT g.name) AS genres\nRETURN p.name AS actor, genres\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)\nWHERE p.born.year = 1980\nWITH p  LIMIT 3\nMATCH (p)-[:ACTED_IN]->(m:Movie)-[:IN_GENRE]->(g)\nWITH p, collect(DISTINCT g.name) AS genres\nRETURN p.name AS actor, genres\"\n\"CALL {\n   MATCH (m:Movie) WHERE m.year = 2000\n   RETURN m ORDER BY m.imdbRating DESC LIMIT 10\n}\nMATCH  (:User)-[r:RATED]->(m)\nRETURN m.title, avg(r.rating)\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (User, RATED, Movie)\",\"CALL {\n   MATCH (m:Movie) WHERE m.year = 2000\n   RETURN m ORDER BY m.imdbRating DESC LIMIT 10\n}\nMATCH  (:User)-[r:RATED]->(m)\nRETURN m.title, avg(r.rating)\"\n\"CALL {\n   MATCH (m:Movie) WHERE m.year = 2000\n   RETURN m ORDER BY m.imdbRating DESC LIMIT 10\n}\nMATCH  (:User)<-[r:RATED]-(m)\nRETURN m.title, avg(r.rating)\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (User, RATED, Movie)\",\"CALL {\n   MATCH (m:Movie) WHERE m.year = 2000\n   RETURN m ORDER BY m.imdbRating DESC LIMIT 10\n}\nMATCH  (:User)-[r:RATED]->(m)\nRETURN m.title, avg(r.rating)\"\n\"MATCH (m:Movie)\nCALL {\n    WITH m\n    MATCH (m)-[r:RATED]->(u)\n     WHERE r.rating = 5\n    RETURN count(u) AS numReviews\n}\nRETURN m.title, numReviews\nORDER BY numReviews DESC\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (m:Movie)\nCALL {\n    WITH m\n    MATCH (m)<-[r:RATED]-(u)\n     WHERE r.rating = 5\n    RETURN count(u) AS numReviews\n}\nRETURN m.title, numReviews\nORDER BY numReviews DESC\"\n\"MATCH (p:Person)\nWITH p LIMIT 100\nCALL {\n  WITH p\n  OPTIONAL MATCH (p)<-[:ACTED_IN]-(m)\n  RETURN m.title + \"\": \"\" + \"\"Actor\"\" AS work\nUNION\n  WITH p\n  OPTIONAL MATCH (p)-[:DIRECTED]->(m:Movie)\n  RETURN m.title+ \"\": \"\" +  \"\"Director\"\" AS work\n}\nRETURN p.name, collect(work)\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)\nWITH p LIMIT 100\nCALL {\n  WITH p\n  OPTIONAL MATCH (p)-[:ACTED_IN]->(m)\n  RETURN m.title + \"\": \"\" + \"\"Actor\"\" AS work\nUNION\n  WITH p\n  OPTIONAL MATCH (p)-[:DIRECTED]->(m:Movie)\n  RETURN m.title+ \"\": \"\" +  \"\"Director\"\" AS work\n}\nRETURN p.name, collect(work)\"\n\"MATCH (p:Person)<-[:ACTED_IN {role:\"\"Neo\"\"}]-(m:Movie)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p, m\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN {role:\"\"Neo\"\"}]->(m:Movie)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p, m\"\n\"MATCH (p:Person)<-[:ACTED_IN {role:\"\"Neo\"\"}]-(m)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN {role:\"\"Neo\"\"}]->(m)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p\"\n\"MATCH (p:Person)-[:ACTED_IN {role:\"\"Neo\"\"}]->(m:Movie)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p, m\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:ACTED_IN {role:\"\"Neo\"\"}]->(m:Movie)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p, m\"\n\"MATCH (wallstreet:Movie {title: 'Wall Street'})-[:ACTED_IN {role:\"\"Foo\"\"}]->(actor)\nRETURN actor.name\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (wallstreet:Movie {title: 'Wall Street'})<-[:ACTED_IN {role:\"\"Foo\"\"}]-(actor)\nRETURN actor.name\"\n\"MATCH (p:Person)<-[:`ACTED_IN` {role:\"\"Neo\"\"}]-(m:Movie)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p, m\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:`ACTED_IN` {role:\"\"Neo\"\"}]->(m:Movie)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p, m\"\n\"MATCH (p:`Person`)<-[:`ACTED_IN` {role:\"\"Neo\"\"}]-(m:Movie)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p, m\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:`Person`)-[:`ACTED_IN` {role:\"\"Neo\"\"}]->(m:Movie)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p, m\"\n\"MATCH (p:`Person`)<-[:`ACTED_IN` {role:\"\"Neo\"\"}]-(m)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p, m\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:`Person`)-[:`ACTED_IN` {role:\"\"Neo\"\"}]->(m)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p, m\"\n\"MATCH (p:Person)<-[:!DIRECTED]-(:Movie) RETURN p, count(*)\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:!DIRECTED]->(:Movie) RETURN p, count(*)\"\n\"MATCH (p:Person)<-[:`ACTED_IN`|`DIRECTED`]-(m:Movie)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p, m\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie)\",\"MATCH (p:Person)-[:`ACTED_IN`|`DIRECTED`]->(m:Movie)\nWHERE p.name = $actorName\nAND m.title = $movieName\nRETURN p, m\"\n\"MATCH (a:Person:Actor)-[:ACTED_IN]->(:Movie)\nRETURN a, count(*)\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (Actor, ACTED_IN, Movie)\",\"MATCH (a:Person:Actor)-[:ACTED_IN]->(:Movie)\nRETURN a, count(*)\"\n\"MATCH (a:Person:Actor)<-[:ACTED_IN]-(:Movie)\nRETURN a, count(*)\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (Actor, ACTED_IN, Movie)\",\"MATCH (a:Person:Actor)-[:ACTED_IN]->(:Movie)\nRETURN a, count(*)\"\n\"MATCH (a:Person:Actor)<-[:ACTED_IN]-()\nRETURN a, count(*)\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (Actor, ACTED_IN, Movie)\",\"MATCH (a:Person:Actor)-[:ACTED_IN]->()\nRETURN a, count(*)\"\n\"MATCH (a:Person:Actor)\nRETURN a, [(a)<-[:`ACTED_IN`]-(m) | m.title] AS movies\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (Actor, ACTED_IN, Movie)\",\"MATCH (a:Person:Actor)\nRETURN a, [(a)-[:`ACTED_IN`]->(m) | m.title] AS movies\"\n\"MATCH (a:Person:Actor)\nRETURN a, [(a)-[:`ACTED_IN`]->(m) | m.title] AS movies\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (Actor, ACTED_IN, Movie)\",\"MATCH (a:Person:Actor)\nRETURN a, [(a)-[:`ACTED_IN`]->(m) | m.title] AS movies\"\n\"MATCH ()-[:ACTED_IN]->(a:Person:Actor)\nRETURN a, count(*)\",\"(Person, FOLLOWS, Person), (Person, ACTED_IN, Movie), (Person, REVIEWED, Movie), (Person, WROTE, Movie), (Person, DIRECTED, Movie), (Movie, IN_GENRE, Genre), (Person, RATED, Movie), (Actor, ACTED_IN, Movie)\",\"MATCH ()<-[:ACTED_IN]-(a:Person:Actor)\nRETURN a, count(*)\"\n\"MATCH (n:Person) <- [:REVIEWED] - (:Movie) RETURN n\",\"(Person, KNOWS, Movie)\",\n"
  },
  {
    "path": "neo4j-cypher-dsl-parser/src/test/resources/qpp-primer.csv",
    "content": "Input,Expected,Num results,Is a counting query?\n\"MATCH ()\n RETURN count(*) AS numNodes\",\"MATCH () RETURN count(*) AS numNodes\",18,true\n\"MATCH (:Stop)\n RETURN count(*) AS numStops\",\"MATCH (:Stop) RETURN count(*) AS numStops\",10,true\n\"MATCH (s:Stop)-[:CALLS_AT]->(:Station {name: 'Denmark Hill'})\n RETURN s.arrives AS arrivalTime\",\"MATCH (s:Stop)-[:CALLS_AT]->(:Station {name: 'Denmark Hill'})\n                                   RETURN s.arrives AS arrivalTime\",2,false\n\"MATCH (n:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-\n         (s:Stop WHERE s.departs = time('22:37'))-[:NEXT]->\n         (:Stop)-[:CALLS_AT]->(d:Station)\n RETURN d.name AS nextCallingPoint\",\"MATCH (n:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(s:Stop WHERE s.departs = time('22:37'))-[:NEXT]->(:Stop)-[:CALLS_AT]->(d:Station)\n                                     RETURN d.name AS nextCallingPoint\",1,false\n\"MATCH (:Station {name: 'Peckham Rye'})-[link:LINK]-+\n         (:Station {name: 'Clapham Junction'})\n RETURN reduce(acc = 0.0, l IN link | round(acc + l.distance, 2)) AS\n          totalDistance\",\"MATCH (:Station {name: 'Peckham Rye'})-[link:LINK]-+(:Station {name: 'Clapham Junction'})\n                          RETURN reduce(acc = 0.0, l IN link | round((acc + l.distance), 2)) AS totalDistance\",2,false\n\"MATCH (:Station {name: 'Peckham Rye'})\n       (()-[link:LINK]-(s) WHERE link.distance <= 2)+\n       (:Station {name: 'London Victoria'})\n UNWIND s AS station\n RETURN station.name AS callingPoint\",\"MATCH (:Station {name: 'Peckham Rye'}) (()-[link:LINK]-(s) WHERE link.distance <= 2)+ (:Station {name: 'London Victoria'})\n                                       UNWIND s AS station\n                                       RETURN station.name AS callingPoint\",5,false\n\"MATCH (:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(s1:Stop)-[:NEXT]->+\n         (sN:Stop WHERE NOT EXISTS { (sN)-[:NEXT]->(:Stop) })-[:CALLS_AT]->\n         (d:Station)\n RETURN s1.departs AS departure, sN.arrives AS arrival,\n        d.name AS finalDestination\",\"MATCH (:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(s1:Stop)-[:NEXT]->+(sN:Stop WHERE NOT (EXISTS { (sN)-[:NEXT]->(:Stop) }))-[:CALLS_AT]->(d:Station)\n                                     RETURN s1.departs AS departure, sN.arrives AS arrival,\n                                            d.name AS finalDestination\",2,false\n\"MATCH (:Station {name: 'Peckham Rye'})<-[:CALLS_AT]-(:Stop)\n       (()-[:NEXT]->(s:Stop))+\n       ()-[:CALLS_AT]->(:Station {name: 'Battersea Park'})\n UNWIND s AS stop\n MATCH (stop)-[:CALLS_AT]->(station:Station)\n RETURN stop.arrives AS arrival, station.name AS callingPoint\",\"MATCH (:Station {name: 'Peckham Rye'})<-[:CALLS_AT]-(:Stop) (()-[:NEXT]->(s:Stop))+ ()-[:CALLS_AT]->(:Station {name: 'Battersea Park'})\n                                                                UNWIND s AS stop\n                                                                MATCH (stop)-[:CALLS_AT]->(station:Station)\n                                                                RETURN stop.arrives AS arrival, station.name AS callingPoint\",4,false\n\"MATCH (n:Station)-[:LINK]-+(n)\n RETURN DISTINCT n.name AS station\",\"MATCH (n:Station)-[:LINK]-+(n)\n                                     RETURN DISTINCT n.name AS station\",6,false\n\"MATCH (:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-\n         (s1:Stop)-[:NEXT]->+(s2:Stop)-[:CALLS_AT]->\n         (c:Station)<-[:CALLS_AT]-(x:Stop),\n        (:Station {name: 'Clapham Junction'})<-[:CALLS_AT]-\n          (t1:Stop)-[:NEXT]->+(x)-[:NEXT]->+(:Stop)-[:CALLS_AT]->\n          (:Station {name: 'London Victoria'})\n WHERE t1.departs = time('22:46')\n       AND s2.arrives < x.departs\n RETURN s1.departs AS departure, s2.arrives AS changeArrival,\n        c.name AS changeAt\",\"MATCH (:Station {name: 'Denmark Hill'})<-[:CALLS_AT]-(s1:Stop)-[:NEXT]->+(s2:Stop)-[:CALLS_AT]->(c:Station)<-[:CALLS_AT]-(x:Stop),\n                                    (:Station {name: 'Clapham Junction'})<-[:CALLS_AT]-(t1:Stop)-[:NEXT]->+(x)-[:NEXT]->+(:Stop)-[:CALLS_AT]->(:Station {name: 'London Victoria'})\n                             WHERE (t1.departs = time('22:46')\n                                   AND s2.arrives < x.departs)\n                             RETURN s1.departs AS departure, s2.arrives AS changeArrival,\n                                    c.name AS changeAt\",1,false\n"
  },
  {
    "path": "neo4j-cypher-dsl-schema-name-support/README.adoc",
    "content": "= Schema Name support\n\nThis module consists of only one class, `SchemaNames`, that allows sanitization and quotation of possible schema names, making them safe to use in string concatenated queries for dynamic manipulation of types and labels. The project is safe to be shaded, it has no dependencies and does not restrict access to its class apart on the package level."
  },
  {
    "path": "neo4j-cypher-dsl-schema-name-support/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-parent</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-schema-name-support</artifactId>\n\n\t<name>Neo4j Cypher DSL (Schema Name Support)</name>\n\t<description>Utilities for quoting schema names to be safely used in string concatenations.</description>\n\n\t<properties>\n\t\t<sonar.coverage.jacoco.xmlReportPaths>${basedir}/../${aggregate.report.dir}</sonar.coverage.jacoco.xmlReportPaths>\n\t</properties>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.assertj</groupId>\n\t\t\t<artifactId>assertj-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.mockito</groupId>\n\t\t\t<artifactId>mockito-core</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j.driver</groupId>\n\t\t\t<artifactId>neo4j-java-driver</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-simple</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.testcontainers</groupId>\n\t\t\t<artifactId>testcontainers-junit-jupiter</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.testcontainers</groupId>\n\t\t\t<artifactId>testcontainers-neo4j</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t</dependencies>\n</project>\n"
  },
  {
    "path": "neo4j-cypher-dsl-schema-name-support/src/main/java/module-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * This module contains utilities to deal with escaping and sanitizing Cypher identifiers.\n *\n * @author Michael J. Simons\n * @since 2023.0.0\n */\nmodule org.neo4j.cypherdsl.support.schema_name {\n\n\texports org.neo4j.cypherdsl.support.schema_name;\n}"
  },
  {
    "path": "neo4j-cypher-dsl-schema-name-support/src/main/java/org/neo4j/cypherdsl/support/schema_name/SchemaNames.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.support.schema_name;\n\nimport java.io.Serial;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n/**\n * A <a href=\n * \"https://s3.amazonaws.com/artifacts.opencypher.org/M18/railroad/SchemaName.html\">SchemaName</a>\n * can appear according to the OpenCypher-Spec all the following places:\n *\n * <ul>\n * <li>NodePattern aka Label</li>\n * <li>RelationshipPattern aka Type</li>\n * <li>PropertyLookup</li>\n * </ul>\n *\n * Some papers refer to a schema name as symbolic names, too. A symbolic name in the\n * context of the Cypher-DSL is usually used to describe variables inside a statement, so\n * we stick with the term schema name here.\n * <p>\n *\n * A schema name must be escaped in statements with backticks - also known as grave\n * accents - ({@code `}) when it contains content that is not a valid identifier or if the\n * name is a reserved word.\n * <p>\n *\n * Backticks themselves must be escaped with a backtick itself: {@code ``}. <strong>We\n * always treat two consecutive backticks as escaped backticks.</strong> An odd number of\n * backticks will always lead to another backtick being inserted so that the single one\n * will be escaped proper. As a concrete example this means an input like {@code ```} will\n * be sanitised and quoted as {@code ``````}. These are one leading and one closing\n * backtick as this schema name needs to be quoted plus one more to escape the outlier.\n * When used as a label or type, the resulting label will be {@code ``}.\n * <p>\n *\n * This utility can be used standalone, the distributed module does not have any\n * dependencies. Shading is ok as well, there is no encapsulation to break.\n *\n * @author Michael J. Simons\n * @since 2022.8.0\n */\npublic final class SchemaNames {\n\n\tprivate static final String ESCAPED_UNICODE_BACKTICK = \"\\\\u0060\";\n\n\tprivate static final Pattern PATTERN_ESCAPED_4DIGIT_UNICODE = Pattern.compile(\"\\\\\\\\u+(\\\\p{XDigit}{4})\");\n\n\tprivate static final Pattern PATTERN_LABEL_AND_TYPE_QUOTATION = Pattern.compile(\"(?<!`)`(?:`{2})*(?!`)\");\n\n\tprivate static final List<String[]> SUPPORTED_ESCAPE_CHARS = List.of(new String[] { \"\\\\b\", \"\\b\" },\n\t\t\tnew String[] { \"\\\\f\", \"\\f\" }, new String[] { \"\\\\n\", \"\\n\" }, new String[] { \"\\\\r\", \"\\r\" },\n\t\t\tnew String[] { \"\\\\t\", \"\\t\" }, new String[] { \"\\\\`\", \"``\" });\n\n\tprivate static final int CACHE_SIZE = 128;\n\n\t/**\n\t * Cypher-DSL has a concrete implementation of such a simple cache, but it should be\n\t * in this module itself.\n\t */\n\tprivate static final Map<CacheKey, SchemaName> CACHE = Collections\n\t\t.synchronizedMap(new LinkedHashMap<>(CACHE_SIZE / 4, 0.75f, true) {\n\t\t\t@Serial\n\t\t\tprivate static final long serialVersionUID = -8109893585632797360L;\n\n\t\t\t@Override\n\t\t\tprotected boolean removeEldestEntry(Map.Entry<CacheKey, SchemaName> eldest) {\n\t\t\t\treturn size() >= CACHE_SIZE;\n\t\t\t}\n\t\t});\n\n\tprivate SchemaNames() {\n\t}\n\n\t/**\n\t * Sanitizes the given input to be used as a valid schema name, adds quotes if\n\t * necessary.\n\t * @param value the value to sanitize\n\t * @return a value that is safe to be used in string concatenation, an empty optional\n\t * indicates a value that cannot be safely quoted\n\t */\n\tpublic static Optional<String> sanitize(String value) {\n\t\treturn sanitize(value, false);\n\t}\n\n\t/**\n\t * Sanitizes the given input to be used as a valid schema name.\n\t * @param value the value to sanitize\n\t * @param enforceQuotes if quotation should be enforced, even when not necessary\n\t * @return a value that is safe to be used in string concatenation, an empty optional\n\t * indicates a value that cannot be safely quoted\n\t */\n\tpublic static Optional<String> sanitize(String value, boolean enforceQuotes) {\n\t\treturn sanitize(value, enforceQuotes, -1, -1);\n\t}\n\n\t/**\n\t * Sanitizes the given input to be used as a valid schema name.\n\t * @param value the value to sanitize\n\t * @param enforceQuotes if quotation should be enforced, even when not necessary\n\t * @param major the Neo4j major version, use a value &lt; 0 to assume the latest major\n\t * version\n\t * @param minor the Neo4j minor version, use a value &lt; 0 to assume any minor\n\t * version\n\t * @return a value that is safe to be used in string concatenation, an empty optional\n\t * indicates a value that cannot be safely quoted\n\t */\n\tpublic static Optional<String> sanitize(String value, boolean enforceQuotes, int major, int minor) {\n\n\t\tif (major >= 0 && (major < 3 || major > 6)) {\n\t\t\tthrow new IllegalArgumentException(\"Unsupported major version: \" + major);\n\t\t}\n\n\t\tif (value == null || value.isEmpty()) {\n\t\t\treturn Optional.empty();\n\t\t}\n\n\t\tCacheKey cacheKey = new CacheKey(value, (major < 0) ? -1 : major, (minor < 0) ? -1 : minor);\n\t\tSchemaName escapedValue = CACHE.computeIfAbsent(cacheKey, SchemaNames::sanitize);\n\n\t\tif (!(enforceQuotes || escapedValue.needsQuotation)) {\n\t\t\treturn Optional.of(escapedValue.value);\n\t\t}\n\n\t\treturn Optional.of(String.format(Locale.ENGLISH, \"`%s`\", escapedValue.value));\n\t}\n\n\tprivate static SchemaName sanitize(CacheKey key) {\n\n\t\tString workingValue = key.value;\n\n\t\t// Replace current and future escaped chars\n\t\tfor (String[] pair : SUPPORTED_ESCAPE_CHARS) {\n\t\t\tworkingValue = workingValue.replace(pair[0], pair[1]);\n\t\t}\n\t\tworkingValue = workingValue.replace(ESCAPED_UNICODE_BACKTICK, \"`\");\n\n\t\t// Replace escaped octal hex\n\t\t// Excluding the support for 6 digit literals, as this contradicts the overall\n\t\t// example in CIP-59r\n\t\tMatcher matcher = PATTERN_ESCAPED_4DIGIT_UNICODE.matcher(workingValue);\n\t\tStringBuilder sb = new StringBuilder();\n\t\twhile (matcher.find()) {\n\t\t\tString replacement = Character.toString((char) Integer.parseInt(matcher.group(1), 16));\n\t\t\tmatcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));\n\t\t}\n\t\tmatcher.appendTail(sb);\n\t\tworkingValue = sb.toString();\n\n\t\tif (substituteRemainingEscapedUnicodeLiteral(key.major, key.minor)) {\n\t\t\tworkingValue = workingValue.replace(\"\\\\u\", \"\\\\u005C\\\\u0075\");\n\t\t}\n\n\t\tmatcher = PATTERN_LABEL_AND_TYPE_QUOTATION.matcher(workingValue);\n\t\tworkingValue = matcher.replaceAll(\"`$0\");\n\n\t\tif (unescapeEscapedBackslashes(key.major)) {\n\t\t\tworkingValue = workingValue.replace(\"\\\\\\\\\", \"\\\\\");\n\t\t}\n\n\t\treturn new SchemaName(workingValue, !isIdentifier(workingValue));\n\t}\n\n\t/**\n\t * True if the start of an escaped Unicode literal {@code \\\\u} should be obfuscated by\n\t * two escaped literals for {@code \\} and {@code u}.\n\t * @param major the Neo4j Major version\n\t * @param minor the Neo4j minor version\n\t * @return {@literal true} if the beginning of an escaped Unicode literal needs\n\t * special treatment\n\t */\n\tprivate static boolean substituteRemainingEscapedUnicodeLiteral(int major, int minor) {\n\t\tif (major == -1) {\n\t\t\treturn true;\n\t\t}\n\t\treturn major >= 4 && major <= 5 && (minor == -1 || minor >= 2);\n\t}\n\n\t/**\n\t * A helper method to determine whether a given Neo4j version supports escaped\n\t * backslashes.\n\t * @param major the Neo4j Major version\n\t * @return {@literal true} if escaped backslashes aren't supported and must be\n\t * unescaped\n\t */\n\tprivate static boolean unescapeEscapedBackslashes(int major) {\n\t\treturn major <= 5;\n\t}\n\n\t/**\n\t * This is a literal copy of\n\t * {@code javax.lang.model.SourceVersion#isIdentifier(CharSequence)} included here to\n\t * be not dependent on the compiler module.\n\t * @param name a possible Java identifier\n\t * @return true, if {@code name} represents an identifier.\n\t */\n\tprivate static boolean isIdentifier(CharSequence name) {\n\n\t\tString id = name.toString();\n\t\tint cp = id.codePointAt(0);\n\t\tif (!Character.isJavaIdentifierStart(cp) || '$' == cp) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (int i = Character.charCount(cp); i < id.length(); i += Character.charCount(cp)) {\n\t\t\tcp = id.codePointAt(i);\n\t\t\tif (!Character.isJavaIdentifierPart(cp) || '$' == cp) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate record CacheKey(String value, int major, int minor) {\n\t}\n\n\tprivate record SchemaName(String value, boolean needsQuotation) {\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-schema-name-support/src/main/java/org/neo4j/cypherdsl/support/schema_name/package-info.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * A single class package providing sanitization of strings to be used as literals in\n * Cypher statements.\n */\npackage org.neo4j.cypherdsl.support.schema_name;\n"
  },
  {
    "path": "neo4j-cypher-dsl-schema-name-support/src/test/java/org/neo4j/cypherdsl/support/schema_name/SchemaNamesIT.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.support.schema_name;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.NoSuchElementException;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.DynamicContainer;\nimport org.junit.jupiter.api.DynamicNode;\nimport org.junit.jupiter.api.DynamicTest;\nimport org.junit.jupiter.api.TestFactory;\nimport org.neo4j.driver.AuthTokens;\nimport org.neo4j.driver.Config;\nimport org.neo4j.driver.Driver;\nimport org.neo4j.driver.GraphDatabase;\nimport org.neo4j.driver.Result;\nimport org.neo4j.driver.Session;\nimport org.neo4j.driver.summary.ResultSummary;\nimport org.neo4j.driver.types.Node;\nimport org.testcontainers.junit.jupiter.Testcontainers;\nimport org.testcontainers.neo4j.Neo4jContainer;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * @author Michael J. Simons\n */\n@Testcontainers(disabledWithoutDocker = true)\nclass SchemaNamesIT {\n\n\tprivate static final Config DRIVER_CONFIG = Config.builder().withMaxConnectionPoolSize(1).build();\n\n\tprivate static final Map<Neo4jContainer, Driver> CACHED_CONNECTIONS = Collections.synchronizedMap(new HashMap<>());\n\n\tprivate static final String LATEST_VERSION = \"4.4\";\n\n\tprivate static final List<TestItem> TEST_DATA = Arrays.asList(\n\t\t\tnew TestItem(Category.Q, \"Simple label\", \"ABC\", \"ABC\"),\n\t\t\tnew TestItem(Category.Q, \"Simple label with non identifiers\", \"A Label\", \"A Label\"),\n\t\t\tnew TestItem(Category.Q, \"Simple label with backticks\", \"A` C\", \"A` C\"),\n\t\t\tnew TestItem(Category.Q, \"Escaped quotes\", \"A`` C\", \"A` C\"),\n\t\t\tnew TestItem(Category.Q, \"Backticks after blank \", \"A `Label\", \"A `Label\"),\n\t\t\tnew TestItem(Category.Q, \"Non consecutive backticks\", \"`A `Label\", \"`A `Label\"),\n\t\t\tnew TestItem(Category.U, \"Single unicode, no quoting needed\", \"ᑖ\", \"ᑖ\"),\n\t\t\tnew TestItem(Category.U, \"Single multibyte unicode, quoting needed\", \"⚡️\", \"⚡️\"),\n\t\t\tnew TestItem(Category.U, \"Unicode pair inside label\", \"Spring Data Neo4j⚡️RX\", \"Spring Data Neo4j⚡️RX\"),\n\t\t\tnew TestItem(Category.Q, \"Single backtick\", \"`\", \"`\"),\n\t\t\tnew TestItem(Category.Q, \"Single unicode literal backtick\", \"\\u0060\", \"`\"),\n\t\t\tnew TestItem(Category.Q, \"One escaped, one unescaped backtick\", \"```\", \"``\"),\n\t\t\tnew TestItem(Category.Q, \"One escaped, one unescaped unicode literal backtick\", \"\\u0060\\u0060\\u0060\", \"``\"),\n\t\t\tnew TestItem(Category.U, \"One escaped, one unescaped Cypher unicode literal backtick\",\n\t\t\t\t\t\"\\\\u0060\\\\u0060\\\\u0060\", \"``\"),\n\t\t\tnew TestItem(Category.Q, \"Backtick at end\", \"Hello`\", \"Hello`\"),\n\t\t\tnew TestItem(Category.Q, \"Escaped backticks\", \"Hi````there\", \"Hi``there\"),\n\t\t\tnew TestItem(Category.Q, \"Mixed escaped and non escaped backticks\", \"Hi`````there\", \"Hi```there\"),\n\t\t\tnew TestItem(Category.Q, \"Even number of scattered backticks\", \"`a`b`c`\", \"`a`b`c`\"),\n\t\t\tnew TestItem(Category.Q, \"Even number of scattered backticks (unicode literals)\",\n\t\t\t\t\t\"\\u0060a`b`c\\u0060d\\u0060\", \"`a`b`c`d`\"),\n\t\t\tnew TestItem(Category.Q, \"Even number of scattered backticks (Cypher unicode literals)\",\n\t\t\t\t\t\"\\\\u0060a`b`c\\\\u0060d\\\\u0060\", \"`a`b`c`d`\"),\n\t\t\tnew TestItem(Category.B, \"Escaped backslash followed by backtick\", \"Foo\\\\\\\\`bar\", \"Foo\\\\`bar\"),\n\t\t\tnew TestItem(Category.U, \"Escaped (invalid) unicode literal\", \"admin\\\\user\", \"admin\\\\user\"),\n\t\t\tnew TestItem(Category.U, \"Escaped (invalid) Cypher unicode literal\", \"admin\\\\\\\\user\", \"admin\\\\user\"),\n\t\t\tnew TestItem(Category.U, \"Cypher unicode literals\", \"\\\\u0075\\\\u1456\", \"uᑖ\"),\n\t\t\tnew TestItem(Category.U, \"Unicode literal\", \"\\u1456\", \"ᑖ\"),\n\t\t\tnew TestItem(Category.U, \"Non recursive Cypher unicode literals\", \"something\\\\u005C\\\\u00751456\",\n\t\t\t\t\t\"something\\\\u1456\"),\n\t\t\tnew TestItem(Category.U, \"Unicode literals creating a backtick unicode\", \"\\u005C\\\\u0060\", \"`\"),\n\t\t\tnew TestItem(Category.U, \"Unicode literals creating only the literal text of a a unicode literal\",\n\t\t\t\t\t\"\\\\u005Cu0060\", \"\\\\u0060\"),\n\t\t\tnew TestItem(Category.U, \"Cypher unicode literals creating unicode backtick literal\", \"\\\\u005C\\\\u0060\",\n\t\t\t\t\t\"\\\\`\"),\n\t\t\tnew TestItem(Category.B, \"Single backslash\", \"x\\\\y\", \"x\\\\y\"),\n\t\t\tnew TestItem(Category.B, \"Escaped single backslash\", \"x\\\\\\\\y\", \"x\\\\y\"),\n\t\t\tnew TestItem(Category.B, \"Escaped multiple backslash\", \"x\\\\\\\\\\\\\\\\y\", \"x\\\\\\\\y\"),\n\t\t\tnew TestItem(Category.E, \"Escaped backticks (Future Neo4j)\", \"x\\\\`y\", \"x`y\"),\n\t\t\tnew TestItem(Category.E, \"Escaped backticks (Future Neo4j)\", \"x\\\\```y\", \"x``y\"),\n\t\t\tnew TestItem(Category.E, \"Escaped backticks (Future Neo4j)\", \"x`\\\\```y\", \"x```y\"),\n\t\t\tnew TestItem(Category.Q, \"Unicode literal backtick at end\", \"Foo \\u0060\", \"Foo `\"),\n\t\t\tnew TestItem(Category.Q, \"Cypher unicode literal backtick at end\", \"Foo \\\\u0060\", \"Foo `\"));\n\n\tprivate static Driver newDriverInstance(Neo4jContainer server) {\n\t\treturn GraphDatabase.driver(server.getBoltUrl(), AuthTokens.basic(\"neo4j\", server.getAdminPassword()),\n\t\t\t\tDRIVER_CONFIG);\n\t}\n\n\t@AfterAll\n\tstatic void closeConnections() {\n\t\tCACHED_CONNECTIONS.values().forEach(Driver::close);\n\t}\n\n\t@TestFactory\n\tStream<DynamicNode> shouldHaveConsistentResultsOnAllSupportedVersions() {\n\t\tStream<String> versions;\n\t\tif (Boolean.getBoolean(\"SCHEMA_NAMES_TEST_ALL_VERSIONS\")) {\n\t\t\tversions = Stream.of(\"3.5\", \"4.0\", \"4.1\", \"4.2\", \"4.3\", LATEST_VERSION);\n\t\t}\n\t\telse {\n\t\t\tversions = Stream.of(LATEST_VERSION);\n\t\t}\n\t\treturn versions.map(version -> {\n\t\t\t@SuppressWarnings(\"resource\")\n\t\t\tNeo4jContainer neo4j = new Neo4jContainer(\"neo4j:\" + version).withReuse(true);\n\t\t\tneo4j.start();\n\n\t\t\tString[] majorMinor = version.split(\"\\\\.\");\n\t\t\tint major;\n\t\t\tint minor;\n\t\t\t// Latest supported must work without config\n\t\t\tif (SchemaNamesIT.LATEST_VERSION.equals(version)) {\n\t\t\t\tmajor = -1;\n\t\t\t\tminor = -1;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tmajor = Integer.parseInt(majorMinor[0]);\n\t\t\t\tminor = Integer.parseInt(majorMinor[1]);\n\t\t\t}\n\n\t\t\tStream<DynamicNode> categories = TEST_DATA.stream()\n\t\t\t\t.collect(Collectors.groupingBy(TestItem::category))\n\t\t\t\t.entrySet()\n\t\t\t\t.stream()\n\t\t\t\t.map(entry -> {\n\t\t\t\t\tStream<DynamicTest> nested = entry.getValue()\n\t\t\t\t\t\t.stream()\n\t\t\t\t\t\t.map(item -> DynamicTest.dynamicTest(item.description() + \" (\" + item.input + \")\", () -> {\n\t\t\t\t\t\t\tString schemaName = SchemaNames.sanitize(item.input(), false, major, minor)\n\t\t\t\t\t\t\t\t.orElseThrow(NoSuchElementException::new);\n\t\t\t\t\t\t\tDriver driver = CACHED_CONNECTIONS.computeIfAbsent(neo4j, SchemaNamesIT::newDriverInstance);\n\t\t\t\t\t\t\ttry (Session session = driver.session()) {\n\t\t\t\t\t\t\t\tResult result = session.run(String.format(\"CREATE (n:%s) RETURN n\", schemaName));\n\t\t\t\t\t\t\t\tNode node = result.single().get(0).asNode();\n\t\t\t\t\t\t\t\tassertThat(node.labels()).containsExactly(item.expected());\n\t\t\t\t\t\t\t\tResultSummary summary = result.consume();\n\t\t\t\t\t\t\t\tassertThat(summary.counters().nodesCreated()).isOne();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}));\n\t\t\t\t\treturn DynamicContainer.dynamicContainer(entry.getKey().value, nested);\n\t\t\t\t});\n\t\t\treturn DynamicContainer.dynamicContainer(version, categories);\n\t\t});\n\t}\n\n\tenum Category {\n\n\t\tQ(\"Quoting\"), U(\"Unicode\"), B(\"Backslashes\"), E(\"Escaping\");\n\n\t\tprivate final String value;\n\n\t\tCategory(String value) {\n\t\t\tthis.value = value;\n\t\t}\n\n\t}\n\n\trecord TestItem(Category category, String description, String input, String expected) {\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-schema-name-support/src/test/java/org/neo4j/cypherdsl/support/schema_name/SchemaNamesTests.java",
    "content": "/*\n * Copyright (c) 2019-2026 \"Neo4j,\"\n * Neo4j Sweden AB [https://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.neo4j.cypherdsl.support.schema_name;\n\nimport java.lang.reflect.Field;\nimport java.util.Map;\nimport java.util.Optional;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;\nimport static org.assertj.core.api.Assertions.assertThatNoException;\n\n/**\n * @author Michael J. Simons\n */\nclass SchemaNamesTests {\n\n\t@Test\n\tvoid shouldDealWithNull() {\n\t\tassertThat(SchemaNames.sanitize(null)).isEmpty();\n\t}\n\n\t@Test\n\tvoid shouldDealWithEmpty() {\n\t\tassertThat(SchemaNames.sanitize(\"\")).isEmpty();\n\t}\n\n\t@Test\n\tvoid shouldThrowOnInvalidVersions() {\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> SchemaNames.sanitize(\"whatever\", false, 2, 3))\n\t\t\t.withMessage(\"Unsupported major version: 2\");\n\t\tassertThatIllegalArgumentException().isThrownBy(() -> SchemaNames.sanitize(\"whatever\", false, 7, 3))\n\t\t\t.withMessage(\"Unsupported major version: 7\");\n\t}\n\n\t@Test\n\tvoid shouldSupportFutureNeo4j() {\n\t\tassertThat(SchemaNames.sanitize(\"x\\\\\\\\y\", false, 6, -1)).hasValue(\"`x\\\\\\\\y`\");\n\t}\n\n\t@Test\n\tvoid shouldBeAbleToForceQuotes() {\n\t\tassertThat(SchemaNames.sanitize(\"a\", true, -1, -1)).hasValue(\"`a`\");\n\t}\n\n\t@Test\n\tvoid shouldQuoteEmptyString() {\n\t\tassertThat(SchemaNames.sanitize(\" \", false, -1, -1)).hasValue(\"` `\");\n\t}\n\n\t@Test\n\tvoid shouldCacheData() throws Exception {\n\t\tField cacheField = SchemaNames.class.getDeclaredField(\"CACHE\");\n\t\tcacheField.setAccessible(true);\n\t\tMap<?, ?> cache = (Map<?, ?>) cacheField.get(null);\n\n\t\tcache.clear();\n\t\tassertThatNoException().isThrownBy(() -> SchemaNames.sanitize(\"a\"));\n\t\tassertThatNoException().isThrownBy(() -> SchemaNames.sanitize(\"b\"));\n\t\tassertThatNoException().isThrownBy(() -> SchemaNames.sanitize(\"a\"));\n\t\tassertThatNoException().isThrownBy(() -> SchemaNames.sanitize(\"a\", false, -23, -42));\n\n\t\tassertThat(cache).hasSize(2);\n\t}\n\n\t@Test\n\tvoid shouldOnlyObfuscateUnicodeWhenRequired() {\n\t\tString plain = \"`administrator\\\\user`\";\n\t\tString obfuscated = \"`administrator\\\\u005C\\\\u0075ser`\";\n\n\t\tOptional<String> v = SchemaNames.sanitize(\"administrator\\\\user\", false, 3, -1);\n\t\tassertThat(v).hasValue(plain);\n\n\t\tv = SchemaNames.sanitize(\"administrator\\\\user\", false, 4, 0);\n\t\tassertThat(v).hasValue(plain);\n\n\t\tv = SchemaNames.sanitize(\"administrator\\\\user\", false, 4, -1);\n\t\tassertThat(v).hasValue(obfuscated);\n\n\t\tv = SchemaNames.sanitize(\"administrator\\\\user\", false, 4, 2);\n\t\tassertThat(v).hasValue(obfuscated);\n\t}\n\n\t@Test\n\tvoid shouldHandleEscapedBackslashes() {\n\n\t\tfor (String input : new String[] { \"x\\\\y\", \"x\\\\\\\\y\" }) {\n\t\t\tOptional<String> v = SchemaNames.sanitize(input, false, 4, -1);\n\t\t\tString expected = \"`x\\\\y`\";\n\t\t\tassertThat(v).hasValue(expected);\n\n\t\t\tv = SchemaNames.sanitize(\"x\\\\\\\\y\", false, 4, -1);\n\t\t\tassertThat(v).hasValue(expected);\n\t\t}\n\n\t\tOptional<String> v = SchemaNames.sanitize(\"x\\\\\\\\y\", false, 6, -1);\n\t\tassertThat(v).hasValue(\"`x\\\\\\\\y`\");\n\t}\n\n}\n"
  },
  {
    "path": "neo4j-cypher-dsl-test-results/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<parent>\n\t\t<groupId>org.neo4j</groupId>\n\t\t<artifactId>neo4j-cypher-dsl-parent</artifactId>\n\t\t<version>${revision}${sha1}${changelist}</version>\n\t</parent>\n\n\t<artifactId>neo4j-cypher-dsl-test-results</artifactId>\n\n\t<name>Aggregated test results</name>\n\n\t<properties>\n\t\t<java-module-name>org.neo4j.cypherdsl.test_results</java-module-name>\n\t</properties>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-dsl-bom</artifactId>\n\t\t\t\t<version>${project.version}</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl-codegen-core</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl-codegen-ogm</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<!-- See below -->\n\t\t\t\t\t<groupId>com.querydsl</groupId>\n\t\t\t\t\t<artifactId>querydsl-apt</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl-codegen-sdn6</artifactId>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<!-- Depends on com.google.code.findbugs:annotations and so does the neo4j-cypher-javacc-parser, which is actually used in contrast to the Spring QueryDSL integration. -->\n\t\t\t\t\t<groupId>com.querydsl</groupId>\n\t\t\t\t\t<artifactId>querydsl-apt</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl-parser</artifactId>\n\t\t\t<version>${project.version}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t<artifactId>neo4j-cypher-dsl-schema-name-support</artifactId>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.mycila</groupId>\n\t\t\t\t<artifactId>license-maven-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<dependencyEnforce>false</dependencyEnforce>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.jacoco</groupId>\n\t\t\t\t<artifactId>jacoco-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>prepare-agent</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>report-aggregate</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>report-aggregate</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>verify</phase>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<dataFileIncludes>\n\t\t\t\t\t\t\t\t<dataFileInclude>**/jacoco.exec</dataFileInclude>\n\t\t\t\t\t\t\t</dataFileIncludes>\n\t\t\t\t\t\t\t<outputDirectory>${project.reporting.outputDirectory}/jacoco-aggregate</outputDirectory>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t\t<configuration combine.self=\"append\">\n\t\t\t\t\t<systemPropertyVariables>\n\t\t\t\t\t\t<jacoco-agent.destfile>**/jacoco.exec</jacoco-agent.destfile>\n\t\t\t\t\t</systemPropertyVariables>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-install-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skip>true</skip>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-jar-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<skipIfEmpty>true</skipIfEmpty>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    Copyright (c) 2019-2026 \"Neo4j,\"\n    Neo4j Sweden AB [https://neo4j.com]\n\n    This file is part of Neo4j.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        https://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>org.neo4j</groupId>\n\t<artifactId>neo4j-cypher-dsl-parent</artifactId>\n\t<version>${revision}${sha1}${changelist}</version>\n\t<packaging>pom</packaging>\n\n\t<name>Neo4j Cypher DSL</name>\n\t<description>A DSL for generating Cypher statements for Neo4j</description>\n\t<url>https://neo4j.github.io/cypher-dsl</url>\n\n\t<inceptionYear>2011</inceptionYear>\n\t<organization>\n\t\t<name>Neo4j, Neo4j Sweden AB</name>\n\t\t<url>https://neo4j.com</url>\n\t</organization>\n\t<licenses>\n\t\t<license>\n\t\t\t<name>The Apache Software License, Version 2.0</name>\n\t\t\t<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>\n\t\t\t<distribution>repo</distribution>\n\t\t</license>\n\t</licenses>\n\n\t<developers>\n\t\t<developer>\n\t\t\t<id>gmeier</id>\n\t\t\t<name>Gerrit Meier</name>\n\t\t\t<email>gerrit.meier at neo4j.com</email>\n\t\t\t<organization>Neo Technology</organization>\n\t\t\t<organizationUrl>https://neo4j.com</organizationUrl>\n\t\t\t<roles>\n\t\t\t\t<role>Developer</role>\n\t\t\t</roles>\n\t\t\t<timezone>+1</timezone>\n\t\t</developer>\n\t\t<developer>\n\t\t\t<id>mhunger</id>\n\t\t\t<name>Michael Hunger</name>\n\t\t\t<email>michael.hunger at neo4j.com</email>\n\t\t\t<organization>Neo Technology</organization>\n\t\t\t<organizationUrl>https://neo4j.com</organizationUrl>\n\t\t\t<roles>\n\t\t\t\t<role>Developer</role>\n\t\t\t</roles>\n\t\t\t<timezone>+1</timezone>\n\t\t</developer>\n\t\t<developer>\n\t\t\t<id>msimons</id>\n\t\t\t<name>Michael Simons</name>\n\t\t\t<email>michael.simons at neo4j.com</email>\n\t\t\t<organization>Neo Technology</organization>\n\t\t\t<organizationUrl>https://neo4j.com</organizationUrl>\n\t\t\t<roles>\n\t\t\t\t<role>Project Lead</role>\n\t\t\t</roles>\n\t\t\t<timezone>+1</timezone>\n\t\t</developer>\n\t\t<developer>\n\t\t\t<id>fbiville</id>\n\t\t\t<name>Florent Biville</name>\n\t\t\t<email>florent.biville at neo4j.com</email>\n\t\t\t<organization>Neo Technology</organization>\n\t\t\t<organizationUrl>https://neo4j.com</organizationUrl>\n\t\t\t<roles>\n\t\t\t\t<role>developer</role>\n\t\t\t</roles>\n\t\t\t<timezone>+1</timezone>\n\t\t</developer>\n\t\t<developer>\n\t\t\t<id>Andy2003</id>\n\t\t\t<name>Andreas Berger</name>\n\t\t\t<email>andreas at berger-ecommerce.com</email>\n\t\t\t<roles>\n\t\t\t\t<role>Developer</role>\n\t\t\t</roles>\n\t\t\t<timezone>+1</timezone>\n\t\t</developer>\n\t\t<developer>\n\t\t\t<id>aince</id>\n\t\t\t<name>Ali Ince</name>\n\t\t\t<email>ali.ince at neo4j.com</email>\n\t\t\t<organization>Neo Technology</organization>\n\t\t\t<organizationUrl>https://neo4j.com</organizationUrl>\n\t\t\t<roles>\n\t\t\t\t<role>developer</role>\n\t\t\t</roles>\n\t\t\t<timezone>0</timezone>\n\t\t</developer>\n\t</developers>\n\n\t<modules>\n\t\t<module>neo4j-cypher-dsl-bom</module>\n\t\t<module>neo4j-cypher-dsl-schema-name-support</module>\n\t\t<module>neo4j-cypher-dsl-build</module>\n\t\t<module>neo4j-cypher-dsl</module>\n\t\t<module>neo4j-cypher-dsl-codegen</module>\n\t\t<module>neo4j-cypher-dsl-parser</module>\n\t\t<module>neo4j-cypher-dsl-native-tests</module>\n\t\t<module>neo4j-cypher-dsl-examples</module>\n\t\t<module>neo4j-cypher-dsl-test-results</module>\n\t</modules>\n\n\t<scm>\n\t\t<connection>scm:git:git@github.com:neo4j/cypher-dsl.git</connection>\n\t\t<developerConnection>scm:git:git@github.com:neo4j/cypher-dsl.git</developerConnection>\n\t\t<tag>HEAD</tag>\n\t\t<url>https://github.com/neo4j/cypher-dsl</url>\n\t</scm>\n\n\t<properties>\n\t\t<aggregate.report.dir>neo4j-cypher-dsl-test-results/target/site/jacoco-aggregate/jacoco.xml</aggregate.report.dir>\n\t\t<apiguardian.version>1.1.2</apiguardian.version>\n\t\t<archunit.version>1.4.2</archunit.version>\n\t\t<asciidoctor-maven-plugin.version>3.2.0</asciidoctor-maven-plugin.version>\n\t\t<asciidoctorj-diagram.version>3.2.1</asciidoctorj-diagram.version>\n\t\t<asciidoctorj.version>3.0.1</asciidoctorj.version>\n\t\t<asm.version>9.9.1</asm.version>\n\t\t<assertj.version>3.27.7</assertj.version>\n\t\t<auto-common.version>1.2.2</auto-common.version>\n\t\t<cglib.version>3.3.0</cglib.version>\n\t\t<changelist>-SNAPSHOT</changelist>\n\t\t<checker-qual.version>4.1.0</checker-qual.version>\n\t\t<checkstyle.version>13.4.2</checkstyle.version>\n\t\t<compile-testing.version>0.23.0</compile-testing.version>\n\t\t<covered-ratio-complexity>0.75</covered-ratio-complexity>\n\t\t<covered-ratio-instructions>0.75</covered-ratio-instructions>\n\t\t<cypher-dsl.version.next/>\n\t\t<cypher-dsl.version.old>2022.7.3</cypher-dsl.version.old>\n\t\t<error_prone_annotations.version>2.23.0</error_prone_annotations.version>\n\t\t<exec-maven-plugin.version>3.6.3</exec-maven-plugin.version>\n\t\t<flatten-maven-plugin.version>1.7.3</flatten-maven-plugin.version>\n\t\t<guava.version>33.6.0-jre</guava.version>\n\t\t<jackson.version>2.21.3</jackson.version>\n\t\t<jacoco-maven-plugin.version>0.8.14</jacoco-maven-plugin.version>\n\t\t<japicmp-maven-plugin.version>0.25.6</japicmp-maven-plugin.version>\n\t\t<java-module-name/>\n\t\t<java.version>25</java.version>\n\t\t<javapoet.version>1.13.0</javapoet.version>\n\t\t<javax.annotation-api.version>1.3.2</javax.annotation-api.version>\n\t\t<jaxb.version>2.3.1</jaxb.version>\n\t\t<joda-time.version>2.14.1</joda-time.version>\n\t\t<jreleaser-maven-plugin.version>1.23.0</jreleaser-maven-plugin.version>\n\t\t<jsr305.version>3.0.2</jsr305.version>\n\t\t<junit-jupiter.version>6.0.3</junit-jupiter.version>\n\t\t<license-maven-plugin.version>5.0.0</license-maven-plugin.version>\n\t\t<maven-checkstyle-plugin.version>3.6.0</maven-checkstyle-plugin.version>\n\t\t<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>\n\t\t<maven-deploy-plugin.version>3.1.4</maven-deploy-plugin.version>\n\t\t<maven-enforcer-plugin.version>3.6.2</maven-enforcer-plugin.version>\n\t\t<maven-failsafe-plugin.version>3.5.5</maven-failsafe-plugin.version>\n\t\t<maven-install-plugin.version>3.1.4</maven-install-plugin.version>\n\t\t<maven-jar-plugin.version>3.5.0</maven-jar-plugin.version>\n\t\t<maven-javadoc-plugin.version>3.12.0</maven-javadoc-plugin.version>\n\t\t<maven-resources-plugin.version>3.5.0</maven-resources-plugin.version>\n\t\t<maven-scm-plugin.version>1.12.0</maven-scm-plugin.version>\n\t\t<maven-shade-plugin.version>3.6.2</maven-shade-plugin.version>\n\t\t<maven-site-plugin.version>3.21.0</maven-site-plugin.version>\n\t\t<maven-source-plugin.version>3.4.0</maven-source-plugin.version>\n\t\t<maven-surefire-plugin.version>3.5.5</maven-surefire-plugin.version>\n\t\t<maven.compiler.debug>true</maven.compiler.debug>\n\t\t<maven.compiler.parameters>true</maven.compiler.parameters>\n\t\t<maven.compiler.release>17</maven.compiler.release>\n\t\t<maven.version>3.9.12</maven.version>\n\t\t<mockito.version>5.23.0</mockito.version>\n\t\t<moditect-maven-plugin.version>1.3.0.Final</moditect-maven-plugin.version>\n\t\t<neo4j-java-driver.version>6.1.0</neo4j-java-driver.version>\n\t\t<neo4j-ogm-quarkus.version>4.2.5</neo4j-ogm-quarkus.version>\n\t\t<neo4j-ogm.version>5.0.5</neo4j-ogm.version>\n\t\t<neo4j.version>5.26.25</neo4j.version>\n\t\t<opencsv.version>5.12.0</opencsv.version>\n\t\t<project.build.docs>${project.build.directory}/docs</project.build.docs>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<quarkus.platform.version>3.35.1</quarkus.platform.version>\n\t\t<querydsl.version>5.1.0</querydsl.version>\n\t\t<revision>9999</revision>\n\t\t<sha1/>\n\t\t<slf4j.version>2.0.17</slf4j.version>\n\t\t<sonar-maven-plugin.version>5.6.0.6792</sonar-maven-plugin.version>\n\t\t<sortpom-maven-plugin.version>4.0.0</sortpom-maven-plugin.version>\n\t\t<spring-data-neo4j.version>8.0.5</spring-data-neo4j.version>\n\t\t<spring-javaformat.version>0.0.47</spring-javaformat.version>\n\t\t<testcontainers.version>2.0.5</testcontainers.version>\n\t\t<use-latest-version-for-docs>0</use-latest-version-for-docs>\n\t</properties>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.fasterxml.jackson</groupId>\n\t\t\t\t<artifactId>jackson-bom</artifactId>\n\t\t\t\t<version>${jackson.version}</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.junit</groupId>\n\t\t\t\t<artifactId>junit-bom</artifactId>\n\t\t\t\t<version>${junit-jupiter.version}</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.testcontainers</groupId>\n\t\t\t\t<artifactId>testcontainers-bom</artifactId>\n\t\t\t\t<version>${testcontainers.version}</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<!-- Testing depends on this directly, which clashes with auto-value's dependencies -->\n\t\t\t\t<groupId>com.google.auto</groupId>\n\t\t\t\t<artifactId>auto-common</artifactId>\n\t\t\t\t<version>${auto-common.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<!-- Only added to avoid dependency convergence errors -->\n\t\t\t\t<groupId>com.google.code.findbugs</groupId>\n\t\t\t\t<artifactId>jsr305</artifactId>\n\t\t\t\t<version>${jsr305.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.querydsl</groupId>\n\t\t\t\t<artifactId>querydsl-core</artifactId>\n\t\t\t\t<version>${querydsl.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.squareup</groupId>\n\t\t\t\t<artifactId>javapoet</artifactId>\n\t\t\t\t<version>${javapoet.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.tngtech.archunit</groupId>\n\t\t\t\t<artifactId>archunit</artifactId>\n\t\t\t\t<version>${archunit.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>javax.xml.bind</groupId>\n\t\t\t\t<artifactId>jaxb-api</artifactId>\n\t\t\t\t<version>${jaxb.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<!-- Coming in test scope via AsciiDoctor in different versions -->\n\t\t\t\t<groupId>joda-time</groupId>\n\t\t\t\t<artifactId>joda-time</artifactId>\n\t\t\t\t<version>${joda-time.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.apiguardian</groupId>\n\t\t\t\t<artifactId>apiguardian-api</artifactId>\n\t\t\t\t<version>${apiguardian.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.asciidoctor</groupId>\n\t\t\t\t<artifactId>asciidoctorj</artifactId>\n\t\t\t\t<version>${asciidoctorj.version}</version>\n\t\t\t\t<exclusions>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>rubygems</groupId>\n\t\t\t\t\t\t<!-- Not needed -->\n\t\t\t\t\t\t<artifactId>test-unit</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t</exclusions>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-cypher-javacc-parser</artifactId>\n\t\t\t\t<version>${neo4j.version}</version>\n\t\t\t\t<exclusions>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>org.scala-lang</groupId>\n\t\t\t\t\t\t<artifactId>scala-reflect</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t</exclusions>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-ogm-core</artifactId>\n\t\t\t\t<version>${neo4j-ogm.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j</groupId>\n\t\t\t\t<artifactId>neo4j-ogm-quarkus</artifactId>\n\t\t\t\t<version>${neo4j-ogm-quarkus.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.neo4j.driver</groupId>\n\t\t\t\t<artifactId>neo4j-java-driver</artifactId>\n\t\t\t\t<version>${neo4j-java-driver.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.ow2.asm</groupId>\n\t\t\t\t<artifactId>asm</artifactId>\n\t\t\t\t<version>${asm.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t\t<artifactId>slf4j-api</artifactId>\n\t\t\t\t<version>${slf4j.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t\t<artifactId>slf4j-simple</artifactId>\n\t\t\t\t<version>${slf4j.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.data</groupId>\n\t\t\t\t<artifactId>spring-data-neo4j</artifactId>\n\t\t\t\t<version>${spring-data-neo4j.version}</version>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>cglib</groupId>\n\t\t\t\t<artifactId>cglib</artifactId>\n\t\t\t\t<version>${cglib.version}</version>\n\t\t\t\t<scope>test</scope>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.google.errorprone</groupId>\n\t\t\t\t<artifactId>error_prone_annotations</artifactId>\n\t\t\t\t<version>${error_prone_annotations.version}</version>\n\t\t\t\t<scope>test</scope>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.google.guava</groupId>\n\t\t\t\t<artifactId>guava</artifactId>\n\t\t\t\t<version>${guava.version}</version>\n\t\t\t\t<scope>test</scope>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.google.testing.compile</groupId>\n\t\t\t\t<artifactId>compile-testing</artifactId>\n\t\t\t\t<version>${compile-testing.version}</version>\n\t\t\t\t<scope>test</scope>\n\t\t\t\t<exclusions>\n\t\t\t\t\t<exclusion>\n\t\t\t\t\t\t<groupId>junit</groupId>\n\t\t\t\t\t\t<artifactId>junit</artifactId>\n\t\t\t\t\t</exclusion>\n\t\t\t\t</exclusions>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.assertj</groupId>\n\t\t\t\t<artifactId>assertj-core</artifactId>\n\t\t\t\t<version>${assertj.version}</version>\n\t\t\t\t<scope>test</scope>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.checkerframework</groupId>\n\t\t\t\t<artifactId>checker-qual</artifactId>\n\t\t\t\t<version>${checker-qual.version}</version>\n\t\t\t\t<scope>test</scope>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.mockito</groupId>\n\t\t\t\t<artifactId>mockito-core</artifactId>\n\t\t\t\t<version>${mockito.version}</version>\n\t\t\t\t<scope>test</scope>\n\t\t\t</dependency>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.mockito</groupId>\n\t\t\t\t<artifactId>mockito-junit-jupiter</artifactId>\n\t\t\t\t<version>${mockito.version}</version>\n\t\t\t\t<scope>test</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<build>\n\t\t<pluginManagement>\n\t\t\t<plugins>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.sonarsource.scanner.maven</groupId>\n\t\t\t\t\t<artifactId>sonar-maven-plugin</artifactId>\n\t\t\t\t\t<version>${sonar-maven-plugin.version}</version>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.moditect</groupId>\n\t\t\t\t\t<artifactId>moditect-maven-plugin</artifactId>\n\t\t\t\t\t<version>${moditect-maven-plugin.version}</version>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.jacoco</groupId>\n\t\t\t\t\t<artifactId>jacoco-maven-plugin</artifactId>\n\t\t\t\t\t<version>${jacoco-maven-plugin.version}</version>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<includes>\n\t\t\t\t\t\t\t<include>**/*</include>\n\t\t\t\t\t\t</includes>\n\t\t\t\t\t</configuration>\n\t\t\t\t\t<executions>\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<id>pre-unit-test</id>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>prepare-agent</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t\t<append>true</append>\n\t\t\t\t\t\t\t</configuration>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<id>pre-integration-test</id>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>prepare-agent-integration</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t\t<append>true</append>\n\t\t\t\t\t\t\t\t<destFile>${project.build.directory}/jacoco.exec</destFile>\n\t\t\t\t\t\t\t</configuration>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<id>report-and-check</id>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>report</goal>\n\t\t\t\t\t\t\t\t<goal>check</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t<phase>post-integration-test</phase>\n\t\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t\t<rules>\n\t\t\t\t\t\t\t\t\t<rule>\n\t\t\t\t\t\t\t\t\t\t<element>BUNDLE</element>\n\t\t\t\t\t\t\t\t\t\t<limits>\n\t\t\t\t\t\t\t\t\t\t\t<limit>\n\t\t\t\t\t\t\t\t\t\t\t\t<counter>INSTRUCTION</counter>\n\t\t\t\t\t\t\t\t\t\t\t\t<value>COVEREDRATIO</value>\n\t\t\t\t\t\t\t\t\t\t\t\t<minimum>${covered-ratio-instructions}</minimum>\n\t\t\t\t\t\t\t\t\t\t\t</limit>\n\t\t\t\t\t\t\t\t\t\t\t<limit>\n\t\t\t\t\t\t\t\t\t\t\t\t<counter>COMPLEXITY</counter>\n\t\t\t\t\t\t\t\t\t\t\t\t<value>COVEREDRATIO</value>\n\t\t\t\t\t\t\t\t\t\t\t\t<minimum>${covered-ratio-complexity}</minimum>\n\t\t\t\t\t\t\t\t\t\t\t</limit>\n\t\t\t\t\t\t\t\t\t\t</limits>\n\t\t\t\t\t\t\t\t\t</rule>\n\t\t\t\t\t\t\t\t</rules>\n\t\t\t\t\t\t\t</configuration>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t</executions>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-shade-plugin</artifactId>\n\t\t\t\t\t<version>${maven-shade-plugin.version}</version>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-install-plugin</artifactId>\n\t\t\t\t\t<version>${maven-install-plugin.version}</version>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-deploy-plugin</artifactId>\n\t\t\t\t\t<version>${maven-deploy-plugin.version}</version>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t\t<version>${maven-compiler-plugin.version}</version>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<parameters>true</parameters>\n\t\t\t\t\t\t<forceJavacCompilerUse>true</forceJavacCompilerUse>\n\t\t\t\t\t\t<showWarnings>true</showWarnings>\n\t\t\t\t\t\t<compilerArgs>\n\t\t\t\t\t\t\t<arg>-Xlint:all,-options,-path,-processing,-exports</arg>\n\t\t\t\t\t\t\t<arg>-Werror</arg>\n\t\t\t\t\t\t</compilerArgs>\n\t\t\t\t\t</configuration>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t\t<version>${maven-javadoc-plugin.version}</version>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<quiet>true</quiet>\n\t\t\t\t\t\t<detectOfflineLinks>false</detectOfflineLinks>\n\t\t\t\t\t\t<detectJavaApiLink>true</detectJavaApiLink>\n\t\t\t\t\t\t<release>${maven.compiler.release}</release>\n\t\t\t\t\t\t<tags>\n\t\t\t\t\t\t\t<tag>\n\t\t\t\t\t\t\t\t<name>neo4j.version</name>\n\t\t\t\t\t\t\t\t<placement>a</placement>\n\t\t\t\t\t\t\t\t<head>Neo4j version required</head>\n\t\t\t\t\t\t\t</tag>\n\t\t\t\t\t\t</tags>\n\t\t\t\t\t</configuration>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-jar-plugin</artifactId>\n\t\t\t\t\t<version>${maven-jar-plugin.version}</version>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>io.spring.javaformat</groupId>\n\t\t\t\t\t<artifactId>spring-javaformat-maven-plugin</artifactId>\n\t\t\t\t\t<version>${spring-javaformat.version}</version>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-checkstyle-plugin</artifactId>\n\t\t\t\t\t<version>${maven-checkstyle-plugin.version}</version>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<excludes>**/module-info.java</excludes>\n\t\t\t\t\t\t<includeTestSourceDirectory>true</includeTestSourceDirectory>\n\t\t\t\t\t\t<configLocation>etc/checkstyle/config.xml</configLocation>\n\t\t\t\t\t\t<suppressionsLocation>etc/checkstyle/suppressions.xml</suppressionsLocation>\n\t\t\t\t\t\t<inputEncoding>${project.build.sourceEncoding}</inputEncoding>\n\t\t\t\t\t\t<consoleOutput>true</consoleOutput>\n\t\t\t\t\t\t<failsOnError>true</failsOnError>\n\t\t\t\t\t\t<includeTestSourceDirectory>true</includeTestSourceDirectory>\n\t\t\t\t\t</configuration>\n\t\t\t\t\t<dependencies>\n\t\t\t\t\t\t<dependency>\n\t\t\t\t\t\t\t<groupId>com.puppycrawl.tools</groupId>\n\t\t\t\t\t\t\t<artifactId>checkstyle</artifactId>\n\t\t\t\t\t\t\t<version>${checkstyle.version}</version>\n\t\t\t\t\t\t</dependency>\n\t\t\t\t\t\t<dependency>\n\t\t\t\t\t\t\t<groupId>io.spring.javaformat</groupId>\n\t\t\t\t\t\t\t<artifactId>spring-javaformat-checkstyle</artifactId>\n\t\t\t\t\t\t\t<version>${spring-javaformat.version}</version>\n\t\t\t\t\t\t</dependency>\n\t\t\t\t\t</dependencies>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t\t\t<version>${maven-surefire-plugin.version}</version>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-failsafe-plugin</artifactId>\n\t\t\t\t\t<version>${maven-failsafe-plugin.version}</version>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-resources-plugin</artifactId>\n\t\t\t\t\t<version>${maven-resources-plugin.version}</version>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-site-plugin</artifactId>\n\t\t\t\t\t<version>${maven-site-plugin.version}</version>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>com.github.ekryd.sortpom</groupId>\n\t\t\t\t\t<artifactId>sortpom-maven-plugin</artifactId>\n\t\t\t\t\t<version>${sortpom-maven-plugin.version}</version>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<encoding>${project.build.sourceEncoding}</encoding>\n\t\t\t\t\t\t<keepBlankLines>true</keepBlankLines>\n\t\t\t\t\t\t<nrOfIndentSpace>-1</nrOfIndentSpace>\n\t\t\t\t\t\t<sortProperties>true</sortProperties>\n\t\t\t\t\t\t<sortDependencies>scope,groupId,artifactId</sortDependencies>\n\t\t\t\t\t\t<sortDependencyExclusions>groupId,artifactId</sortDependencyExclusions>\n\t\t\t\t\t\t<createBackupFile>false</createBackupFile>\n\t\t\t\t\t\t<expandEmptyElements>false</expandEmptyElements>\n\t\t\t\t\t</configuration>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>com.github.siom79.japicmp</groupId>\n\t\t\t\t\t<artifactId>japicmp-maven-plugin</artifactId>\n\t\t\t\t\t<version>${japicmp-maven-plugin.version}</version>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<oldVersion>\n\t\t\t\t\t\t\t<dependency>\n\t\t\t\t\t\t\t\t<groupId>${project.groupId}</groupId>\n\t\t\t\t\t\t\t\t<artifactId>${project.artifactId}</artifactId>\n\t\t\t\t\t\t\t\t<version>${cypher-dsl.version.old}</version>\n\t\t\t\t\t\t\t\t<type>jar</type>\n\t\t\t\t\t\t\t</dependency>\n\t\t\t\t\t\t</oldVersion>\n\t\t\t\t\t\t<newVersion>\n\t\t\t\t\t\t\t<file>\n\t\t\t\t\t\t\t\t<path>${project.build.directory}/${project.artifactId}-${project.version}.${project.packaging}</path>\n\t\t\t\t\t\t\t</file>\n\t\t\t\t\t\t</newVersion>\n\t\t\t\t\t\t<parameter>\n\t\t\t\t\t\t\t<ignoreNonResolvableArtifacts>true</ignoreNonResolvableArtifacts>\n\t\t\t\t\t\t\t<breakBuildBasedOnSemanticVersioning>true</breakBuildBasedOnSemanticVersioning>\n\t\t\t\t\t\t\t<!--\n\t\t\t\t\t\t\t | See this helpful discussion: https://github.com/siom79/japicmp/issues/201\n\t\t\t\t\t\t\t | The interfaces we have are generally not be implemented by our users, but are just part\n\t\t\t\t\t\t\t | of the DSL contract. So it rather safe to assume compatibility.\n\t\t\t\t\t\t\t | Further reading:\n\t\t\t\t\t\t\t | https://docs.oracle.com/javase/specs/jls/se11/html/jls-13.html#jls-13.5.3\n\t\t\t\t\t\t\t -->\n\t\t\t\t\t\t\t<overrideCompatibilityChangeParameters>\n\t\t\t\t\t\t\t\t<overrideCompatibilityChangeParameter>\n\t\t\t\t\t\t\t\t\t<compatibilityChange>METHOD_NEW_DEFAULT</compatibilityChange>\n\t\t\t\t\t\t\t\t\t<binaryCompatible>true</binaryCompatible>\n\t\t\t\t\t\t\t\t\t<sourceCompatible>true</sourceCompatible>\n\t\t\t\t\t\t\t\t\t<!-- To make it tick with METHOD_DEFAULT_ADDED_IN_IMPLEMENTED_INTERFACE below, we must wind this down from MAJOR to MINOR. -->\n\t\t\t\t\t\t\t\t\t<semanticVersionLevel>MINOR</semanticVersionLevel>\n\t\t\t\t\t\t\t\t</overrideCompatibilityChangeParameter>\n\t\t\t\t\t\t\t\t<overrideCompatibilityChangeParameter>\n\t\t\t\t\t\t\t\t\t<compatibilityChange>METHOD_DEFAULT_ADDED_IN_IMPLEMENTED_INTERFACE</compatibilityChange>\n\t\t\t\t\t\t\t\t\t<binaryCompatible>true</binaryCompatible>\n\t\t\t\t\t\t\t\t\t<sourceCompatible>true</sourceCompatible>\n\t\t\t\t\t\t\t\t</overrideCompatibilityChangeParameter>\n\t\t\t\t\t\t\t</overrideCompatibilityChangeParameters>\n\t\t\t\t\t\t\t<excludes>\n\t\t\t\t\t\t\t\t<!-- Internal packages, protected by Java Module system on module path. -->\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.internal</exclude>\n\t\t\t\t\t\t\t\t<!-- 2023.1.0, changed for #553. It's safely marked as internal -->\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.ast.TypedSubtree</exclude>\n\t\t\t\t\t\t\t\t<!-- Not exported either, but let's be a more lenient. -->\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.utils.Strings#isValidJavaIdentifierPartAt(int,int)</exclude>\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.utils.Strings#isIdentifier(java.lang.CharSequence)</exclude>\n\t\t\t\t\t\t\t\t<!-- Those are shaded classes from Neo4j, and we work around their changes. -->\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.parser.internal</exclude>\n\t\t\t\t\t\t\t\t<!-- 2023.0.4 and higher, this should have been package private to begin with -->\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.parser.NodeAtom</exclude>\n\t\t\t\t\t\t\t\t<!-- 2023.1.0 and higher, this is internal API -->\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.StatementContext</exclude>\n\t\t\t\t\t\t\t\t<!-- 2023.2.0 and higher, removed internal API -->\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.Unwind#getVariable()</exclude>\n\t\t\t\t\t\t\t\t<!-- 2023.2.0 and higher, made Asterisk identifiable proper -->\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.ExposesWith#with(org.neo4j.cypherdsl.core.Asterisk)</exclude>\n\t\t\t\t\t\t\t\t<!-- 2023.2.0 and higher, internal API being polished -->\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.DefaultStatementBuilder$DefaultStatementWithWithBuilder</exclude>\n\t\t\t\t\t\t\t\t<!-- 2023.5.0 and higher, move up an interface, not to be implemented, has not been removed -->\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.StatementBuilder$ExposesSetAndRemove#set(org.neo4j.cypherdsl.core.Node,java.util.Collection)</exclude>\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.StatementBuilder$ExposesSetAndRemove#set(org.neo4j.cypherdsl.core.Node,java.lang.String[])</exclude>\n\t\t\t\t\t\t\t\t<!-- 2023.9.7 and higher, changed to a broader return type, only we implement that interface -->\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.ExposesSubqueryCall#call(org.neo4j.cypherdsl.core.Statement)</exclude>\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.ExposesSubqueryCall#call(org.neo4j.cypherdsl.core.Statement,java.lang.String[])</exclude>\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.ExposesSubqueryCall#call(org.neo4j.cypherdsl.core.Statement,org.neo4j.cypherdsl.core.IdentifiableElement[])</exclude>\n\t\t\t\t\t\t\t\t<!-- 2023.9.8 and higher, internal API -->\n\t\t\t\t\t\t\t\t<exclude>org.neo4j.cypherdsl.core.StatementBuilder$OngoingUpdate</exclude>\n\t\t\t\t\t\t\t</excludes>\n\t\t\t\t\t\t\t<ignoreMissingClassesByRegularExpressions>\n\t\t\t\t\t\t\t\t<ignoreMissingClassesByRegularExpression>org.neo4j.cypherdsl.parser.internal.*</ignoreMissingClassesByRegularExpression>\n\t\t\t\t\t\t\t</ignoreMissingClassesByRegularExpressions>\n\t\t\t\t\t\t</parameter>\n\t\t\t\t\t</configuration>\n\t\t\t\t\t<executions>\n\t\t\t\t\t\t<!--\n\t\t\t\t\t\tRelease will always set a -Drevision=XXXX and use `deploy` phase, which in turn will depend\n\t\t\t\t\t\ton verify, regardless if tests are skipped or not.\n\t\t\t\t\t\t-->\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>cmp</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t<phase>verify</phase>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t</executions>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>com.mycila</groupId>\n\t\t\t\t\t<artifactId>license-maven-plugin</artifactId>\n\t\t\t\t\t<version>${license-maven-plugin.version}</version>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.jreleaser</groupId>\n\t\t\t\t\t<artifactId>jreleaser-maven-plugin</artifactId>\n\t\t\t\t\t<version>${jreleaser-maven-plugin.version}</version>\n\t\t\t\t</plugin>\n\t\t\t</plugins>\n\t\t</pluginManagement>\n\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.mycila</groupId>\n\t\t\t\t<artifactId>license-maven-plugin</artifactId>\n\t\t\t\t<configuration>\n\n\t\t\t\t\t<strictCheck>true</strictCheck>\n\t\t\t\t\t<mapping>\n\t\t\t\t\t\t<factories>SCRIPT_STYLE</factories>\n\t\t\t\t\t</mapping>\n\t\t\t\t\t<properties>\n\t\t\t\t\t\t<year>2026</year>\n\t\t\t\t\t</properties>\n\t\t\t\t\t<licenseSets>\n\t\t\t\t\t\t<licenseSet>\n\t\t\t\t\t\t\t<header>etc/license.tpl</header>\n\t\t\t\t\t\t\t<includes>\n\t\t\t\t\t\t\t\t<include>**</include>\n\t\t\t\t\t\t\t</includes>\n\t\t\t\t\t\t\t<excludes>\n\t\t\t\t\t\t\t\t<exclude>**/*.adoc</exclude>\n\t\t\t\t\t\t\t\t<exclude>**/*.csv</exclude>\n\t\t\t\t\t\t\t\t<exclude>**/*.cypher</exclude>\n\t\t\t\t\t\t\t\t<exclude>**/*.sh</exclude>\n\t\t\t\t\t\t\t\t<exclude>**/*.tpl</exclude>\n\t\t\t\t\t\t\t\t<exclude>**/*.txt</exclude>\n\t\t\t\t\t\t\t\t<exclude>**/*.yaml</exclude>\n\t\t\t\t\t\t\t\t<exclude>**/.flattened-pom.xml</exclude>\n\t\t\t\t\t\t\t\t<exclude>**/.git-blame-ignore-revs</exclude>\n\t\t\t\t\t\t\t\t<exclude>**/org.mockito.plugins.MockMaker</exclude>\n\t\t\t\t\t\t\t\t<exclude>bin/runtests.java</exclude>\n\t\t\t\t\t\t\t\t<exclude>**/src/test/resources/**/*_.java</exclude>\n\t\t\t\t\t\t\t</excludes>\n\t\t\t\t\t\t</licenseSet>\n\t\t\t\t\t</licenseSets>\n\t\t\t\t\t<dependencyEnforce>true</dependencyEnforce>\n\t\t\t\t\t<dependencyExceptionMessage>One or more dependencies are licensed under a non-approved license.</dependencyExceptionMessage>\n\t\t\t\t\t<dependencyPolicies>\n\t\t\t\t\t\t<!-- Apache 2 -->\n\t\t\t\t\t\t<dependencyPolicy>\n\t\t\t\t\t\t\t<type>LICENSE_URL</type>\n\t\t\t\t\t\t\t<rule>APPROVE</rule>\n\t\t\t\t\t\t\t<value>https://www.apache.org/licenses/LICENSE-2.0</value>\n\t\t\t\t\t\t</dependencyPolicy>\n\t\t\t\t\t\t<dependencyPolicy>\n\t\t\t\t\t\t\t<type>LICENSE_NAME</type>\n\t\t\t\t\t\t\t<rule>APPROVE</rule>\n\t\t\t\t\t\t\t<value>Apache License, Version 2</value>\n\t\t\t\t\t\t</dependencyPolicy>\n\t\t\t\t\t\t<dependencyPolicy>\n\t\t\t\t\t\t\t<type>LICENSE_NAME</type>\n\t\t\t\t\t\t\t<rule>APPROVE</rule>\n\t\t\t\t\t\t\t<value>Apache License, Version 2.0</value>\n\t\t\t\t\t\t</dependencyPolicy>\n\t\t\t\t\t\t<dependencyPolicy>\n\t\t\t\t\t\t\t<type>LICENSE_NAME</type>\n\t\t\t\t\t\t\t<rule>APPROVE</rule>\n\t\t\t\t\t\t\t<value>The Apache Software License, Version 2.0</value>\n\t\t\t\t\t\t</dependencyPolicy>\n\t\t\t\t\t\t<dependencyPolicy>\n\t\t\t\t\t\t\t<type>LICENSE_NAME</type>\n\t\t\t\t\t\t\t<rule>APPROVE</rule>\n\t\t\t\t\t\t\t<value>The Apache License, Version 2.0</value>\n\t\t\t\t\t\t</dependencyPolicy>\n\t\t\t\t\t\t<dependencyPolicy>\n\t\t\t\t\t\t\t<type>LICENSE_NAME</type>\n\t\t\t\t\t\t\t<rule>APPROVE</rule>\n\t\t\t\t\t\t\t<value>Apache 2.0</value>\n\t\t\t\t\t\t</dependencyPolicy>\n\t\t\t\t\t\t<dependencyPolicy>\n\t\t\t\t\t\t\t<type>LICENSE_NAME</type>\n\t\t\t\t\t\t\t<rule>APPROVE</rule>\n\t\t\t\t\t\t\t<value>Apache-2.0</value>\n\t\t\t\t\t\t</dependencyPolicy>\n\t\t\t\t\t\t<!-- MIT -->\n\t\t\t\t\t\t<dependencyPolicy>\n\t\t\t\t\t\t\t<type>LICENSE_NAME</type>\n\t\t\t\t\t\t\t<rule>APPROVE</rule>\n\t\t\t\t\t\t\t<value>MIT License</value>\n\t\t\t\t\t\t</dependencyPolicy>\n\t\t\t\t\t\t<dependencyPolicy>\n\t\t\t\t\t\t\t<type>LICENSE_NAME</type>\n\t\t\t\t\t\t\t<rule>APPROVE</rule>\n\t\t\t\t\t\t\t<value>MIT</value>\n\t\t\t\t\t\t</dependencyPolicy>\n\t\t\t\t\t</dependencyPolicies>\n\t\t\t\t</configuration>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>validate</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>check</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.codehaus.mojo</groupId>\n\t\t\t\t<artifactId>exec-maven-plugin</artifactId>\n\t\t\t\t<version>${exec-maven-plugin.version}</version>\n\t\t\t\t<inherited>false</inherited>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>prepare-release</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>exec</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<executable>bin/prepare-release.sh</executable>\n\t\t\t\t\t\t\t<arguments>\n\t\t\t\t\t\t\t\t<argument>${revision}${sha1}${changelist}</argument>\n\t\t\t\t\t\t\t\t<argument>${cypher-dsl.version.next}</argument>\n\t\t\t\t\t\t\t</arguments>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.github.ekryd.sortpom</groupId>\n\t\t\t\t<artifactId>sortpom-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>sort</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>sort</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>verify</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.jacoco</groupId>\n\t\t\t\t<artifactId>jacoco-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-enforcer-plugin</artifactId>\n\t\t\t\t<version>${maven-enforcer-plugin.version}</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>enforce</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>enforce</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<rules>\n\t\t\t\t\t\t\t\t<requireJavaVersion>\n\t\t\t\t\t\t\t\t\t<version>${java.version}</version>\n\t\t\t\t\t\t\t\t</requireJavaVersion>\n\t\t\t\t\t\t\t\t<requireMavenVersion>\n\t\t\t\t\t\t\t\t\t<version>${maven.version}</version>\n\t\t\t\t\t\t\t\t</requireMavenVersion>\n\t\t\t\t\t\t\t\t<DependencyConvergence/>\n\t\t\t\t\t\t\t</rules>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-failsafe-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>integration-test</goal>\n\t\t\t\t\t\t\t<goal>verify</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-jar-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<archive>\n\t\t\t\t\t\t<manifest>\n\t\t\t\t\t\t\t<addDefaultEntries>true</addDefaultEntries>\n\t\t\t\t\t\t\t<addDefaultImplementationEntries>true</addDefaultImplementationEntries>\n\t\t\t\t\t\t\t<addBuildEnvironmentEntries>true</addBuildEnvironmentEntries>\n\t\t\t\t\t\t</manifest>\n\t\t\t\t\t</archive>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-source-plugin</artifactId>\n\t\t\t\t<version>${maven-source-plugin.version}</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>attach-sources</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>jar-no-fork</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>attach-javadocs</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>jar</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.codehaus.mojo</groupId>\n\t\t\t\t<artifactId>flatten-maven-plugin</artifactId>\n\t\t\t\t<version>${flatten-maven-plugin.version}</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<updatePomFile>true</updatePomFile>\n\t\t\t\t\t<flattenMode>resolveCiFriendliesOnly</flattenMode>\n\t\t\t\t</configuration>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>flatten</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>flatten</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>flatten.clean</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>clean</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>clean</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.asciidoctor</groupId>\n\t\t\t\t<artifactId>asciidoctor-maven-plugin</artifactId>\n\t\t\t\t<version>${asciidoctor-maven-plugin.version}</version>\n\t\t\t\t<inherited>false</inherited>\n\t\t\t\t<configuration>\n\t\t\t\t\t<backend>html</backend>\n\t\t\t\t\t<doctype>book</doctype>\n\t\t\t\t\t<sourceDirectory>${basedir}/docs</sourceDirectory>\n\t\t\t\t\t<sourceDocumentName>index.adoc</sourceDocumentName>\n\t\t\t\t\t<attributes>\n\t\t\t\t\t\t<icons>font</icons>\n\t\t\t\t\t\t<toc>left</toc>\n\t\t\t\t\t\t<setanchors/>\n\t\t\t\t\t\t<idprefix/>\n\t\t\t\t\t\t<idseparator/>\n\t\t\t\t\t\t<imagesdir>img</imagesdir>\n\t\t\t\t\t\t<neo4j-version>${neo4j.version}</neo4j-version>\n\t\t\t\t\t\t<source-highlighter>coderay</source-highlighter>\n\t\t\t\t\t\t<use-latest-version-for-docs>${use-latest-version-for-docs}</use-latest-version-for-docs>\n\t\t\t\t\t</attributes>\n\t\t\t\t\t<requires>\n\t\t\t\t\t\t<require>asciidoctor-diagram</require>\n\t\t\t\t\t</requires>\n\t\t\t\t\t<outputDirectory>${project.build.docs}</outputDirectory>\n\t\t\t\t</configuration>\n\t\t\t\t<dependencies>\n\t\t\t\t\t<dependency>\n\t\t\t\t\t\t<groupId>org.asciidoctor</groupId>\n\t\t\t\t\t\t<artifactId>asciidoctorj-diagram</artifactId>\n\t\t\t\t\t\t<version>${asciidoctorj-diagram.version}</version>\n\t\t\t\t\t</dependency>\n\t\t\t\t</dependencies>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>generate-docs</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>process-asciidoc</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<phase>prepare-package</phase>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\t<reporting>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t<version>${maven-javadoc-plugin.version}</version>\n\t\t\t\t<reportSets>\n\t\t\t\t\t<reportSet>\n\t\t\t\t\t\t<id>default</id>\n\t\t\t\t\t\t<reports>\n\t\t\t\t\t\t\t<report>javadoc</report>\n\t\t\t\t\t\t</reports>\n\t\t\t\t\t</reportSet>\n\t\t\t\t\t<reportSet>\n\t\t\t\t\t\t<id>aggregate</id>\n\t\t\t\t\t\t<reports>\n\t\t\t\t\t\t\t<report>aggregate</report>\n\t\t\t\t\t\t</reports>\n\t\t\t\t\t</reportSet>\n\t\t\t\t</reportSets>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-checkstyle-plugin</artifactId>\n\t\t\t\t<reportSets>\n\t\t\t\t\t<reportSet>\n\t\t\t\t\t\t<reports>\n\t\t\t\t\t\t\t<report>checkstyle</report>\n\t\t\t\t\t\t</reports>\n\t\t\t\t\t</reportSet>\n\t\t\t\t</reportSets>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</reporting>\n\n\t<profiles>\n\t\t<profile>\n\t\t\t<id>with_checkstyle</id>\n\t\t\t<activation>\n\t\t\t\t<jdk>[21,)</jdk>\n\t\t\t</activation>\n\t\t\t<build>\n\t\t\t\t<plugins>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<groupId>io.spring.javaformat</groupId>\n\t\t\t\t\t\t<artifactId>spring-javaformat-maven-plugin</artifactId>\n\t\t\t\t\t\t<executions>\n\t\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t\t<goal>validate</goal>\n\t\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t\t\t<inherited>true</inherited>\n\t\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t</executions>\n\t\t\t\t\t</plugin>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t\t<artifactId>maven-checkstyle-plugin</artifactId>\n\t\t\t\t\t\t<executions>\n\t\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t\t<id>validate</id>\n\t\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t\t<goal>check</goal>\n\t\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t\t<phase>validate</phase>\n\t\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t</executions>\n\t\t\t\t\t</plugin>\n\t\t\t\t</plugins>\n\t\t\t</build>\n\t\t</profile>\n\n\t\t<profile>\n\t\t\t<id>fast</id>\n\t\t\t<activation>\n\t\t\t\t<property>\n\t\t\t\t\t<name>fast</name>\n\t\t\t\t</property>\n\t\t\t</activation>\n\t\t\t<properties>\n\t\t\t\t<asciidoctor.skip>true</asciidoctor.skip>\n\t\t\t\t<checkstyle.skip>true</checkstyle.skip>\n\t\t\t\t<jacoco.skip>true</jacoco.skip>\n\t\t\t\t<maven.javadoc.skip>true</maven.javadoc.skip>\n\t\t\t\t<skipITs>true</skipITs>\n\t\t\t\t<skipNativeBuild>true</skipNativeBuild>\n\t\t\t\t<skipTests>true</skipTests>\n\t\t\t\t<spring-javaformat.skip>true</spring-javaformat.skip>\n\t\t\t</properties>\n\t\t</profile>\n\n\t\t<profile>\n\t\t\t<id>sonar</id>\n\t\t\t<activation>\n\t\t\t\t<activeByDefault>false</activeByDefault>\n\t\t\t</activation>\n\t\t\t<properties>\n\t\t\t\t<sonar.host.url>https://sonarcloud.io</sonar.host.url>\n\t\t\t\t<sonar.moduleKey>${project.groupId}:${project.artifactId}</sonar.moduleKey>\n\t\t\t\t<sonar.organization>michael-simons-github</sonar.organization>\n\t\t\t\t<sonar.projectKey>org.neo4j:neo4j-cypher-dsl-parent</sonar.projectKey>\n\t\t\t</properties>\n\t\t\t<build>\n\t\t\t\t<plugins>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<groupId>org.sonarsource.scanner.maven</groupId>\n\t\t\t\t\t\t<artifactId>sonar-maven-plugin</artifactId>\n\t\t\t\t\t\t<executions>\n\t\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t\t<id>sonar</id>\n\t\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t\t<goal>sonar</goal>\n\t\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t\t<phase>verify</phase>\n\t\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t</executions>\n\t\t\t\t\t</plugin>\n\t\t\t\t</plugins>\n\t\t\t</build>\n\t\t</profile>\n\n\t\t<profile>\n\t\t\t<id>jreleaser</id>\n\t\t\t<activation>\n\t\t\t\t<property>\n\t\t\t\t\t<name>jreleaser</name>\n\t\t\t\t</property>\n\t\t\t</activation>\n\t\t\t<build>\n\t\t\t\t<plugins>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<groupId>org.jreleaser</groupId>\n\t\t\t\t\t\t<artifactId>jreleaser-maven-plugin</artifactId>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<jreleaser>\n\t\t\t\t\t\t\t\t<project>\n\t\t\t\t\t\t\t\t\t<name>neo4j-cypher-dsl</name>\n\t\t\t\t\t\t\t\t</project>\n\t\t\t\t\t\t\t\t<release>\n\t\t\t\t\t\t\t\t\t<github>\n\t\t\t\t\t\t\t\t\t\t<owner>neo4j</owner>\n\t\t\t\t\t\t\t\t\t\t<tagName>{{projectVersion}}</tagName>\n\t\t\t\t\t\t\t\t\t\t<releaseName>{{projectVersion}}</releaseName>\n\t\t\t\t\t\t\t\t\t</github>\n\t\t\t\t\t\t\t\t</release>\n\t\t\t\t\t\t\t\t<announce>\n\t\t\t\t\t\t\t\t\t<webhooks>\n\t\t\t\t\t\t\t\t\t\t<slack>\n\t\t\t\t\t\t\t\t\t\t\t<active>ALWAYS</active>\n\t\t\t\t\t\t\t\t\t\t\t<structuredMessage>true</structuredMessage>\n\t\t\t\t\t\t\t\t\t\t</slack>\n\t\t\t\t\t\t\t\t\t</webhooks>\n\t\t\t\t\t\t\t\t</announce>\n\t\t\t\t\t\t\t</jreleaser>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</plugin>\n\t\t\t\t</plugins>\n\t\t\t</build>\n\t\t</profile>\n\t</profiles>\n</project>\n"
  }
]