[
  {
    "path": ".github/workflows/ci.yml",
    "content": "---\nname: Java CI\n\non:\n  push:\n  pull_request:\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        java: [ 17, 21 ]\n      fail-fast: false\n      max-parallel: 4\n    name: JDK ${{ matrix.java }}\n\n    steps:\n      - uses: actions/checkout@v4\n      - name: Set up JDK\n        uses: actions/setup-java@v3\n        with:\n          java-version: ${{ matrix.java }}\n          distribution: temurin\n          cache: 'gradle'\n\n      - name: Grant execute permission for gradlew\n        run: chmod +x gradlew\n\n      - name: Build with Gradle\n        run: ./gradlew build --warning-mode all\n\n      - name: Run Tests\n        run: ./gradlew check\n\n      - name: Maven Install\n        run: ./gradlew clean publishToMavenLocal\n\n...\n"
  },
  {
    "path": ".gitignore",
    "content": ".idea/\ntarget\n*.iws\n*.ipr\n*.iml\n.classpath\n.project\n.settings\n.springBeans\n.DS_Store\n.gradle\n.java-version\nTODO\ngradle.properties\nbuild\nbin/\nout/\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: java\n\nsudo: false\n\njdk:\n - openjdk17\n\ncache:\n  directories:\n  - $HOME/.gradle\n\narch:\n  - amd64\n  - ppc64le\n"
  },
  {
    "path": "LICENSE",
    "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 2017 Jayway\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS 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": "Procfile",
    "content": "web: java $JAVA_OPTS -Dserver.http.port=$PORT -DresourceBase=json-path-web-test/build/resources/main/webapp/  -jar json-path-web-test/build/libs/json-path-web-test-*-all.jar"
  },
  {
    "path": "README.md",
    "content": "Jayway JsonPath\n=====================\n\n**A Java DSL for reading JSON documents.**\n\n[![Build Status](https://travis-ci.org/json-path/JsonPath.svg?branch=master)](https://travis-ci.org/json-path/JsonPath)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.jayway.jsonpath/json-path/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.jayway.jsonpath/json-path)\n[![Javadoc](https://www.javadoc.io/badge/com.jayway.jsonpath/json-path.svg)](http://www.javadoc.io/doc/com.jayway.jsonpath/json-path)\n\nJayway JsonPath is a Java port of [Stefan Goessner JsonPath implementation](http://goessner.net/articles/JsonPath/).\n\nGetting Started\n---------------\n\nJsonPath is available at the Central Maven Repository. Maven users add this to your POM.\n\n> [!NOTE]  \n> Version 3.0.0 Uses Java 17 baseline to support Jackson 3\n\n```xml\n\n<dependency>\n    <groupId>com.jayway.jsonpath</groupId>\n    <artifactId>json-path</artifactId>\n    <version>3.0.0</version>\n</dependency>\n```\n\nIf you need help ask questions at [Stack Overflow](http://stackoverflow.com/questions/tagged/jsonpath). Tag the\nquestion 'jsonpath' and 'java'.\n\nJsonPath expressions always refer to a JSON structure in the same way as XPath expression are used in combination\nwith an XML document. The \"root member object\" in JsonPath is always referred to as `$` regardless if it is an\nobject or array.\n\nJsonPath expressions can use the dot–notation\n\n`$.store.book[0].title`\n\nor the bracket–notation\n\n`$['store']['book'][0]['title']`\n\nOperators\n---------\n\n| Operator                  | Description                                                     |\n|:--------------------------|:----------------------------------------------------------------|\n| `$`                       | The root element to query. This starts all path expressions.    |\n| `@`                       | The current node being processed by a filter predicate.         |\n| `*`                       | Wildcard. Available anywhere a name or numeric are required.    |\n| `..`                      | Deep scan. Available anywhere a name is required.               |\n| `.<name>`                 | Dot-notated child                                               |\n| `['<name>' (, '<name>')]` | Bracket-notated child or children                               |\n| `[<number> (, <number>)]` | Array index or indexes                                          |\n| `[start:end]`             | Array slice operator                                            |\n| `[?(<expression>)]`       | Filter expression. Expression must evaluate to a boolean value. |\n\nFunctions\n---------\n\nFunctions can be invoked at the tail end of a path - the input to a function is the output of the path expression.\nThe function output is dictated by the function itself.\n\n| Function    | Description                                                                          | Output type          |\n|:------------|:-------------------------------------------------------------------------------------|:---------------------|\n| `min()`     | Provides the min value of an array of numbers                                        | Double               |\n| `max()`     | Provides the max value of an array of numbers                                        | Double               |\n| `avg()`     | Provides the average value of an array of numbers                                    | Double               | \n| `stddev()`  | Provides the standard deviation value of an array of numbers                         | Double               | \n| `length()`  | Provides the length of an array                                                      | Integer              |\n| `sum()`     | Provides the sum value of an array of numbers                                        | Double               |\n| `keys()`    | Provides the property keys (An alternative for terminal tilde `~`)                   | `Set<E>`             |\n| `concat(X)` | Provides a concatinated version of the path output with a new item                   | like input           |\n| `append(X)` | add an item to the json path output array                                            | like input           |\n| `first()`   | Provides the first item of an array                                                  | Depends on the array |\n| `last()`    | Provides the last item of an array                                                   | Depends on the array |\n| `index(X)`  | Provides the item of an array of index: X, if the X is negative, take from backwards | Depends on the array |\n\nFilter Operators\n-----------------\n\nFilters are logical expressions used to filter arrays. A typical filter would be `[?(@.age > 18)]` where `@` represents\nthe current item being processed. More complex filters can be created with logical operators `&&` and `||`. String\nliterals must be enclosed by single or double quotes (`[?(@.color == 'blue')]` or `[?(@.color == \"blue\")]`).\n\n| Operator   | Description                                                        |\n|:-----------|:-------------------------------------------------------------------|\n| `==`       | left is equal to right (note that 1 is not equal to '1')           |\n| `!=`       | left is not equal to right                                         |\n| `<`        | left is less than right                                            |\n| `<=`       | left is less or equal to right                                     |\n| `>`        | left is greater than right                                         |\n| `>=`       | left is greater than or equal to right                             |\n| `=~`       | left matches regular expression  [?(@.name =~ /foo.*?/i)]          |\n| `in`       | left exists in right [?(@.size in ['S', 'M'])]                     |\n| `nin`      | left does not exists in right                                      |\n| `subsetof` | left is a subset of right [?(@.sizes subsetof ['S', 'M', 'L'])]    |\n| `anyof`    | left has an intersection with right [?(@.sizes anyof ['M', 'L'])]  |\n| `noneof`   | left has no intersection with right [?(@.sizes noneof ['M', 'L'])] |\n| `size`     | size of left (array or string) should match right                  |\n| `empty`    | left (array or string) should be empty                             |\n\nPath Examples\n-------------\n\nGiven the json\n\n```javascript\n{\n    \"store\": {\n        \"book\": [\n            {\n                \"category\": \"reference\",\n                \"author\": \"Nigel Rees\",\n                \"title\": \"Sayings of the Century\",\n                \"price\": 8.95\n            },\n            {\n                \"category\": \"fiction\",\n                \"author\": \"Evelyn Waugh\",\n                \"title\": \"Sword of Honour\",\n                \"price\": 12.99\n            },\n            {\n                \"category\": \"fiction\",\n                \"author\": \"Herman Melville\",\n                \"title\": \"Moby Dick\",\n                \"isbn\": \"0-553-21311-3\",\n                \"price\": 8.99\n            },\n            {\n                \"category\": \"fiction\",\n                \"author\": \"J. R. R. Tolkien\",\n                \"title\": \"The Lord of the Rings\",\n                \"isbn\": \"0-395-19395-8\",\n                \"price\": 22.99\n            }\n        ],\n        \"bicycle\": {\n            \"color\": \"red\",\n            \"price\": 19.95\n        }\n    },\n    \"expensive\": 10\n}\n```\n\n| JsonPath                                | Result                                                       |\n|:----------------------------------------|:-------------------------------------------------------------|\n| `$.store.book[*].author`                | The authors of all books                                     |\n| `$..author`                             | All authors                                                  |\n| `$.store.*`                             | All things, both books and bicycles                          |\n| `$.store..price`                        | The price of everything                                      |\n| `$..book[2]`                            | The third book                                               |\n| `$..book[-2]`                           | The second to last book                                      |\n| `$..book[0,1]`                          | The first two books                                          |\n| `$..book[:2]`                           | All books from index 0 (inclusive) until index 2 (exclusive) |\n| `$..book[1:2]`                          | All books from index 1 (inclusive) until index 2 (exclusive) |\n| `$..book[-2:]`                          | Last two books                                               |\n| `$..book[2:]`                           | All books from index 2 (inclusive) to last                   |\n| `$..book[?(@.isbn)]`                    | All books with an ISBN number                                |\n| `$.store.book[?(@.price < 10)]`         | All books in store cheaper than 10                           |\n| `$..book[?(@.price <= $['expensive'])]` | All books in store that are not \"expensive\"                  |\n| `$..book[?(@.author =~ /.*REES/i)]`     | All books matching regex (ignore case)                       |\n| `$..*`                                  | Give me every thing                                          \n| `$..book.length()`                      | The number of books                                          |\n\nReading a Document\n------------------\nThe simplest most straight forward way to use JsonPath is via the static read API.\n\n```java\nString json = \"...\";\n\nList<String> authors = JsonPath.read(json, \"$.store.book[*].author\");\n```\n\nIf you only want to read once this is OK. In case you need to read an other path as well this is not the way\nto go since the document will be parsed every time you call JsonPath.read(...). To avoid the problem you can\nparse the json first.\n\n```java\nString json = \"...\";\nObject document = Configuration.defaultConfiguration().jsonProvider().parse(json);\n\nString author0 = JsonPath.read(document, \"$.store.book[0].author\");\nString author1 = JsonPath.read(document, \"$.store.book[1].author\");\n```\n\nJsonPath also provides a fluent API. This is also the most flexible one.\n\n```java\nString json = \"...\";\n\nReadContext ctx = JsonPath.parse(json);\n\nList<String> authorsOfBooksWithISBN = ctx.read(\"$.store.book[?(@.isbn)].author\");\n\n\nList<Map<String, Object>> expensiveBooks = JsonPath\n        .using(configuration)\n        .parse(json)\n        .read(\"$.store.book[?(@.price > 10)]\", List.class);\n```\n\nWhat is Returned When?\n----------------------\nWhen using JsonPath in java its important to know what type you expect in your result. JsonPath will automatically\ntry to cast the result to the type expected by the invoker.\n\n```java\n//Will throw an java.lang.ClassCastException    \nList<String> list = JsonPath.parse(json).read(\"$.store.book[0].author\");\n\n//Works fine\nString author = JsonPath.parse(json).read(\"$.store.book[0].author\");\n```\n\nWhen evaluating a path you need to understand the concept of when a path is `definite`. A path is `indefinite` if it\ncontains:\n\n* `..` - a deep scan operator\n* `?(<expression>)` - an expression\n* `[<number>, <number> (, <number>)]` - multiple array indexes\n\n`Indefinite` paths always returns a list (as represented by current JsonProvider).\n\nBy default a simple object mapper is provided by the MappingProvider SPI. This allows you to specify the return type you\nwant and the MappingProvider will\ntry to perform the mapping. In the example below mapping between `Long` and `Date` is demonstrated.\n\n```java\nString json = \"{\\\"date_as_long\\\" : 1411455611975}\";\n\nDate date = JsonPath.parse(json).read(\"$['date_as_long']\", Date.class);\n```\n\nIf you configure JsonPath to use `JacksonMappingProvider`, `Jackson3MappingProvider`, `GsonMappingProvider`,\nor `JakartaJsonProvider` you can even\nmap your JsonPath output directly into POJO's.\n\n```java\nBook book = JsonPath.parse(json).read(\"$.store.book[0]\", Book.class);\n```\n\nTo obtain full generics type information, use TypeRef.\n\n```java\nTypeRef<List<String>> typeRef = new TypeRef<List<String>>() {\n};\n\nList<String> titles = JsonPath.parse(JSON_DOCUMENT).read(\"$.store.book[*].title\", typeRef);\n```\n\nPredicates\n----------\nThere are three different ways to create filter predicates in JsonPath.\n\n### Inline Predicates\n\nInline predicates are the ones defined in the path.\n\n```java\nList<Map<String, Object>> books = JsonPath.parse(json)\n        .read(\"$.store.book[?(@.price < 10)]\");\n```\n\nYou can use `&&` and `||` to combine multiple predicates `[?(@.price < 10 && @.category == 'fiction')]` ,\n`[?(@.category == 'reference' || @.price > 10)]`.\n\nYou can use `!` to negate a predicate `[?(!(@.price < 10 && @.category == 'fiction'))]`.\n\n### Filter Predicates\n\nPredicates can be built using the Filter API as shown below:\n\n```java\nimport static com.jayway.jsonpath.JsonPath.parse;\nimport static com.jayway.jsonpath.Criteria.where;\nimport static com.jayway.jsonpath.Filter.filter;\n...\n        ...\n\nFilter cheapFictionFilter = filter(\n        where(\"category\").is(\"fiction\").and(\"price\").lte(10D)\n);\n\nList<Map<String, Object>> books =\n        parse(json).read(\"$.store.book[?]\", cheapFictionFilter);\n\n```\n\nNotice the placeholder `?` for the filter in the path. When multiple filters are provided they are applied in order\nwhere the number of placeholders must match\nthe number of provided filters. You can specify multiple predicate placeholders in one filter operation `[?, ?]`, both\npredicates must match.\n\nFilters can also be combined with 'OR' and 'AND'\n\n```java\nFilter fooOrBar = filter(\n        where(\"foo\").exists(true)).or(where(\"bar\").exists(true)\n);\n\nFilter fooAndBar = filter(\n        where(\"foo\").exists(true)).and(where(\"bar\").exists(true)\n);\n```\n\n### Roll Your Own\n\nThird option is to implement your own predicates\n\n```java \nPredicate booksWithISBN = new Predicate() {\n    @Override\n    public boolean apply(PredicateContext ctx) {\n        return ctx.item(Map.class).containsKey(\"isbn\");\n    }\n};\n\nList<Map<String, Object>> books =\n        reader.read(\"$.store.book[?].isbn\", List.class, booksWithISBN);\n```\n\nPath vs Value\n-------------\nIn the Goessner implementation a JsonPath can return either `Path` or `Value`. `Value` is the default and what all the\nexamples above are returning. If you rather have the path of the elements our query is hitting this can be achieved with\nan option.\n\n```java\nConfiguration conf = Configuration.builder()\n        .options(Option.AS_PATH_LIST).build();\n\nList<String> pathList = using(conf).parse(json).read(\"$..author\");\n\nassertThat(pathList).\n\ncontainsExactly(\n    \"$['store']['book'][0]['author']\",\n            \"$['store']['book'][1]['author']\",\n            \"$['store']['book'][2]['author']\",\n            \"$['store']['book'][3]['author']\");\n```\n\nSet a value\n-----------\nThe library offers the possibility to set a value.\n\n```java\nString newJson = JsonPath.parse(json).set(\"$['store']['book'][0]['author']\", \"Paul\").jsonString();\n```\n\nTweaking Configuration\n----------------------\n\n### Options\n\nWhen creating your Configuration there are a few option flags that can alter the default behaviour.\n\n**DEFAULT_PATH_LEAF_TO_NULL**\n<br/>\nThis option makes JsonPath return null for missing leafs. Consider the following json\n\n```javascript\n[\n   {\n      \"name\" : \"john\",\n      \"gender\" : \"male\"\n   },\n   {\n      \"name\" : \"ben\"\n   }\n]\n```\n\n```java\nConfiguration conf = Configuration.defaultConfiguration();\n\n//Works fine\nString gender0 = JsonPath.using(conf).parse(json).read(\"$[0]['gender']\");\n//PathNotFoundException thrown\nString gender1 = JsonPath.using(conf).parse(json).read(\"$[1]['gender']\");\n\nConfiguration conf2 = conf.addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL);\n\n//Works fine\nString gender0 = JsonPath.using(conf2).parse(json).read(\"$[0]['gender']\");\n//Works fine (null is returned)\nString gender1 = JsonPath.using(conf2).parse(json).read(\"$[1]['gender']\");\n```\n\n**ALWAYS_RETURN_LIST**\n<br/>\nThis option configures JsonPath to return a list even when the path is `definite`.\n\n```java\nConfiguration conf = Configuration.defaultConfiguration();\n\n//ClassCastException thrown\nList<String> genders0 = JsonPath.using(conf).parse(json).read(\"$[0]['gender']\");\n\nConfiguration conf2 = conf.addOptions(Option.ALWAYS_RETURN_LIST);\n\n//Works fine\nList<String> genders0 = JsonPath.using(conf2).parse(json).read(\"$[0]['gender']\");\n``` \n\n**SUPPRESS_EXCEPTIONS**\n<br/>\nThis option makes sure no exceptions are propagated from path evaluation. It follows these simple rules:\n\n* If option `ALWAYS_RETURN_LIST` is present an empty list will be returned\n* If option `ALWAYS_RETURN_LIST` is **NOT** present null returned\n\n**REQUIRE_PROPERTIES**\n</br>\nThis option configures JsonPath to require properties defined in path when an `indefinite` path is evaluated.\n\n```java\nConfiguration conf = Configuration.defaultConfiguration();\n\n//Works fine\nList<String> genders = JsonPath.using(conf).parse(json).read(\"$[*]['gender']\");\n\nConfiguration conf2 = conf.addOptions(Option.REQUIRE_PROPERTIES);\n\n//PathNotFoundException thrown\nList<String> genders = JsonPath.using(conf2).parse(json).read(\"$[*]['gender']\");\n```\n\n### JsonProvider SPI\n\nJsonPath is shipped with five different JsonProviders:\n\n* [JsonSmartJsonProvider](https://github.com/netplex/json-smart-v2) (default)\n* [JacksonJsonProvider](https://github.com/FasterXML/jackson)\n* [JacksonJsonNodeJsonProvider](https://github.com/FasterXML/jackson)\n* [JacksonJson3Provider](https://github.com/FasterXML/jackson)\n* [JacksonJson3NodeJsonProvider](https://github.com/FasterXML/jackson)\n* [GsonJsonProvider](https://code.google.com/p/google-gson/)\n* [JsonOrgJsonProvider](https://github.com/stleary/JSON-java)\n* [JakartaJsonProvider](https://javaee.github.io/jsonp/)\n\nChanging the configuration defaults as demonstrated should only be done when your application is being initialized.\nChanges during runtime is strongly discouraged, especially in multi threaded applications.\n\n```java\nConfiguration.setDefaults(new Configuration.Defaults() {\n\n    private final JsonProvider jsonProvider = new JacksonJsonProvider();\n    private final MappingProvider mappingProvider = new JacksonMappingProvider();\n\n    @Override\n    public JsonProvider jsonProvider () {\n        return jsonProvider;\n    }\n\n    @Override\n    public MappingProvider mappingProvider () {\n        return mappingProvider;\n    }\n\n    @Override\n    public Set<Option> options () {\n        return EnumSet.noneOf(Option.class);\n    }\n});\n```\n\nNote that the JacksonJsonProvider requires `com.fasterxml.jackson.core:jackson-databind:2.20.1`, the\nJackson3JsonProvider requires `tools.jackson.core:jackson-databind:3.0.3` and the GsonJsonProvider\nrequires `com.google.code.gson:gson:2.3.1` on your classpath.\n\nBoth of Jakarta EE 9 [JSON-P (JSR-342)](https://javaee.github.io/jsonp/) and [JSON-B (JSR-367)](http://json-b.net/)\nproviders expect at least Java 8 and require compatible JSON API implementations (such\nas [Eclipse Glassfish](https://projects.eclipse.org/projects/ee4j.jsonp)\nand [Eclipse Yasson](https://projects.eclipse.org/projects/ee4j.yasson)) on application runtime classpath; such\nimplementations may also be provided by Java EE application container. Please also note that Apache Johnzon is not\nclasspath-compatible with Jakarta EE 9 specification yet, and if JSON-B mapping provider is chosen then JSON-P provider\nmust be configured and used, too.\n\nOne peculiarity of Jakarta EE 9 specifications for JSON processing and databinding (mapping) is immutability of Json\narrays and objects as soon as they are fully parsed or written to. To respect the API specification, but allow JsonPath\nto modify Json documents through add, set/put, replace, and delete operations, `JakartaJsonProvider` has to be\ninitiliazed with optional `true` argument:\n\n* `JsonProvider jsonProvider = new JakartaJsonProvider(true)` (enable mutable Json arrays and objects)\n* `JsonProvider jsonProvider = new JakartaJsonProvider()` (default, strict JSON-P API compliance)\n\nAll lookup and read operations with JsonPath are supported regardless of initilization mode. Default mode also needs\nless memory and is more performant.\n\n### Cache SPI\n\nIn JsonPath 2.1.0 a new Cache SPI was introduced. This allows API consumers to configure path caching in a way that\nsuits their needs. The cache must be configured before it is accesses for the first time or a JsonPathException is\nthrown. JsonPath ships with two cache implementations\n\n* `com.jayway.jsonpath.spi.cache.LRUCache` (default, thread safe)\n* `com.jayway.jsonpath.spi.cache.NOOPCache` (no cache)\n\nIf you want to implement your own cache the API is simple.\n\n```java\nCacheProvider.setCache(new Cache() {\n    //Not thread safe simple cache\n    private Map<String, JsonPath> map = new HashMap<String, JsonPath>();\n\n    @Override\n    public JsonPath get (String key){\n        return map.get(key);\n    }\n\n    @Override\n    public void put (String key, JsonPath jsonPath){\n        map.put(key, jsonPath);\n    }\n});\n```\n\n[![Analytics](https://ga-beacon.appspot.com/UA-54945131-1/jsonpath/index)](https://github.com/igrigorik/ga-beacon)\n"
  },
  {
    "path": "build.gradle",
    "content": "buildscript {\n    repositories {\n        mavenCentral()\n        maven {\n            url \"https://plugins.gradle.org/m2/\"\n        }\n    }\n    dependencies {\n        classpath 'biz.aQute.bnd:biz.aQute.bnd.gradle:6.1.0'\n    }\n}\n\next {\n    libs = [\n            jsonSmart       : 'net.minidev:json-smart:2.6.0',\n            slf4jApi        : 'org.slf4j:slf4j-api:2.0.17',\n            gson            : 'com.google.code.gson:gson:2.13.2',\n            hamcrest        : 'org.hamcrest:hamcrest:3.0',\n            jacksonDatabind : 'com.fasterxml.jackson.core:jackson-databind:2.20.1',\n            jacksonDatabind3: 'tools.jackson.core:jackson-databind:3.0.4',\n            jettison        : 'org.codehaus.jettison:jettison:1.5.4',\n            jsonOrg         : 'org.json:json:20250517',\n            tapestryJson    : 'org.apache.tapestry:tapestry-json:5.9.0',\n            jakartaJsonP    : 'jakarta.json:jakarta.json-api:2.1.3',\n            jakartaJsonB    : 'jakarta.json.bind:jakarta.json.bind-api:2.0.0',\n\n            test            : [\n                    'commons-io:commons-io:2.20.0',\n                    'org.junit.jupiter:junit-jupiter:5.10.1',\n                    'org.assertj:assertj-core:3.25.1',\n                    'org.hamcrest:hamcrest:3.0',\n                    'org.glassfish:jakarta.json:2.0.1',\n                    'org.eclipse:yasson:2.0.4',\n                    'org.slf4j:slf4j-simple:2.0.17',\n                    'com.google.code.gson:gson:2.13.2',\n                    'org.hamcrest:hamcrest:3.0',\n                    'com.fasterxml.jackson.core:jackson-databind:2.20.1',\n                    'tools.jackson.core:jackson-databind:3.0.3',\n                    'org.codehaus.jettison:jettison:1.5.4',\n                    'org.json:json:20250517',\n                    'org.apache.tapestry:tapestry-json:5.9.0',\n                    'jakarta.json:jakarta.json-api:2.1.3',\n                    'jakarta.json.bind:jakarta.json.bind-api:2.0.0'\n\n            ]\n    ]\n    snapshotVersion = false\n}\n\nallprojects {\n    ext.displayName = null\n    ext.buildTimestamp = new Date().format('yyyy-MM-dd HH:mm:ss')\n\n    group = 'com.jayway.jsonpath'\n    version = '3.0.0' + (snapshotVersion ? \"-SNAPSHOT\" : \"\")\n}\n\nsubprojects {\n    apply plugin: 'java'\n    apply plugin: 'java-library'\n    apply plugin: 'maven-publish'\n    apply plugin: 'signing'\n    apply plugin: 'biz.aQute.bnd.builder'\n\n    java {\n        sourceCompatibility = JavaVersion.VERSION_17\n        targetCompatibility = JavaVersion.VERSION_17\n    }\n\n    repositories {\n        mavenCentral()\n    }\n\n    java {\n        withJavadocJar()\n        withSourcesJar()\n    }\n\n    test {\n        useJUnitPlatform()\n        testLogging {\n            events \"passed\", \"skipped\", \"failed\"\n        }\n    }\n\n    signing {\n        sign publishing.publications\n        required { !snapshotVersion && gradle.taskGraph.hasTask(\"publish\") }\n    }\n\n    javadoc {\n        if (JavaVersion.current().isJava8Compatible()) {\n            options.addStringOption('Xdoclint:none', '-quiet')\n        }\n\n        if (JavaVersion.current().isJava9Compatible()) {\n            options.addBooleanOption('html5', true)\n        }\n    }\n\n    publishing {\n        repositories {\n            maven {\n                name = 'ossrh-staging-api'\n                url = 'https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/'\n                credentials {\n                    username = project.hasProperty('sonatypeOssUsername') ? sonatypeOssUsername : \"Unknown user\"\n                    password = project.hasProperty('sonatypeOssPassword') ? sonatypeOssPassword : \"Unknown password\"\n                }\n            }\n        }\n        publications {\n            mavenJava(MavenPublication) {\n                from components.java\n\n                artifactId = project.name\n                //artifactId = jar.archiveBaseName\n\n                pom {\n                    name = project.name\n                    description = 'A library to query and verify JSON'\n                    url = 'https://github.com/jayway/JsonPath'\n\n                    licenses {\n                        license {\n                            name = \"The Apache Software License, Version 2.0\"\n                            url = \"https://www.apache.org/licenses/LICENSE-2.0.txt\"\n                            distribution = \"repo\"\n                        }\n                    }\n\n                    scm {\n                        url = 'scm:git:git://github.com/jayway/JsonPath.git'\n                        connection = 'scm:git:git://github.com/jayway/JsonPath.git'\n                        developerConnection = 'scm:git:git://github.com/jayway/JsonPath.git'\n                    }\n\n                    developers {\n                        developer {\n                            id = 'kalle.stenflo'\n                            name = 'Kalle Stenflo'\n                            email = 'kalle.stenflo (a) gmail.com'\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\nwrapper {\n    gradleVersion = '8.5'\n}\n\n"
  },
  {
    "path": "changelog.md",
    "content": "2.2.0 (2016-02-29)\n===========\n* Upgraded dependency versions\n* Hamcrest-matcher support in json-path-assert\n* Bug fixes and improvements\n\n2.1.0 (2015-11-22)\n===========\n* Upgraded dependency versions\n* Introduced Cache SPI\n* Introduced path functions\n* Introduced JsonOrgJsonProvider\n* OSGI improvements\n* Inline filters supports same operators as Filter builders\n* Improved filter evaluation\n* Internal makeovers\n* New write operations : map(...) and renameKey(...)\n\n2.0.0 (2015-03-19)\n=================\n* Upgraded dependency versions\n* Moved JsonProvider and MappingProvider implementations out of the interal package **OSGi**\n* Removed HTTP provider and methods\n* Add an unwrap(Object) method to JsonProvider, use it when extracting values for Criteria evaluation **breaks JsonProvider SPI**\n* Fixed issue #71 - esacpe character in inline predicates \n  `JsonPath.read(json, \"$.logs[?(@.message == 'it\\\\'s here')].message\");`\n* New method `jsonString()` added to `ReadContext` and `WriteContext` to extract json model as a string  \n* Path does not have to be definite in filter API `filter(where(\"authors[*].lastName\").contains(\"Waugh\"))`\n\n1.2.0 (2014-11-11)\n==================\n* Added EvaluationListener interface that allows abortion of evaluation if criteria is fulfilled.\n  this makes it possible to limit the number of results to fetch when a document is scanned. Also \n  added utility method to limit results `JsonPath.parse(json).limit(1).read(\"$..title\", List.class);`\n* Added support for OR in inline filters `[?(@.foo == 'bar' || @.foo == 'baz')]` \n* Upgrade json-smart to 2.1.0\n* Support for Update and Delete by path. **breaks JsonProvider SPI**\n  `parse(JSON_DOCUMENT).set(\"$.store.book[*].display-price\", 1)`\n  `parse(JSON_DOCUMENT).put(\"$.store.book[1]\", \"new-key\", \"new-val\")`\n  `parse(JSON_DOCUMENT).add(\"$.store.book\", newBook)`\n  `parse(JSON_DOCUMENT).delete(\"$.store.book[1].display-price\")`\n* Support regex in inline filters (ruby syntax)\n  `parse(JSON_DOCUMENT).read(\"$.store.book[?(@.category =~ /reference/)].author\")`\n  `parse(JSON_DOCUMENT).read(\"$.store.book[?(@.category =~ /REFERENCE/i)].author\")`\n* Inline filter does not require path statement on left side of operator  \n  `parse(JSON_DOCUMENT).read(\"$.store.book[?(@.category == 'reference')].author\")`    \n  `parse(JSON_DOCUMENT).read(\"$.store.book[?('reference' == @.category)].author\")`    \n* Negate exist checks in inline filters (not defined or null) \n  `parse(JSON_DOCUMENT).read(\"$.store.book[?(!@.isbn)]\")`    \n* Improved object mapping with Jackson and Gson (now handles generic types)\n* JacksonJsonNodeJsonProvider supporting path operations on `com.fasterxml.jackson.databind.JsonNode`\n* Exceptions thrown by JsonPath.compile are now wrapped in an InvalidPathException\n* Fixed Deep scanning issue (#60) \n\n1.1.0 (2014-10-01)\n==================\n* Reintroduced method JsonProvider.createMap(). This should never have been removed. **NOTE: This is a breaking change if you implemented your own JsonProvider based on the 1.0.0 API**  \n* Filters threw exception if an item being filtered did not contain the path being filtered upon.\n* Multi-property selects works as it did in 0.9. e.g. `$[*]['category', 'price']` \n* Cache results when predicates refer to path in document e.g. `$[*][?(@.price <= $.max-price)]` will only evaluate `$.max-price` once.   \n\n1.0.0 (2014-09-26)\n==================\n* Complete rewrite of internals. Major API changes.\n* Better compliance with the Goessner implementation\n\nRelease history\n===============\n* 0.9.0 (2013-09-26)\n* 0.8.1 (2012-04-16)\n* 0.8.0 (2012-03-08)\n* 0.5.6 (2012-02-09)\n* 0.5.5 (2011-07-15)\n* 0.5.4 (2011-06-26)\n* 0.5.3 (2011-02-18)\n* 0.5.2 (2011-02-08)\n\n\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.5-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "json-path/build.gradle",
    "content": "description = \"Java port of Stefan Goessner JsonPath.\"\n\njar {\n    bnd(\n            'Automatic-Module-Name': 'json.path',\n            'Implementation-Title': 'json-path', 'Implementation-Version': archiveVersion,\n            'Import-Package': 'org.json.*;resolution:=optional, com.google.gson.*;resolution:=optional, com.fasterxml.jackson.*;resolution:=optional, org.apache.tapestry5.json.*;resolution:=optional, org.codehaus.jettison.*;resolution:=optional, jakarta.json.*;resolution:=optional, *',\n            'Export-Package': 'com.jayway.jsonpath,com.jayway.jsonpath.spi,com.jayway.jsonpath.spi.cache,com.jayway.jsonpath.spi.json,com.jayway.jsonpath.spi.mapper'\n    )\n}\n\ndependencies {\n    implementation libs.jsonSmart\n    implementation libs.slf4jApi\n    compileOnly libs.jacksonDatabind // , optional\n    compileOnly libs.jacksonDatabind3 // , optional\n    compileOnly libs.gson// , optional\n    compileOnly libs.jsonOrg// , optional\n    compileOnly libs.tapestryJson// , optional\n    compileOnly libs.jettison// , optional\n    compileOnly libs.jakartaJsonP// , optional\n    compileOnly libs.jakartaJsonB// , optional\n\n    testImplementation libs.test\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/Configuration.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\nimport com.jayway.jsonpath.internal.DefaultsImpl;\nimport com.jayway.jsonpath.spi.json.JsonProvider;\nimport com.jayway.jsonpath.spi.mapper.MappingProvider;\n\nimport java.util.*;\n\nimport static com.jayway.jsonpath.internal.Utils.notNull;\nimport static java.util.Arrays.asList;\n\n/**\n * Immutable configuration object\n */\npublic class Configuration {\n\n    private static Defaults DEFAULTS = null;\n\n    /**\n     * Set Default configuration\n     * @param defaults default configuration settings\n     */\n    public static synchronized void setDefaults(Defaults defaults){\n        DEFAULTS = defaults;\n    }\n\n    private static Defaults getEffectiveDefaults(){\n        if (DEFAULTS == null) {\n          return DefaultsImpl.INSTANCE;\n        } else {\n          return DEFAULTS;\n        }\n    }\n\n    private final JsonProvider jsonProvider;\n    private final MappingProvider mappingProvider;\n    private final Set<Option> options;\n    private final Collection<EvaluationListener> evaluationListeners;\n\n    private Configuration(JsonProvider jsonProvider, MappingProvider mappingProvider, EnumSet<Option> options, Collection<EvaluationListener> evaluationListeners) {\n        notNull(jsonProvider, \"jsonProvider can not be null\");\n        notNull(mappingProvider, \"mappingProvider can not be null\");\n        notNull(options, \"setOptions can not be null\");\n        notNull(evaluationListeners, \"evaluationListeners can not be null\");\n        this.jsonProvider = jsonProvider;\n        this.mappingProvider = mappingProvider;\n        this.options = Collections.unmodifiableSet(options);\n        this.evaluationListeners = Collections.unmodifiableCollection(evaluationListeners);\n    }\n\n    /**\n     * Creates a new Configuration by the provided evaluation listeners to the current listeners\n     * @param evaluationListener listeners\n     * @return a new configuration\n     */\n    public Configuration addEvaluationListeners(EvaluationListener... evaluationListener){\n        return Configuration.builder().jsonProvider(jsonProvider).mappingProvider(mappingProvider).options(options).evaluationListener(evaluationListener).build();\n    }\n\n    /**\n     * Creates a new Configuration with the provided evaluation listeners\n     * @param evaluationListener listeners\n     * @return a new configuration\n     */\n    public Configuration setEvaluationListeners(EvaluationListener... evaluationListener){\n        return Configuration.builder().jsonProvider(jsonProvider).mappingProvider(mappingProvider).options(options).evaluationListener(evaluationListener).build();\n    }\n\n    /**\n     * Returns the evaluation listeners registered in this configuration\n     * @return the evaluation listeners\n     */\n    public Collection<EvaluationListener> getEvaluationListeners(){\n        return evaluationListeners;\n    }\n\n    /**\n     * Creates a new Configuration based on the given {@link com.jayway.jsonpath.spi.json.JsonProvider}\n     * @param newJsonProvider json provider to use in new configuration\n     * @return a new configuration\n     */\n    public Configuration jsonProvider(JsonProvider newJsonProvider) {\n        return Configuration.builder().jsonProvider(newJsonProvider).mappingProvider(mappingProvider).options(options).evaluationListener(evaluationListeners).build();\n    }\n\n    /**\n     * Returns {@link com.jayway.jsonpath.spi.json.JsonProvider} used by this configuration\n     * @return jsonProvider used\n     */\n    public JsonProvider jsonProvider() {\n        return jsonProvider;\n    }\n\n    /**\n     * Creates a new Configuration based on the given {@link com.jayway.jsonpath.spi.mapper.MappingProvider}\n     * @param newMappingProvider mapping provider to use in new configuration\n     * @return a new configuration\n     */\n    public Configuration mappingProvider(MappingProvider newMappingProvider) {\n        return Configuration.builder().jsonProvider(jsonProvider).mappingProvider(newMappingProvider).options(options).evaluationListener(evaluationListeners).build();\n    }\n\n    /**\n     * Returns {@link com.jayway.jsonpath.spi.mapper.MappingProvider} used by this configuration\n     * @return mappingProvider used\n     */\n    public MappingProvider mappingProvider() {\n        return mappingProvider;\n    }\n\n    /**\n     * Creates a new configuration by adding the new options to the options used in this configuration.\n     * @param options options to add\n     * @return a new configuration\n     */\n    public Configuration addOptions(Option... options) {\n        EnumSet<Option> opts = EnumSet.noneOf(Option.class);\n        opts.addAll(this.options);\n        opts.addAll(asList(options));\n        return Configuration.builder().jsonProvider(jsonProvider).mappingProvider(mappingProvider).options(opts).evaluationListener(evaluationListeners).build();\n    }\n\n    /**\n     * Creates a new configuration with the provided options. Options in this configuration are discarded.\n     * @param options\n     * @return the new configuration instance\n     */\n    public Configuration setOptions(Option... options) {\n        return Configuration.builder().jsonProvider(jsonProvider).mappingProvider(mappingProvider).options(options).evaluationListener(evaluationListeners).build();\n    }\n\n    /**\n     * Returns the options used by this configuration\n     * @return the new configuration instance\n     */\n    public Set<Option> getOptions() {\n        return options;\n    }\n\n    /**\n     * Check if this configuration contains the given option\n     * @param option option to check\n     * @return true if configurations contains option\n     */\n    public boolean containsOption(Option option){\n        return options.contains(option);\n    }\n\n    /**\n     * Creates a new configuration based on default values\n     * @return a new configuration based on defaults\n     */\n    public static Configuration defaultConfiguration() {\n        Defaults defaults = getEffectiveDefaults();\n        return Configuration.builder().jsonProvider(defaults.jsonProvider()).options(defaults.options()).build();\n    }\n\n    /**\n     * Returns a new ConfigurationBuilder\n     * @return a builder\n     */\n    public static ConfigurationBuilder builder() {\n        return new ConfigurationBuilder();\n    }\n\n    /**\n     * Configuration builder\n     */\n    public static class ConfigurationBuilder {\n\n        private JsonProvider jsonProvider;\n        private MappingProvider mappingProvider;\n        private EnumSet<Option> options = EnumSet.noneOf(Option.class);\n        private Collection<EvaluationListener> evaluationListener = new ArrayList<EvaluationListener>();\n\n        public ConfigurationBuilder jsonProvider(JsonProvider provider) {\n            this.jsonProvider = provider;\n            return this;\n        }\n\n        public ConfigurationBuilder mappingProvider(MappingProvider provider) {\n            this.mappingProvider = provider;\n            return this;\n        }\n\n        public ConfigurationBuilder options(Option... flags) {\n            if(flags.length > 0) {\n                this.options.addAll(asList(flags));\n            }\n            return this;\n        }\n\n        public ConfigurationBuilder options(Set<Option> options) {\n            this.options.addAll(options);\n            return this;\n        }\n\n        public ConfigurationBuilder evaluationListener(EvaluationListener... listener){\n            this.evaluationListener = Arrays.asList(listener);\n            return this;\n        }\n\n        public ConfigurationBuilder evaluationListener(Collection<EvaluationListener> listeners){\n            this.evaluationListener = listeners == null ? Collections.<EvaluationListener>emptyList() : listeners;\n            return this;\n        }\n\n        public Configuration build() {\n            if (jsonProvider == null || mappingProvider == null) {\n                final Defaults defaults = getEffectiveDefaults();\n                if (jsonProvider == null) {\n                    jsonProvider = defaults.jsonProvider();\n                }\n                if (mappingProvider == null){\n                    mappingProvider = defaults.mappingProvider();\n                }\n            }\n            return new Configuration(jsonProvider, mappingProvider, options, evaluationListener);\n        }\n    }\n\n    public interface Defaults {\n        /**\n         * Returns the default {@link com.jayway.jsonpath.spi.json.JsonProvider}\n         * @return default json provider\n         */\n        JsonProvider jsonProvider();\n\n        /**\n         * Returns default setOptions\n         * @return setOptions\n         */\n        Set<Option> options();\n\n        /**\n         * Returns the default {@link com.jayway.jsonpath.spi.mapper.MappingProvider}\n         *\n         * @return default mapping provider\n         */\n        MappingProvider mappingProvider();\n\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        Configuration that = (Configuration) o;\n        return jsonProvider.getClass() == that.jsonProvider.getClass() &&\n                mappingProvider.getClass() == that.mappingProvider.getClass() &&\n                Objects.equals(options, that.options);\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/Criteria.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\nimport com.jayway.jsonpath.internal.Path;\nimport com.jayway.jsonpath.internal.Utils;\nimport com.jayway.jsonpath.internal.filter.RelationalExpressionNode;\nimport com.jayway.jsonpath.internal.filter.RelationalOperator;\nimport com.jayway.jsonpath.internal.filter.ValueNode;\nimport com.jayway.jsonpath.internal.filter.ValueNodes;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.regex.Pattern;\n\nimport static com.jayway.jsonpath.internal.Utils.notNull;\nimport static com.jayway.jsonpath.internal.filter.ValueNodes.PredicateNode;\nimport static com.jayway.jsonpath.internal.filter.ValueNodes.ValueListNode;\n\n/**\n *\n */\n@SuppressWarnings(\"unchecked\")\npublic class Criteria implements Predicate {\n\n    private final List<Criteria> criteriaChain;\n    private ValueNode left;\n    private RelationalOperator criteriaType;\n    private ValueNode right;\n\n    private Criteria(List<Criteria> criteriaChain, ValueNode left) {\n        this.left = left;\n        this.criteriaChain = criteriaChain;\n        this.criteriaChain.add(this);\n    }\n\n    private Criteria(ValueNode left) {\n        this(new LinkedList<Criteria>(), left);\n    }\n\n    @Override\n    public boolean apply(PredicateContext ctx) {\n        for (RelationalExpressionNode expressionNode : toRelationalExpressionNodes()) {\n            if(!expressionNode.apply(ctx)){\n                return false;\n            }\n        }\n        return true;\n    }\n\n    @Override\n    public String toString() {\n        return Utils.join(\" && \", toRelationalExpressionNodes());\n    }\n\n    private Collection<RelationalExpressionNode> toRelationalExpressionNodes(){\n        List<RelationalExpressionNode> nodes = new ArrayList<RelationalExpressionNode>(criteriaChain.size());\n        for (Criteria criteria : criteriaChain) {\n            nodes.add(new RelationalExpressionNode(criteria.left, criteria.criteriaType, criteria.right));\n        }\n        return nodes;\n    }\n\n    /**\n     * Static factory method to create a Criteria using the provided key\n     *\n     * @param key filed name\n     * @return the new criteria\n     */\n    @Deprecated\n    //This should be private.It exposes internal classes\n    public static Criteria where(Path key) {\n        return new Criteria(ValueNode.createPathNode(key));\n    }\n\n\n    /**\n     * Static factory method to create a Criteria using the provided key\n     *\n     * @param key filed name\n     * @return the new criteria\n     */\n\n    public static Criteria where(String key) {\n        return new Criteria(ValueNode.toValueNode(prefixPath(key)));\n    }\n\n    /**\n     * Static factory method to create a Criteria using the provided key\n     *\n     * @param key ads new filed to criteria\n     * @return the criteria builder\n     */\n    public Criteria and(String key) {\n        checkComplete();\n        return new Criteria(this.criteriaChain, ValueNode.toValueNode(prefixPath(key)));\n    }\n\n    /**\n     * Creates a criterion using equality\n     *\n     * @param o\n     * @return the criteria\n     */\n    public Criteria is(Object o) {\n        this.criteriaType = RelationalOperator.EQ;\n        this.right = ValueNode.toValueNode(o);\n        return this;\n    }\n\n    /**\n     * Creates a criterion using equality\n     *\n     * @param o\n     * @return the criteria\n     */\n    public Criteria eq(Object o) {\n        return is(o);\n    }\n\n    /**\n     * Creates a criterion using the <b>!=</b> operator\n     *\n     * @param o\n     * @return the criteria\n     */\n    public Criteria ne(Object o) {\n        this.criteriaType = RelationalOperator.NE;\n        this.right = ValueNode.toValueNode(o);\n        return this;\n    }\n\n    /**\n     * Creates a criterion using the <b>&lt;</b> operator\n     *\n     * @param o\n     * @return the criteria\n     */\n    public Criteria lt(Object o) {\n        this.criteriaType = RelationalOperator.LT;\n        this.right = ValueNode.toValueNode(o);\n        return this;\n    }\n\n    /**\n     * Creates a criterion using the <b>&lt;=</b> operator\n     *\n     * @param o\n     * @return the criteria\n     */\n    public Criteria lte(Object o) {\n        this.criteriaType = RelationalOperator.LTE;\n        this.right = ValueNode.toValueNode(o);\n        return this;\n    }\n\n    /**\n     * Creates a criterion using the <b>&gt;</b> operator\n     *\n     * @param o\n     * @return the criteria\n     */\n    public Criteria gt(Object o) {\n        this.criteriaType = RelationalOperator.GT;\n        this.right = ValueNode.toValueNode(o);\n        return this;\n    }\n\n    /**\n     * Creates a criterion using the <b>&gt;=</b> operator\n     *\n     * @param o\n     * @return the criteria\n     */\n    public Criteria gte(Object o) {\n        this.criteriaType = RelationalOperator.GTE;\n        this.right = ValueNode.toValueNode(o);\n        return this;\n    }\n\n    /**\n     * Creates a criterion using a Regex\n     *\n     * @param pattern\n     * @return the criteria\n     */\n    public Criteria regex(Pattern pattern) {\n        notNull(pattern, \"pattern can not be null\");\n        this.criteriaType = RelationalOperator.REGEX;\n        this.right = ValueNode.toValueNode(pattern);\n        return this;\n    }\n\n    /**\n     * The <code>in</code> operator is analogous to the SQL IN modifier, allowing you\n     * to specify an array of possible matches.\n     *\n     * @param o the values to match against\n     * @return the criteria\n     */\n    public Criteria in(Object... o) {\n        return in(Arrays.asList(o));\n    }\n\n    /**\n     * The <code>in</code> operator is analogous to the SQL IN modifier, allowing you\n     * to specify an array of possible matches.\n     *\n     * @param c the collection containing the values to match against\n     * @return the criteria\n     */\n    public Criteria in(Collection<?> c) {\n        notNull(c, \"collection can not be null\");\n        this.criteriaType = RelationalOperator.IN;\n        this.right = new ValueListNode(c);\n        return this;\n    }\n\n    /**\n     * The <code>contains</code> operator asserts that the provided object is contained\n     * in the result. The object that should contain the input can be either an object or a String.\n     *\n     * @param o that should exists in given collection or\n     * @return the criteria\n     */\n    public Criteria contains(Object o) {\n        this.criteriaType = RelationalOperator.CONTAINS;\n        this.right = ValueNode.toValueNode(o);\n        return this;\n    }\n\n    /**\n     * The <code>nin</code> operator is similar to $in except that it selects objects for\n     * which the specified field does not have any value in the specified array.\n     *\n     * @param o the values to match against\n     * @return the criteria\n     */\n    public Criteria nin(Object... o) {\n        return nin(Arrays.asList(o));\n    }\n\n    /**\n     * The <code>nin</code> operator is similar to $in except that it selects objects for\n     * which the specified field does not have any value in the specified array.\n     *\n     * @param c the values to match against\n     * @return the criteria\n     */\n    public Criteria nin(Collection<?> c) {\n        notNull(c, \"collection can not be null\");\n        this.criteriaType = RelationalOperator.NIN;\n        this.right = new ValueListNode(c);\n        return this;\n    }\n\n    /**\n     * The <code>subsetof</code> operator selects objects for which the specified field is\n     * an array whose elements comprise a subset of the set comprised by the elements of\n     * the specified array.\n     *\n     * @param o the values to match against\n     * @return the criteria\n     */\n    public Criteria subsetof(Object... o) {\n        return subsetof(Arrays.asList(o));\n    }\n\n    /**\n     * The <code>subsetof</code> operator selects objects for which the specified field is\n     * an array whose elements comprise a subset of the set comprised by the elements of\n     * the specified array.\n     *\n     * @param c the values to match against\n     * @return the criteria\n     */\n    public Criteria subsetof(Collection<?> c) {\n        notNull(c, \"collection can not be null\");\n        this.criteriaType = RelationalOperator.SUBSETOF;\n        this.right = new ValueListNode(c);\n        return this;\n    }\n\n    /**\n     * The <code>anyof</code> operator selects objects for which the specified field is\n     * an array that contain at least an element in the specified array.\n     *\n     * @param o the values to match against\n     * @return the criteria\n     */\n    public Criteria anyof(Object... o) {\n        return subsetof(Arrays.asList(o));\n    }\n\n    /**\n     * The <code>anyof</code> operator selects objects for which the specified field is\n     * an array that contain at least an element in the specified array.\n     *\n     * @param c the values to match against\n     * @return the criteria\n     */\n    public Criteria anyof(Collection<?> c) {\n        notNull(c, \"collection can not be null\");\n        this.criteriaType = RelationalOperator.ANYOF;\n        this.right = new ValueListNode(c);\n        return this;\n    }\n\n    /**\n     * The <code>noneof</code> operator selects objects for which the specified field is\n     * an array that does not contain any of the elements of the specified array.\n     *\n     * @param o the values to match against\n     * @return the criteria\n     */\n    public Criteria noneof(Object... o) {\n        return noneof(Arrays.asList(o));\n    }\n\n    /**\n     * The <code>noneof</code> operator selects objects for which the specified field is\n     * an array that does not contain any of the elements of the specified array.\n     *\n     * @param c the values to match against\n     * @return the criteria\n     */\n    public Criteria noneof(Collection<?> c) {\n        notNull(c, \"collection can not be null\");\n        this.criteriaType = RelationalOperator.NONEOF;\n        this.right = new ValueListNode(c);\n        return this;\n    }\n\n    /**\n     * The <code>all</code> operator is similar to $in, but instead of matching any value\n     * in the specified array all values in the array must be matched.\n     *\n     * @param o\n     * @return the criteria\n     */\n    public Criteria all(Object... o) {\n        return all(Arrays.asList(o));\n    }\n\n    /**\n     * The <code>all</code> operator is similar to $in, but instead of matching any value\n     * in the specified array all values in the array must be matched.\n     *\n     * @param c\n     * @return the criteria\n     */\n    public Criteria all(Collection<?> c) {\n        notNull(c, \"collection can not be null\");\n        this.criteriaType = RelationalOperator.ALL;\n        this.right = new ValueListNode(c);\n        return this;\n    }\n\n    /**\n     * The <code>size</code> operator matches:\n     * <p/>\n     * <ol>\n     * <li>array with the specified number of elements.</li>\n     * <li>string with given length.</li>\n     * </ol>\n     *\n     * @param size\n     * @return the criteria\n     */\n    public Criteria size(int size) {\n        this.criteriaType = RelationalOperator.SIZE;\n        this.right = ValueNode.toValueNode(size);\n        return this;\n    }\n\n    /**\n     * The $type operator matches values based on their Java JSON type.\n     *\n     * Supported types are:\n     *\n     *  List.class\n     *  Map.class\n     *  String.class\n     *  Number.class\n     *  Boolean.class\n     *\n     * Other types evaluates to false\n     *\n     * @param clazz\n     * @return the criteria\n     */\n    public Criteria type(Class<?> clazz) {\n        this.criteriaType = RelationalOperator.TYPE;\n        this.right = ValueNode.createClassNode(clazz);\n        return this;\n    }\n\n    /**\n     * Check for existence (or lack thereof) of a field.\n     *\n     * @param shouldExist\n     * @return the criteria\n     */\n    public Criteria exists(boolean shouldExist) {\n        this.criteriaType = RelationalOperator.EXISTS;\n        this.right = ValueNode.toValueNode(shouldExist);\n        this.left = left.asPathNode().asExistsCheck(shouldExist);\n        return this;\n    }\n\n    /**\n     * The <code>notEmpty</code> operator checks that an array or String is not empty.\n     *\n     * @return the criteria\n     */\n    @Deprecated\n    public Criteria notEmpty() {\n        return empty(false);\n    }\n\n    /**\n     * The <code>notEmpty</code> operator checks that an array or String is empty.\n     *\n     * @param empty should be empty\n     * @return the criteria\n     */\n    public Criteria empty(boolean empty) {\n        this.criteriaType = RelationalOperator.EMPTY;\n        this.right = empty ? ValueNodes.TRUE : ValueNodes.FALSE;\n        return this;\n    }\n\n    /**\n     * The <code>matches</code> operator checks that an object matches the given predicate.\n     *\n     * @param p\n     * @return the criteria\n     */\n    public Criteria matches(Predicate p) {\n        this.criteriaType = RelationalOperator.MATCHES;\n        this.right = new PredicateNode(p);\n        return this;\n    }\n\n    /**\n     * Parse the provided criteria\n     *\n     * Deprecated use {@link Filter#parse(String)}\n     *\n     * @param criteria\n     * @return a criteria\n     */\n    @Deprecated\n    public static Criteria parse(String criteria) {\n        if(criteria == null){\n            throw new InvalidPathException(\"Criteria can not be null\");\n        }\n        String[] split = criteria.trim().split(\" \");\n        if(split.length == 3){\n            return create(split[0], split[1], split[2]);\n        } else if(split.length == 1){\n            return create(split[0], \"EXISTS\", \"true\");\n        } else {\n            throw new InvalidPathException(\"Could not parse criteria\");\n        }\n    }\n\n    /**\n     * Creates a new criteria\n     * @param left path to evaluate in criteria\n     * @param operator operator\n     * @param right expected value\n     * @return a new Criteria\n     */\n    @Deprecated\n    public static Criteria create(String left, String operator, String right) {\n        Criteria criteria = new Criteria(ValueNode.toValueNode(left));\n        criteria.criteriaType = RelationalOperator.fromString(operator);\n        criteria.right = ValueNode.toValueNode(right);\n        return criteria;\n    }\n\n\n    private static String prefixPath(String key){\n        if (!key.startsWith(\"$\") && !key.startsWith(\"@\")) {\n            key = \"@.\" + key;\n        }\n        return key;\n    }\n\n    private void checkComplete(){\n        boolean complete = (left != null && criteriaType != null && right != null);\n        if(!complete){\n            throw new JsonPathException(\"Criteria build exception. Complete on criteria before defining next.\");\n        }\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/DocumentContext.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\npublic interface DocumentContext extends ReadContext, WriteContext {\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/EvaluationListener.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\n/**\n * A listener that can be registered on a {@link com.jayway.jsonpath.Configuration} that is notified when a\n * result is added to the result of this path evaluation.\n */\npublic interface EvaluationListener {\n\n    /**\n     * Callback invoked when result is found\n     * @param found the found result\n     * @return continuation instruction\n     */\n    EvaluationContinuation resultFound(FoundResult found);\n\n    enum EvaluationContinuation {\n        /**\n         * Evaluation continues\n         */\n        CONTINUE,\n        /**\n         * Current result is included but no further evaluation will be performed.\n         */\n        ABORT\n    }\n\n    /**\n     *\n     */\n    interface FoundResult {\n        /**\n         * the index of this result. First result i 0\n         * @return index\n         */\n        int index();\n\n        /**\n         * The path of this result\n         * @return path\n         */\n        String path();\n\n        /**\n         * The result object\n         * @return the result object\n         */\n        Object result();\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/Filter.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\nimport com.jayway.jsonpath.internal.filter.FilterCompiler;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Iterator;\n\nimport static java.util.Arrays.asList;\n\n/**\n *\n */\npublic abstract class Filter implements Predicate {\n\n    /**\n     * Creates a new Filter based on given criteria\n     * @param predicate criteria\n     * @return a new Filter\n     */\n    public static Filter filter(Predicate predicate) {\n        return new SingleFilter(predicate);\n    }\n\n    /**\n     * Create a new Filter based on given list of criteria.\n     * @param predicates list of criteria all needs to evaluate to true\n     * @return the filter\n     */\n    public static Filter filter(Collection<Predicate> predicates) {\n        return new AndFilter(predicates);\n    }\n\n    @Override\n    public abstract boolean apply(PredicateContext ctx);\n\n\n    public Filter or(final Predicate other){\n        return new OrFilter(this, other);\n    }\n\n    public Filter and(final Predicate other){\n        return new AndFilter(this, other);\n    }\n\n    /**\n     * Parses a filter. The filter must match <code>[?(<filter>)]</code>, white spaces are ignored.\n     * @param filter filter string to parse\n     * @return the filter\n     */\n    public static Filter parse(String filter){\n        return FilterCompiler.compile(filter);\n    }\n\n    private static final class SingleFilter extends Filter {\n\n        private final Predicate predicate;\n\n        private SingleFilter(Predicate predicate) {\n            this.predicate = predicate;\n        }\n\n        @Override\n        public boolean apply(PredicateContext ctx) {\n            return predicate.apply(ctx);\n        }\n\n        @Override\n        public String toString() {\n            String predicateString = predicate.toString();\n            if(predicateString.startsWith(\"(\")){\n                return \"[?\" + predicateString + \"]\";\n            } else {\n                return \"[?(\" + predicateString + \")]\";\n            }\n        }\n    }\n\n    private static final class AndFilter extends Filter {\n\n        private final Collection<Predicate> predicates;\n\n        private AndFilter(Collection<Predicate> predicates) {\n            this.predicates = predicates;\n        }\n\n        private AndFilter(Predicate left, Predicate right) {\n            this(asList(left, right));\n        }\n\n        public Filter and(final Predicate other){\n            Collection<Predicate> newPredicates = new ArrayList<Predicate>(predicates);\n            newPredicates.add(other);\n            return new AndFilter(newPredicates);\n        }\n\n        @Override\n        public boolean apply(PredicateContext ctx) {\n            for (Predicate predicate : predicates) {\n                if(!predicate.apply(ctx)){\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        @Override\n        public String toString() {\n            Iterator<Predicate> i = predicates.iterator();\n            StringBuilder sb = new StringBuilder();\n            sb.append(\"[?(\");\n            while (i.hasNext()){\n                String p = i.next().toString();\n\n                if(p.startsWith(\"[?(\")){\n                    p = p.substring(3, p.length() - 2);\n                }\n                sb.append(p);\n\n                if(i.hasNext()){\n                    sb.append(\" && \");\n                }\n            }\n            sb.append(\")]\");\n            return sb.toString();\n        }\n    }\n\n    private static final class OrFilter extends Filter {\n\n        private final Predicate left;\n        private final Predicate right;\n  \n        private OrFilter(Predicate left, Predicate right) {\n            this.left = left;\n            this.right = right;\n        }\n\n        public Filter and(final Predicate other){\n            return new OrFilter(left, new AndFilter(right, other));\n        }\n\n        @Override\n        public boolean apply(PredicateContext ctx) {\n            boolean a = left.apply(ctx);\n            return a || right.apply(ctx);\n        }\n\n        @Override\n        public String toString() {\n            StringBuilder sb = new StringBuilder();\n            sb.append(\"[?(\");\n\n            String l = left.toString();\n            String r = right.toString();\n\n            if(l.startsWith(\"[?(\")){\n                l = l.substring(3, l.length() - 2);\n            }\n            if(r.startsWith(\"[?(\")){\n                r = r.substring(3, r.length() - 2);\n            }\n\n            sb.append(l).append(\" || \").append(r);\n\n            sb.append(\")]\");\n            return sb.toString();\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/InvalidCriteriaException.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\n@SuppressWarnings(\"serial\")\npublic class InvalidCriteriaException extends JsonPathException {\n    public InvalidCriteriaException() {\n    }\n\n    public InvalidCriteriaException(String message) {\n        super(message);\n    }\n\n    public InvalidCriteriaException(String message, Throwable cause) {\n        super(message, cause);\n    }\n\n    public InvalidCriteriaException(Throwable cause) {\n        super(cause);\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/InvalidJsonException.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\n@SuppressWarnings(\"serial\")\npublic class InvalidJsonException extends JsonPathException {\n\n    /**\n     * Problematic JSON if available.\n     */\n    private final String json;\n    \n    public InvalidJsonException() {\n        json = null;\n    }\n\n    public InvalidJsonException(String message) {\n        super(message);\n        json = null;\n    }\n\n    public InvalidJsonException(String message, Throwable cause) {\n        super(message, cause);\n        json = null;\n    }\n\n    public InvalidJsonException(Throwable cause) {\n        super(cause);\n        json = null;\n    }\n    \n    /**\n     * Rethrow the exception with the problematic JSON captured.\n     */\n    public InvalidJsonException(final Throwable cause, final String json) {\n        super(cause);\n        this.json = json;\n    }\n    \n    /**\n     * @return the problematic JSON if available.\n     */\n    public String getJson() {\n        return json;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/InvalidModificationException.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\npublic class InvalidModificationException extends JsonPathException {\n    public InvalidModificationException(String message) {\n        super(message);\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/InvalidPathException.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\n@SuppressWarnings(\"serial\")\npublic class InvalidPathException extends JsonPathException {\n\n    public InvalidPathException() {\n    }\n\n    public InvalidPathException(String message) {\n        super(message);\n    }\n\n    public InvalidPathException(String message, Throwable cause) {\n        super(message, cause);\n    }\n\n    public InvalidPathException(Throwable cause) {\n        super(cause);\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/JsonPath.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\n\nimport com.jayway.jsonpath.internal.*;\nimport com.jayway.jsonpath.internal.path.PathCompiler;\nimport com.jayway.jsonpath.spi.json.JsonProvider;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URL;\n\nimport static com.jayway.jsonpath.Option.ALWAYS_RETURN_LIST;\nimport static com.jayway.jsonpath.Option.AS_PATH_LIST;\nimport static com.jayway.jsonpath.internal.Utils.*;\n\n/**\n * <p/>\n * JsonPath is to JSON what XPATH is to XML, a simple way to extract parts of a given document. JsonPath is\n * available in many programming languages such as Javascript, Python and PHP.\n * <p/>\n * JsonPath allows you to compile a json path string to use it many times or to compile and apply in one\n * single on demand operation.\n * <p/>\n * Given the Json document:\n * <p/>\n * <pre>\n * String json =\n * \"{\n * \"store\":\n * {\n * \"book\":\n * [\n * {\n * \"category\": \"reference\",\n * \"author\": \"Nigel Rees\",\n * \"title\": \"Sayings of the Century\",\n * \"price\": 8.95\n * },\n * {\n * \"category\": \"fiction\",\n * \"author\": \"Evelyn Waugh\",\n * \"title\": \"Sword of Honour\",\n * \"price\": 12.99\n * }\n * ],\n * \"bicycle\":\n * {\n * \"color\": \"red\",\n * \"price\": 19.95\n * }\n * }\n * }\";\n * </pre>\n * <p/>\n * A JsonPath can be compiled and used as shown:\n * <p/>\n * <code>\n * JsonPath path = JsonPath.compile(\"$.store.book[1]\");\n * <br/>\n * List&lt;Object&gt; books = path.read(json);\n * </code>\n * </p>\n * Or:\n * <p/>\n * <code>\n * List&lt;Object&gt; authors = JsonPath.read(json, \"$.store.book[*].author\")\n * </code>\n * <p/>\n * If the json path returns a single value (is definite):\n * </p>\n * <code>\n * String author = JsonPath.read(json, \"$.store.book[1].author\")\n * </code>\n */\npublic class JsonPath {\n\n    private final Path path;\n\n    private JsonPath(String jsonPath, Predicate[] filters) {\n        notNull(jsonPath, \"path can not be null\");\n        this.path = PathCompiler.compile(jsonPath, filters);\n    }\n\n    /**\n     * Returns the string representation of this JsonPath\n     *\n     * @return path as String\n     */\n    public String getPath() {\n        return this.path.toString();\n    }\n\n    /**\n     * @see JsonPath#isDefinite()\n     */\n    public static boolean isPathDefinite(String path) {\n        return compile(path).isDefinite();\n    }\n\n\n    /**\n     * Checks if a path points to a single item or if it potentially returns multiple items\n     * <p/>\n     * a path is considered <strong>not</strong> definite if it contains a scan fragment \"..\"\n     * or an array position fragment that is not based on a single index\n     * <p/>\n     * <p/>\n     * definite path examples are:\n     * <p/>\n     * $store.book\n     * $store.book[1].title\n     * <p/>\n     * not definite path examples are:\n     * <p/>\n     * $..book\n     * $.store.book[*]\n     * $.store.book[1,2]\n     * $.store.book[?(@.category = 'fiction')]\n     *\n     * @return true if path is definite (points to single item)\n     */\n    public boolean isDefinite() {\n        return path.isDefinite();\n    }\n\n    /**\n     * Applies this JsonPath to the provided json document.\n     * Note that the document must be identified as either a List or Map by\n     * the {@link JsonProvider}\n     *\n     * @param jsonObject a container Object\n     * @param <T>        expected return type\n     * @return object(s) matched by the given path\n     */\n    @SuppressWarnings({\"unchecked\"})\n    public <T> T read(Object jsonObject) {\n        return read(jsonObject, Configuration.defaultConfiguration());\n    }\n\n    /**\n     * Applies this JsonPath to the provided json document.\n     * Note that the document must be identified as either a List or Map by\n     * the {@link JsonProvider}\n     *\n     * @param jsonObject    a container Object\n     * @param configuration configuration to use\n     * @param <T>           expected return type\n     * @return object(s) matched by the given path\n     */\n    @SuppressWarnings(\"unchecked\")\n    public <T> T read(Object jsonObject, Configuration configuration) {\n        boolean optAsPathList = configuration.containsOption(AS_PATH_LIST);\n        boolean optAlwaysReturnList = configuration.containsOption(Option.ALWAYS_RETURN_LIST);\n        boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);\n\n        if (path.isFunctionPath()) {\n            if (optAsPathList || optAlwaysReturnList) {\n                if (optSuppressExceptions) {\n                    return (T) (path.isDefinite() ? null : configuration.jsonProvider().createArray());\n                }\n                throw new JsonPathException(\"Options \" + AS_PATH_LIST + \" and \" + ALWAYS_RETURN_LIST + \" are not allowed when using path functions!\");\n            }\n            EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration);\n            if (optSuppressExceptions && evaluationContext.getPathList().isEmpty()) {\n                return (T) (path.isDefinite() ? null : configuration.jsonProvider().createArray());\n            }\n            return evaluationContext.getValue(true);\n        } else if (optAsPathList) {\n            EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration);\n            if (optSuppressExceptions && evaluationContext.getPathList().isEmpty()) {\n                return (T) configuration.jsonProvider().createArray();\n            }\n            return (T) evaluationContext.getPath();\n        } else {\n            EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration);\n            if (optSuppressExceptions && evaluationContext.getPathList().isEmpty()) {\n                if (optAlwaysReturnList) {\n                    return (T) configuration.jsonProvider().createArray();\n                } else {\n                    return (T) (path.isDefinite() ? null : configuration.jsonProvider().createArray());\n                }\n            }\n            Object res = evaluationContext.getValue(false);\n            if (optAlwaysReturnList && path.isDefinite()) {\n                Object array = configuration.jsonProvider().createArray();\n                configuration.jsonProvider().setArrayIndex(array, 0, res);\n                return (T) array;\n            } else {\n                return (T) res;\n            }\n        }\n    }\n\n    /**\n     * Set the value this path points to in the provided jsonObject\n     *\n     * @param jsonObject    a json object\n     * @param configuration configuration to use\n     * @param <T>           expected return type\n     * @return the updated jsonObject or the path list to updated objects if option AS_PATH_LIST is set.\n     */\n    public <T> T set(Object jsonObject, Object newVal, Configuration configuration) {\n        notNull(jsonObject, \"json can not be null\");\n        notNull(configuration, \"configuration can not be null\");\n        EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration, true);\n        if (evaluationContext.getPathList().isEmpty()) {\n            boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);\n            if (optSuppressExceptions) {\n                return handleMissingPathInContext(configuration);\n            } else {\n                throw new PathNotFoundException();\n            }\n        }\n        for (PathRef updateOperation : evaluationContext.updateOperations()) {\n            updateOperation.set(newVal, configuration);\n        }\n        return resultByConfiguration(jsonObject, configuration, evaluationContext);\n    }\n\n\n    /**\n     * Replaces the value on the given path with the result of the {@link MapFunction}.\n     *\n     * @param jsonObject    a json object\n     * @param mapFunction   Converter object to be invoked\n     * @param configuration configuration to use\n     * @return the updated jsonObject or the path list to updated objects if option AS_PATH_LIST is set.\n     */\n    public <T> T map(Object jsonObject, MapFunction mapFunction, Configuration configuration) {\n        notNull(jsonObject, \"json can not be null\");\n        notNull(configuration, \"configuration can not be null\");\n        notNull(mapFunction, \"mapFunction can not be null\");\n        EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration, true);\n        if (evaluationContext.getPathList().isEmpty()) {\n            boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);\n            if (optSuppressExceptions) {\n                return handleMissingPathInContext(configuration);\n            } else {\n                throw new PathNotFoundException();\n            }\n        }\n        for (PathRef updateOperation : evaluationContext.updateOperations()) {\n            updateOperation.convert(mapFunction, configuration);\n        }\n        return resultByConfiguration(jsonObject, configuration, evaluationContext);\n\n    }\n\n    /**\n     * Deletes the object this path points to in the provided jsonObject\n     *\n     * @param jsonObject    a json object\n     * @param configuration configuration to use\n     * @param <T>           expected return type\n     * @return the updated jsonObject or the path list to deleted objects if option AS_PATH_LIST is set.\n     */\n    public <T> T delete(Object jsonObject, Configuration configuration) {\n        notNull(jsonObject, \"json can not be null\");\n        notNull(configuration, \"configuration can not be null\");\n        EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration, true);\n        if (evaluationContext.getPathList().isEmpty()) {\n            boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);\n            if (optSuppressExceptions) {\n                return handleMissingPathInContext(configuration);\n            } else {\n                throw new PathNotFoundException();\n            }\n        }\n        for (PathRef updateOperation : evaluationContext.updateOperations()) {\n            updateOperation.delete(configuration);\n        }\n        return resultByConfiguration(jsonObject, configuration, evaluationContext);\n    }\n\n    /**\n     * Adds a new value to the Array this path points to in the provided jsonObject\n     *\n     * @param jsonObject    a json object\n     * @param value         the value to add\n     * @param configuration configuration to use\n     * @param <T>           expected return type\n     * @return the updated jsonObject or the path list to updated object if option AS_PATH_LIST is set.\n     */\n    public <T> T add(Object jsonObject, Object value, Configuration configuration) {\n        notNull(jsonObject, \"json can not be null\");\n        notNull(configuration, \"configuration can not be null\");\n        EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration, true);\n        if (evaluationContext.getPathList().isEmpty()) {\n            boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);\n            if (optSuppressExceptions) {\n                return handleMissingPathInContext(configuration);\n            } else {\n                throw new PathNotFoundException();\n            }\n        }\n        for (PathRef updateOperation : evaluationContext.updateOperations()) {\n            updateOperation.add(value, configuration);\n        }\n        return resultByConfiguration(jsonObject, configuration, evaluationContext);\n    }\n\n    /**\n     * Adds or updates the Object this path points to in the provided jsonObject with a key with a value\n     *\n     * @param jsonObject    a json object\n     * @param key           the key to add or update\n     * @param value         the new value\n     * @param configuration configuration to use\n     * @param <T>           expected return type\n     * @return the updated jsonObject or the path list to updated objects if option AS_PATH_LIST is set.\n     */\n    public <T> T put(Object jsonObject, String key, Object value, Configuration configuration) {\n        notNull(jsonObject, \"json can not be null\");\n        notEmpty(key, \"key can not be null or empty\");\n        notNull(configuration, \"configuration can not be null\");\n        EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration, true);\n        if (evaluationContext.getPathList().isEmpty()) {\n            boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);\n            if (optSuppressExceptions) {\n                return handleMissingPathInContext(configuration);\n            } else {\n                throw new PathNotFoundException();\n            }\n        }\n        for (PathRef updateOperation : evaluationContext.updateOperations()) {\n            updateOperation.put(key, value, configuration);\n        }\n        return resultByConfiguration(jsonObject, configuration, evaluationContext);\n    }\n\n    public <T> T renameKey(Object jsonObject, String oldKeyName, String newKeyName, Configuration configuration) {\n        notNull(jsonObject, \"json can not be null\");\n        notEmpty(newKeyName, \"newKeyName can not be null or empty\");\n        notNull(configuration, \"configuration can not be null\");\n        EvaluationContext evaluationContext = path.evaluate(jsonObject, jsonObject, configuration, true);\n        for (PathRef updateOperation : evaluationContext.updateOperations()) {\n            boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);\n            try {\n                updateOperation.renameKey(oldKeyName, newKeyName, configuration);\n            } catch (RuntimeException e) {\n                if(!optSuppressExceptions){\n                    throw e;\n                }else{\n                    // With option SUPPRESS_EXCEPTIONS,\n                    // the PathNotFoundException should be ignored and the other updateOperation should be continued.\n                }\n            }\n        }\n        return resultByConfiguration(jsonObject, configuration, evaluationContext);\n    }\n\n    /**\n     * Applies this JsonPath to the provided json string\n     *\n     * @param json a json string\n     * @param <T>  expected return type\n     * @return list of objects matched by the given path\n     */\n    @SuppressWarnings({\"unchecked\"})\n    public <T> T read(String json) {\n        return read(json, Configuration.defaultConfiguration());\n    }\n\n    /**\n     * Applies this JsonPath to the provided json string\n     *\n     * @param json          a json string\n     * @param configuration configuration to use\n     * @param <T>           expected return type\n     * @return list of objects matched by the given path\n     */\n    @SuppressWarnings({\"unchecked\"})\n    public <T> T read(String json, Configuration configuration) {\n        notEmpty(json, \"json can not be null or empty\");\n        notNull(configuration, \"jsonProvider can not be null\");\n\n        return read(configuration.jsonProvider().parse(json), configuration);\n    }\n\n    /**\n     * Applies this JsonPath to the provided json URL\n     *\n     * @param jsonURL url to read from\n     * @param <T>     expected return type\n     * @return list of objects matched by the given path\n     * @throws IOException\n     */\n    @SuppressWarnings({\"unchecked\"})\n    public <T> T read(URL jsonURL) throws IOException {\n        return read(jsonURL, Configuration.defaultConfiguration());\n    }\n\n    /**\n     * Applies this JsonPath to the provided json file\n     *\n     * @param jsonFile file to read from\n     * @param <T>      expected return type\n     * @return list of objects matched by the given path\n     * @throws IOException\n     */\n    @SuppressWarnings({\"unchecked\"})\n    public <T> T read(File jsonFile) throws IOException {\n        return read(jsonFile, Configuration.defaultConfiguration());\n    }\n\n\n    /**\n     * Applies this JsonPath to the provided json file\n     *\n     * @param jsonFile      file to read from\n     * @param configuration configuration to use\n     * @param <T>           expected return type\n     * @return list of objects matched by the given path\n     * @throws IOException\n     */\n    @SuppressWarnings({\"unchecked\"})\n    public <T> T read(File jsonFile, Configuration configuration) throws IOException {\n        notNull(jsonFile, \"json file can not be null\");\n        isTrue(jsonFile.exists(), \"json file does not exist\");\n        notNull(configuration, \"jsonProvider can not be null\");\n\n        FileInputStream fis = null;\n        try {\n            fis = new FileInputStream(jsonFile);\n            return read(fis, configuration);\n        } finally {\n            Utils.closeQuietly(fis);\n        }\n    }\n\n    /**\n     * Applies this JsonPath to the provided json input stream\n     *\n     * @param jsonInputStream input stream to read from\n     * @param <T>             expected return type\n     * @return list of objects matched by the given path\n     * @throws IOException\n     */\n    @SuppressWarnings({\"unchecked\"})\n    public <T> T read(InputStream jsonInputStream) throws IOException {\n        return read(jsonInputStream, Configuration.defaultConfiguration());\n    }\n\n    /**\n     * Applies this JsonPath to the provided json input stream\n     *\n     * @param jsonInputStream input stream to read from\n     * @param configuration   configuration to use\n     * @param <T>             expected return type\n     * @return list of objects matched by the given path\n     * @throws IOException\n     */\n    @SuppressWarnings({\"unchecked\"})\n    public <T> T read(InputStream jsonInputStream, Configuration configuration) throws IOException {\n        notNull(jsonInputStream, \"json input stream can not be null\");\n        notNull(configuration, \"configuration can not be null\");\n\n        return read(jsonInputStream, \"UTF-8\", configuration);\n    }\n\n    /**\n     * Applies this JsonPath to the provided json input stream\n     *\n     * @param jsonInputStream input stream to read from\n     * @param configuration   configuration to use\n     * @param <T>             expected return type\n     * @return list of objects matched by the given path\n     * @throws IOException\n     */\n    @SuppressWarnings({\"unchecked\"})\n    public <T> T read(InputStream jsonInputStream, String charset, Configuration configuration) throws IOException {\n        notNull(jsonInputStream, \"json input stream can not be null\");\n        notNull(charset, \"charset can not be null\");\n        notNull(configuration, \"configuration can not be null\");\n\n        try {\n            return read(configuration.jsonProvider().parse(jsonInputStream, charset), configuration);\n        } finally {\n            Utils.closeQuietly(jsonInputStream);\n        }\n    }\n\n    // --------------------------------------------------------\n    //\n    // Static factory methods\n    //\n    // --------------------------------------------------------\n\n    /**\n     * Compiles a JsonPath\n     *\n     * @param jsonPath to compile\n     * @param filters  filters to be applied to the filter place holders  [?] in the path\n     * @return compiled JsonPath\n     */\n    public static JsonPath compile(String jsonPath, Predicate... filters) {\n        notEmpty(jsonPath, \"json can not be null or empty\");\n\n        return new JsonPath(jsonPath, filters);\n    }\n\n\n    // --------------------------------------------------------\n    //\n    // Static utility functions\n    //\n    // --------------------------------------------------------\n\n    /**\n     * Creates a new JsonPath and applies it to the provided Json object\n     *\n     * @param json     a json object\n     * @param jsonPath the json path\n     * @param filters  filters to be applied to the filter place holders  [?] in the path\n     * @param <T>      expected return type\n     * @return list of objects matched by the given path\n     */\n    @SuppressWarnings({\"unchecked\"})\n    public static <T> T read(Object json, String jsonPath, Predicate... filters) {\n        return parse(json).read(jsonPath, filters);\n    }\n\n    /**\n     * Creates a new JsonPath and applies it to the provided Json string\n     *\n     * @param json     a json string\n     * @param jsonPath the json path\n     * @param filters  filters to be applied to the filter place holders  [?] in the path\n     * @param <T>      expected return type\n     * @return list of objects matched by the given path\n     */\n    @SuppressWarnings({\"unchecked\"})\n    public static <T> T read(String json, String jsonPath, Predicate... filters) {\n        return new ParseContextImpl().parse(json).read(jsonPath, filters);\n    }\n\n\n    /**\n     * Creates a new JsonPath and applies it to the provided Json object\n     *\n     * @param jsonURL  url pointing to json doc\n     * @param jsonPath the json path\n     * @param filters  filters to be applied to the filter place holders  [?] in the path\n     * @param <T>      expected return type\n     * @return list of objects matched by the given path\n     */\n    @SuppressWarnings({\"unchecked\"})\n    @Deprecated\n    public static <T> T read(URL jsonURL, String jsonPath, Predicate... filters) throws IOException {\n        return new ParseContextImpl().parse(jsonURL).read(jsonPath, filters);\n    }\n\n    /**\n     * Creates a new JsonPath and applies it to the provided Json object\n     *\n     * @param jsonFile json file\n     * @param jsonPath the json path\n     * @param filters  filters to be applied to the filter place holders  [?] in the path\n     * @param <T>      expected return type\n     * @return list of objects matched by the given path\n     */\n    @SuppressWarnings({\"unchecked\"})\n    public static <T> T read(File jsonFile, String jsonPath, Predicate... filters) throws IOException {\n        return new ParseContextImpl().parse(jsonFile).read(jsonPath, filters);\n    }\n\n    /**\n     * Creates a new JsonPath and applies it to the provided Json object\n     *\n     * @param jsonInputStream json input stream\n     * @param jsonPath        the json path\n     * @param filters         filters to be applied to the filter place holders  [?] in the path\n     * @param <T>             expected return type\n     * @return list of objects matched by the given path\n     */\n    @SuppressWarnings({\"unchecked\"})\n    public static <T> T read(InputStream jsonInputStream, String jsonPath, Predicate... filters) throws IOException {\n        return new ParseContextImpl().parse(jsonInputStream).read(jsonPath, filters);\n    }\n\n\n    // --------------------------------------------------------\n    //\n    // Static Fluent API\n    //\n    // --------------------------------------------------------\n\n\n    /**\n     * Creates a {@link ParseContext} that can be used to parse JSON input. The parse context\n     * is as thread safe as the underlying {@link JsonProvider}. Note that not all JsonProvider are\n     * thread safe.\n     *\n     * @param configuration configuration to use when parsing JSON\n     * @return a parsing context based on given configuration\n     */\n    public static ParseContext using(Configuration configuration) {\n        return new ParseContextImpl(configuration);\n    }\n\n    /**\n     * Creates a {@link ParseContext} that will parse a given JSON input.\n     *\n     * @param provider jsonProvider to use when parsing JSON\n     * @return a parsing context based on given jsonProvider\n     */\n    @Deprecated\n    public static ParseContext using(JsonProvider provider) {\n        return new ParseContextImpl(Configuration.builder().jsonProvider(provider).build());\n    }\n\n    /**\n     * Parses the given JSON input using the default {@link Configuration} and\n     * returns a {@link DocumentContext} for path evaluation\n     *\n     * @param json input\n     * @return a read context\n     */\n    public static DocumentContext parse(Object json) {\n        return new ParseContextImpl().parse(json);\n    }\n\n    /**\n     * Parses the given JSON input using the default {@link Configuration} and\n     * returns a {@link DocumentContext} for path evaluation\n     *\n     * @param json string\n     * @return a read context\n     */\n    public static DocumentContext parse(String json) {\n        return new ParseContextImpl().parse(json);\n    }\n\n    /**\n     * Parses the given JSON input using the default {@link Configuration} and\n     * returns a {@link DocumentContext} for path evaluation\n     *\n     * @param json stream\n     * @return a read context\n     */\n    public static DocumentContext parse(InputStream json) {\n        return new ParseContextImpl().parse(json);\n    }\n\n    /**\n     * Parses the given JSON input using the default {@link Configuration} and\n     * returns a {@link DocumentContext} for path evaluation\n     *\n     * @param json file\n     * @return a read context\n     */\n    public static DocumentContext parse(File json) throws IOException {\n        return new ParseContextImpl().parse(json);\n    }\n\n    /**\n     * Parses the given JSON input using the default {@link Configuration} and\n     * returns a {@link DocumentContext} for path evaluation\n     *\n     * @param json url\n     * @return a read context\n     */\n    @Deprecated\n    public static DocumentContext parse(URL json) throws IOException {\n        return new ParseContextImpl().parse(json);\n    }\n\n    /**\n     * Parses the given JSON input using the provided {@link Configuration} and\n     * returns a {@link DocumentContext} for path evaluation\n     *\n     * @param json input\n     * @return a read context\n     */\n    public static DocumentContext parse(Object json, Configuration configuration) {\n        return new ParseContextImpl(configuration).parse(json);\n    }\n\n    /**\n     * Parses the given JSON input using the provided {@link Configuration} and\n     * returns a {@link DocumentContext} for path evaluation\n     *\n     * @param json input\n     * @return a read context\n     */\n    public static DocumentContext parse(String json, Configuration configuration) {\n        return new ParseContextImpl(configuration).parse(json);\n    }\n\n    /**\n     * Parses the given JSON input using the provided {@link Configuration} and\n     * returns a {@link DocumentContext} for path evaluation\n     *\n     * @param json input\n     * @return a read context\n     */\n    public static DocumentContext parse(InputStream json, Configuration configuration) {\n        return new ParseContextImpl(configuration).parse(json);\n    }\n\n    /**\n     * Parses the given JSON input using the provided {@link Configuration} and\n     * returns a {@link DocumentContext} for path evaluation\n     *\n     * @param json input\n     * @return a read context\n     */\n    public static DocumentContext parse(File json, Configuration configuration) throws IOException {\n        return new ParseContextImpl(configuration).parse(json);\n    }\n\n    /**\n     * Parses the given JSON input using the provided {@link Configuration} and\n     * returns a {@link DocumentContext} for path evaluation\n     *\n     * @param json input\n     * @return a read context\n     */\n    @Deprecated\n    public static DocumentContext parse(URL json, Configuration configuration) throws IOException {\n        return new ParseContextImpl(configuration).parse(json);\n    }\n\n    private <T> T resultByConfiguration(Object jsonObject, Configuration configuration, EvaluationContext evaluationContext) {\n        if(configuration.containsOption(AS_PATH_LIST)){\n            return (T)evaluationContext.getPathList();\n        } else {\n            return (T) jsonObject;\n        }\n    }\n\n    private <T> T handleMissingPathInContext(final Configuration configuration) {\n        boolean optAsPathList = configuration.containsOption(AS_PATH_LIST);\n        boolean optAlwaysReturnList = configuration.containsOption(Option.ALWAYS_RETURN_LIST);\n        if (optAsPathList) {\n            return (T) configuration.jsonProvider().createArray();\n        } else {\n            if (optAlwaysReturnList) {\n                return (T) configuration.jsonProvider().createArray();\n            } else {\n                return (T) (path.isDefinite() ? null : configuration.jsonProvider().createArray());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/JsonPathException.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\npublic class JsonPathException extends RuntimeException {\n\n    public JsonPathException() {\n    }\n\n    public JsonPathException(String message) {\n        super(message);\n    }\n\n    public JsonPathException(String message, Throwable cause) {\n        super(message, cause);\n    }\n\n    public JsonPathException(Throwable cause) {\n        super(cause);\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/MapFunction.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\n\n/**\n * Returns a new representation for the input value.\n */\npublic interface MapFunction {\n    Object map(Object currentValue, Configuration configuration);\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/Option.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\npublic enum Option {\n\n    /**\n     * returns <code>null</code> for missing leaf.\n     *\n     * <pre>\n     * [\n     *      {\n     *         \"foo\" : \"foo1\",\n     *         \"bar\" : \"bar1\"\n     *      }\n     *      {\n     *         \"foo\" : \"foo2\"\n     *      }\n     * ]\n     *</pre>\n     *\n     * the path :\n     *\n     * \"$[*].bar\"\n     *\n     * Without flag [\"bar1\"] is returned\n     * With flag [\"bar1\", null] is returned\n     *\n     *\n     */\n    DEFAULT_PATH_LEAF_TO_NULL,\n\n    /**\n     * Makes this implementation more compliant to the Goessner spec. All results are returned as Lists.\n     */\n    ALWAYS_RETURN_LIST,\n\n    /**\n     * Returns a list of path strings representing the path of the evaluation hits\n     */\n    AS_PATH_LIST,\n\n    /**\n     * Suppress all exceptions when evaluating path.\n     * <br/>\n     * If an exception is thrown and the option {@link Option#ALWAYS_RETURN_LIST} an empty list is returned.\n     * If an exception is thrown and the option {@link Option#ALWAYS_RETURN_LIST} is not present null is returned.\n     */\n    SUPPRESS_EXCEPTIONS,\n\n    /**\n     * Configures JsonPath to require properties defined in path when an <bold>indefinite</bold> path is evaluated.\n     *\n     *\n     * Given:\n     *\n     * <pre>\n     * [\n     *     {\n     *         \"a\" : \"a-val\",\n     *         \"b\" : \"b-val\"\n     *     },\n     *     {\n     *         \"a\" : \"a-val\",\n     *     }\n     * ]\n     * </pre>\n     *\n     * evaluating the path \"$[*].b\"\n     *\n     * If REQUIRE_PROPERTIES option is present PathNotFoundException is thrown.\n     * If REQUIRE_PROPERTIES option is not present [\"b-val\"] is returned.\n     */\n    REQUIRE_PROPERTIES\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/ParseContext.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URL;\n\n\n/**\n * Parses JSON as specified by the used {@link com.jayway.jsonpath.spi.json.JsonProvider}.\n */\npublic interface ParseContext {\n\n    DocumentContext parse(String json);\n\n    DocumentContext parse(Object json);\n\n    DocumentContext parse(InputStream json);\n\n    DocumentContext parse(InputStream json, String charset);\n\n    DocumentContext parse(File json) throws IOException;\n\n    DocumentContext parseUtf8(byte[] json);\n\n    @Deprecated\n    DocumentContext parse(URL json) throws IOException;\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/PathNotFoundException.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\npublic class PathNotFoundException extends InvalidPathException {\n\n    public PathNotFoundException() {\n    }\n\n    public PathNotFoundException(String message) {\n        super(message);\n    }\n\n    public PathNotFoundException(String message, Throwable cause) {\n        super(message, cause);\n    }\n\n    public PathNotFoundException(Throwable cause) {\n        super(cause);\n    }\n\n    @Override\n    public synchronized Throwable fillInStackTrace() {\n        return this;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/Predicate.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\nimport com.jayway.jsonpath.spi.mapper.MappingException;\n\n/**\n *\n */\npublic interface Predicate {\n\n    boolean apply(PredicateContext ctx);\n\n    public interface PredicateContext {\n\n        /**\n         * Returns the current item being evaluated by this predicate\n         * @return current document\n         */\n        Object item();\n\n        /**\n         * Returns the current item being evaluated by this predicate. It will be mapped\n         * to the provided class\n         * @return current document\n         */\n        <T> T item(Class<T> clazz) throws MappingException;\n\n        /**\n         * Returns the root document (the complete JSON)\n         * @return root document\n         */\n        Object root();\n\n        /**\n         * Configuration to use when evaluating\n         * @return configuration\n         */\n        Configuration configuration();\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/ReadContext.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\npublic interface ReadContext {\n\n    /**\n     * Returns the configuration used for reading\n     *\n     * @return an immutable configuration\n     */\n    Configuration configuration();\n\n    /**\n     * Returns the JSON model that this context is operating on\n     *\n     * @return json model\n     */\n    <T> T json();\n\n    /**\n     * Returns the JSON model that this context is operating on as a JSON string\n     *\n     * @return json model as string\n     */\n    String jsonString();\n\n    /**\n     * Reads the given path from this context\n     *\n     * @param path    path to read\n     * @param filters filters\n     * @param <T>\n     * @return result\n     */\n    <T> T read(String path, Predicate... filters);\n\n    /**\n     * Reads the given path from this context\n     *\n     * @param path    path to read\n     * @param type    expected return type (will try to map)\n     * @param filters filters\n     * @param <T>\n     * @return result\n     */\n    <T> T read(String path, Class<T> type, Predicate... filters);\n\n    /**\n     * Reads the given path from this context\n     *\n     * @param path path to apply\n     * @param <T>\n     * @return result\n     */\n    <T> T read(JsonPath path);\n\n    /**\n     * Reads the given path from this context\n     *\n     * @param path path to apply\n     * @param type    expected return type (will try to map)\n     * @param <T>\n     * @return result\n     */\n    <T> T read(JsonPath path, Class<T> type);\n\n    /**\n     * Reads the given path from this context\n     *\n     * Sample code to create a TypeRef\n     * <code>\n     *       TypeRef ref = new TypeRef<List<Integer>>() {};\n     * </code>\n     *\n     * @param path path to apply\n     * @param typeRef  expected return type (will try to map)\n     * @param <T>\n     * @return result\n     */\n    <T> T read(JsonPath path, TypeRef<T> typeRef);\n\n    /**\n     * Reads the given path from this context\n     *\n     * Sample code to create a TypeRef\n     * <code>\n     *       TypeRef ref = new TypeRef<List<Integer>>() {};\n     * </code>\n     *\n     * @param path path to apply\n     * @param typeRef  expected return type (will try to map)\n     * @param <T>\n     * @return result\n     */\n    <T> T read(String path, TypeRef<T> typeRef);\n\n    /**\n     * Stops evaluation when maxResults limit has been reached\n     * @param maxResults\n     * @return the read context\n     */\n    ReadContext limit(int maxResults);\n\n    /**\n     * Adds listener to the evaluation of this path\n     * @param listener listeners to add\n     * @return the read context\n     */\n    ReadContext withListeners(EvaluationListener... listener);\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/TypeRef.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\nimport java.lang.reflect.ParameterizedType;\nimport java.lang.reflect.Type;\n\n\n/**\n * Used to specify generic type information in {@link com.jayway.jsonpath.ReadContext}\n *\n * <code>\n *       TypeRef ref = new TypeRef<List<Integer>>() { };\n * </code>\n *\n * @param <T>\n */\npublic abstract class TypeRef<T> implements Comparable<TypeRef<T>> {\n    protected final Type type;\n    \n    protected TypeRef()\n    {\n        Type superClass = getClass().getGenericSuperclass();\n        if (superClass instanceof Class<?>) {\n            throw new IllegalArgumentException(\"No type info in TypeRef\");\n        }\n        type = ((ParameterizedType) superClass).getActualTypeArguments()[0];\n    }\n\n    public Type getType() { return type; }\n    \n    /**\n     * The only reason we define this method (and require implementation\n     * of <code>Comparable</code>) is to prevent constructing a\n     * reference without type information.\n     */\n    @Override\n    public int compareTo(TypeRef<T> o) {\n        return 0;\n    }\n}\n\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/ValueCompareException.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\npublic class ValueCompareException extends JsonPathException {\n\n    public ValueCompareException() {\n    }\n\n    /**\n     * Construct the exception with message capturing the classes for two objects.\n     *\n     * @param left first object\n     * @param right second object\n     */\n    public ValueCompareException(final Object left, final Object right) {\n        super(String.format(\"Can not compare a %1s with a %2s\", left.getClass().getName(), right.getClass().getName()));\n    }\n\n    public ValueCompareException(String message) {\n        super(message);\n    }\n\n    public ValueCompareException(String message, Throwable cause) {\n        super(message, cause);\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/WriteContext.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath;\n\npublic interface WriteContext {\n\n    /**\n     * Returns the configuration used for reading\n     *\n     * @return an immutable configuration\n     */\n    Configuration configuration();\n\n    /**\n     * Returns the JSON model that this context is operating on\n     *\n     * @return json model\n     */\n    <T> T json();\n\n    /**\n     * Returns the JSON model that this context is operating on as a JSON string\n     *\n     * @return json model as string\n     */\n    String jsonString();\n\n    /**\n     * Set the value a the given path\n     *\n     * @param path      path to set\n     * @param newValue  new value\n     * @param filters   filters\n     * @return a document context\n     */\n    DocumentContext set(String path, Object newValue, Predicate... filters);\n\n    /**\n     * Set the value a the given path\n     *\n     * @param path      path to set\n     * @param newValue  new value\n     * @return a document context\n     */\n    DocumentContext set(JsonPath path, Object newValue);\n\n    /**\n     * Replaces the value on the given path with the result of the {@link MapFunction}.\n     *\n     * @param path           path to be converted set\n     * @param mapFunction    Converter object to be invoked\n     * @param filters        filters\n     * @return a document context\n     */\n    DocumentContext map(String path, MapFunction mapFunction, Predicate... filters);\n\n    /**\n     * Replaces the value on the given path with the result of the {@link MapFunction}.\n     *\n     * @param path           path to be converted set\n     * @param mapFunction    Converter object to be invoked (or lambda:))\n     * @return a document context\n     */\n    DocumentContext map(JsonPath path, MapFunction mapFunction);\n\n    /**\n     * Deletes the given path\n     *\n     * @param path    path to delete\n     * @param filters filters\n     * @return a document context\n     */\n    DocumentContext delete(String path, Predicate... filters);\n\n    /**\n     * Deletes the given path\n     *\n     * @param path    path to delete\n     * @return a document context\n     */\n    DocumentContext delete(JsonPath path);\n\n    /**\n     * Add value to array\n     *\n     * <pre>\n     * <code>\n     * List<Integer> array = new ArrayList<Integer>(){{\n     *      add(0);\n     *      add(1);\n     * }};\n     *\n     * JsonPath.parse(array).add(\"$\", 2);\n     *\n     * assertThat(array).containsExactly(0,1,2);\n     * </code>\n     * </pre>\n     *\n     * @param path    path to array\n     * @param value   value to add\n     * @param filters filters\n     * @return a document context\n     */\n    DocumentContext add(String path, Object value, Predicate... filters);\n\n    /**\n     * Add value to array at the given path\n     *\n     * @param path    path to array\n     * @param value   value to add\n     * @return a document context\n     */\n    DocumentContext add(JsonPath path, Object value);\n\n    /**\n     * Add or update the key with a the given value at the given path\n     *\n     * @param path    path to object\n     * @param key     key to add\n     * @param value   value of key\n     * @param filters filters\n     * @return a document context\n     */\n    DocumentContext put(String path, String key, Object value, Predicate... filters);\n\n    /**\n     * Add or update the key with a the given value at the given path\n     *\n     * @param path    path to array\n     * @param key     key to add\n     * @param value   value of key\n     * @return a document context\n     */\n    DocumentContext put(JsonPath path, String key, Object value);\n\n    /**\n     * Renames the last key element of a given path.\n     * @param path          The path to the old key. Should be resolved to a map\n     *                      or an array including map items.\n     * @param oldKeyName    The old key name.\n     * @param newKeyName    The new key name.\n     * @param filters       filters.\n     * @return a document content.\n     */\n    DocumentContext renameKey(String path, String oldKeyName, String newKeyName, Predicate... filters);\n\n    /**\n     * Renames the last key element of a given path.\n     * @param path          The path to the old key. Should be resolved to a map\n     *                      or an array including map items.\n     * @param oldKeyName    The old key name.\n     * @param newKeyName    The new key name.\n     * @return a document content.\n     */\n    DocumentContext renameKey(JsonPath path, String oldKeyName, String newKeyName);\n}"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java",
    "content": "package com.jayway.jsonpath.internal;\n\nimport com.jayway.jsonpath.InvalidPathException;\n\npublic class CharacterIndex {\n\n    private static final char OPEN_PARENTHESIS = '(';\n    private static final char CLOSE_PARENTHESIS = ')';\n    private static final char CLOSE_SQUARE_BRACKET = ']';\n    private static final char SPACE = ' ';\n    private static final char ESCAPE = '\\\\';\n    private static final char SINGLE_QUOTE = '\\'';\n    private static final char DOUBLE_QUOTE = '\"';\n    private static final char MINUS = '-';\n    private static final char PERIOD = '.';\n    private static final char REGEX = '/';\n\n    //workaround for issue: https://github.com/json-path/JsonPath/issues/590\n    private static final char SCI_E = 'E';\n    private static final char SCI_e = 'e';\n\n    private final CharSequence charSequence;\n    private int position;\n    private int endPosition;\n\n    public CharacterIndex(CharSequence charSequence) {\n        this.charSequence = charSequence;\n        this.position = 0;\n        this.endPosition = charSequence.length() - 1;\n    }\n\n    public int length() {\n        return endPosition + 1;\n    }\n\n    public char charAt(int idx) {\n        return charSequence.charAt(idx);\n    }\n\n    public char currentChar() {\n        return charSequence.charAt(position);\n    }\n\n    public boolean currentCharIs(char c) {\n        return (charSequence.charAt(position) == c);\n    }\n\n    public boolean lastCharIs(char c) {\n      return charSequence.charAt(endPosition) == c;\n    }\n\n    public boolean nextCharIs(char c) {\n        return inBounds(position + 1) && (charSequence.charAt(position + 1) == c);\n    }\n\n    public int incrementPosition(int charCount) {\n        return setPosition(position + charCount);\n    }\n\n    public int decrementEndPosition(int charCount) {\n        return setEndPosition(endPosition - charCount);\n    }\n\n    public int setPosition(int newPosition) {\n        //position = min(newPosition, charSequence.length() - 1);\n        position = newPosition;\n        return position;\n    }\n\n    private int setEndPosition(int newPosition) {\n        endPosition = newPosition;\n        return endPosition;\n    }\n\n    public int position(){\n        return position;\n    }\n\n    public int indexOfClosingSquareBracket(int startPosition) {\n        int readPosition = startPosition;\n        while (inBounds(readPosition)) {\n            if(charAt(readPosition) == CLOSE_SQUARE_BRACKET){\n                return readPosition;\n            }\n            readPosition++;\n        }\n        return -1;\n    }\n\n    public int indexOfMatchingCloseChar(int startPosition, char openChar, char closeChar, boolean skipStrings, boolean skipRegex) {\n        if(charAt(startPosition) != openChar){\n            throw new InvalidPathException(\"Expected \" + openChar + \" but found \" + charAt(startPosition));\n        }\n\n        int opened = 1;\n        int readPosition = startPosition + 1;\n        while (inBounds(readPosition)) {\n            if (skipStrings) {\n                char quoteChar = charAt(readPosition);\n                if (quoteChar == SINGLE_QUOTE || quoteChar == DOUBLE_QUOTE){\n                    readPosition = nextIndexOfUnescaped(readPosition, quoteChar);\n                    if(readPosition == -1){\n                        throw new InvalidPathException(\"Could not find matching close quote for \" + quoteChar + \" when parsing : \" + charSequence);\n                    }\n                    readPosition++;\n                }\n            }\n            if (skipRegex) {\n                if (charAt(readPosition) == REGEX) {\n                    readPosition = nextIndexOfUnescaped(readPosition, REGEX);\n                    if(readPosition == -1){\n                        throw new InvalidPathException(\"Could not find matching close for \" + REGEX + \" when parsing regex in : \" + charSequence);\n                    }\n                    readPosition++;\n                }\n            }\n            if (charAt(readPosition) == openChar) {\n                opened++;\n            }\n            if (charAt(readPosition) == closeChar) {\n                opened--;\n                if (opened == 0) {\n                    return readPosition;\n                }\n            }\n            readPosition++;\n        }\n        return -1;\n    }\n\n    public int indexOfClosingBracket(int startPosition, boolean skipStrings, boolean skipRegex) {\n        return indexOfMatchingCloseChar(startPosition, OPEN_PARENTHESIS, CLOSE_PARENTHESIS, skipStrings, skipRegex);\n    }\n\n    public int indexOfNextSignificantChar(char c) {\n        return indexOfNextSignificantChar(position, c);\n    }\n\n    public int indexOfNextSignificantChar(int startPosition, char c) {\n        int readPosition = startPosition + 1;\n        while (!isOutOfBounds(readPosition) && charAt(readPosition) == SPACE) {\n            readPosition++;\n        }\n        if (charAt(readPosition) == c) {\n            return readPosition;\n        } else {\n            return -1;\n        }\n    }\n\n    public int nextIndexOf(char c) {\n        return nextIndexOf(position + 1, c);\n    }\n\n    public int nextIndexOf(int startPosition, char c) {\n        int readPosition = startPosition;\n        while (!isOutOfBounds(readPosition)) {\n            if (charAt(readPosition) == c) {\n                return readPosition;\n            }\n            readPosition++;\n        }\n        return -1;\n    }\n\n    public int nextIndexOfUnescaped(char c) {\n        return nextIndexOfUnescaped(position, c);\n    }\n\n    public int nextIndexOfUnescaped(int startPosition, char c) {\n\n        int readPosition = startPosition + 1;\n        boolean inEscape = false;\n        while (!isOutOfBounds(readPosition)) {\n            if(inEscape){\n                inEscape = false;\n            } else if('\\\\' == charAt(readPosition)){\n                inEscape = true;\n            } else if (c == charAt(readPosition)){\n                return readPosition;\n            }\n            readPosition ++;\n        }\n        return -1;\n    }\n\n    public char charAtOr(int postition, char defaultChar){\n        if(!inBounds(postition)) return defaultChar;\n        else return charAt(postition);\n    }\n\n    public boolean nextSignificantCharIs(int startPosition, char c) {\n        int readPosition = startPosition + 1;\n        while (!isOutOfBounds(readPosition) && charAt(readPosition) == SPACE) {\n            readPosition++;\n        }\n        return !isOutOfBounds(readPosition) && charAt(readPosition) == c;\n    }\n\n    public boolean nextSignificantCharIs(char c) {\n        return nextSignificantCharIs(position, c);\n    }\n\n    public char nextSignificantChar() {\n        return nextSignificantChar(position);\n    }\n\n    public char nextSignificantChar(int startPosition) {\n        int readPosition = startPosition + 1;\n        while (!isOutOfBounds(readPosition) && charAt(readPosition) == SPACE) {\n            readPosition++;\n        }\n        if (!isOutOfBounds(readPosition)) {\n            return charAt(readPosition);\n        } else {\n            return ' ';\n        }\n    }\n\n    public void readSignificantChar(char c) {\n        if (skipBlanks().currentChar() != c) {\n            throw new InvalidPathException(String.format(\"Expected character: %c\", c));\n        }\n        incrementPosition(1);\n    }\n\n    public boolean hasSignificantSubSequence(CharSequence s) {\n        skipBlanks();\n        if (! inBounds(position + s.length() - 1)) {\n            return false;\n        }\n        if (! subSequence(position, position + s.length()).equals(s)) {\n            return false;\n        }\n\n        incrementPosition(s.length());\n        return true;\n    }\n\n    public int indexOfPreviousSignificantChar(int startPosition){\n        int readPosition = startPosition - 1;\n        while (!isOutOfBounds(readPosition) && charAt(readPosition) == SPACE) {\n            readPosition--;\n        }\n        if (!isOutOfBounds(readPosition)) {\n            return readPosition;\n        } else {\n            return -1;\n        }\n    }\n\n    public int indexOfPreviousSignificantChar(){\n        return indexOfPreviousSignificantChar(position);\n    }\n\n    public char previousSignificantChar(int startPosition) {\n        int previousSignificantCharIndex = indexOfPreviousSignificantChar(startPosition);\n        if(previousSignificantCharIndex == -1) return ' ';\n        else return charAt(previousSignificantCharIndex);\n    }\n\n    public char previousSignificantChar() {\n        return previousSignificantChar(position);\n    }\n\n    public boolean currentIsTail() {\n        return position >= endPosition;\n    }\n\n    public boolean hasMoreCharacters() {\n        return inBounds(position + 1);\n    }\n\n    public boolean inBounds(int idx) {\n        return (idx >= 0) && (idx <= endPosition);\n    }\n    public boolean inBounds() {\n        return inBounds(position);\n    }\n\n    public boolean isOutOfBounds(int idx) {\n        return !inBounds(idx);\n    }\n\n    public CharSequence subSequence(int start, int end) {\n        return charSequence.subSequence(start, end);\n    }\n\n    public CharSequence charSequence() {\n        return charSequence;\n    }\n\n    @Override\n    public String toString() {\n        return charSequence.toString();\n    }\n\n    public boolean isNumberCharacter(int readPosition) {\n        char c = charAt(readPosition);\n        //workaround for issue: https://github.com/json-path/JsonPath/issues/590\n        return Character.isDigit(c) || c == MINUS  || c == PERIOD || c == SCI_E || c == SCI_e;\n    }\n\n    public CharacterIndex skipBlanks() {\n        while (inBounds() && position < endPosition  && currentChar() == SPACE){\n            incrementPosition(1);\n        }\n        return this;\n    }\n\n    private CharacterIndex skipBlanksAtEnd() {\n        while (inBounds() && position < endPosition && lastCharIs(SPACE)){\n            decrementEndPosition(1);\n        }\n        return this;\n    }\n\n    public CharacterIndex trim() {\n        skipBlanks();\n        skipBlanksAtEnd();\n        return this;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/DefaultsImpl.java",
    "content": "package com.jayway.jsonpath.internal;\n\nimport com.jayway.jsonpath.Configuration.Defaults;\nimport com.jayway.jsonpath.Option;\nimport com.jayway.jsonpath.spi.json.JsonProvider;\nimport com.jayway.jsonpath.spi.json.JsonSmartJsonProvider;\nimport com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.MappingProvider;\n\nimport java.util.EnumSet;\nimport java.util.Set;\n\npublic final class DefaultsImpl implements Defaults {\n\n  public static final DefaultsImpl INSTANCE = new DefaultsImpl();\n\n  private final MappingProvider mappingProvider = new JsonSmartMappingProvider();\n\n  @Override\n  public JsonProvider jsonProvider() {\n    return new JsonSmartJsonProvider();\n  }\n\n  @Override\n  public Set<Option> options() {\n    return EnumSet.noneOf(Option.class);\n  }\n\n  @Override\n  public MappingProvider mappingProvider() {\n    return mappingProvider;\n  }\n\n  private DefaultsImpl() {\n  }\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/EvaluationAbortException.java",
    "content": "package com.jayway.jsonpath.internal;\n\npublic class EvaluationAbortException extends RuntimeException {\n\n  private static final long serialVersionUID = 4419305302960432348L;\n\n  // this is just a marker exception to abort evaluation, we don't care about\n  // the stack\n  @Override\n  public Throwable fillInStackTrace() {\n    return this;\n  }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/EvaluationContext.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal;\n\nimport com.jayway.jsonpath.Configuration;\n\nimport java.util.Collection;\nimport java.util.List;\n\npublic interface EvaluationContext {\n\n    /**\n     *\n     * @return the configuration used for this evaluation\n     */\n    Configuration configuration();\n\n    /**\n     * The json document that is evaluated\n     *\n     * @return the document\n     */\n    Object rootDocument();\n\n    /**\n     * This method does not adhere to configuration settings. It will return a single object (not wrapped in a List) even if the\n     * configuration contains the {@link com.jayway.jsonpath.Option#ALWAYS_RETURN_LIST}\n     *\n     * @param <T> expected return type\n     * @return evaluation result\n     */\n    <T> T getValue();\n\n    /**\n     * See {@link com.jayway.jsonpath.internal.EvaluationContext#getValue()}\n     *\n     * @param unwrap tells th underlying json provider if primitives should be unwrapped\n     * @param <T> expected return type\n     * @return evaluation result\n     */\n    <T> T getValue(boolean unwrap);\n\n\n    /**\n     * Returns the list of formalized paths that represent the result of the evaluation\n     * @param <T>\n     * @return list of paths\n     */\n    <T> T getPath();\n\n\n    /**\n     * Convenience method to get list of hits as String path representations\n     *\n     * @return list of path representations\n     */\n    List<String> getPathList();\n\n    Collection<PathRef> updateOperations();\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/JsonContext.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.DocumentContext;\nimport com.jayway.jsonpath.EvaluationListener;\nimport com.jayway.jsonpath.JsonPath;\nimport com.jayway.jsonpath.MapFunction;\nimport com.jayway.jsonpath.Option;\nimport com.jayway.jsonpath.Predicate;\nimport com.jayway.jsonpath.ReadContext;\nimport com.jayway.jsonpath.TypeRef;\nimport com.jayway.jsonpath.spi.cache.Cache;\nimport com.jayway.jsonpath.spi.cache.CacheProvider;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static com.jayway.jsonpath.JsonPath.compile;\nimport static com.jayway.jsonpath.internal.Utils.notEmpty;\nimport static com.jayway.jsonpath.internal.Utils.notNull;\n\npublic class JsonContext implements DocumentContext {\n\n    private static final Logger logger = LoggerFactory.getLogger(JsonContext.class);\n\n    private final Configuration configuration;\n    private final Object json;\n\n    JsonContext(Object json, Configuration configuration) {\n        notNull(json, \"json can not be null\");\n        notNull(configuration, \"configuration can not be null\");\n        this.configuration = configuration;\n        this.json = json;\n    }\n\n\n    @Override\n    public Configuration configuration() {\n        return configuration;\n    }\n\n    //------------------------------------------------\n    //\n    // ReadContext impl\n    //\n    //------------------------------------------------\n    @Override\n    public Object json() {\n        return json;\n    }\n\n    @Override\n    public String jsonString() {\n        return configuration.jsonProvider().toJson(json);\n    }\n\n    @Override\n    public <T> T read(String path, Predicate... filters) {\n        notEmpty(path, \"path can not be null or empty\");\n        return read(pathFromCache(path, filters));\n    }\n\n    @Override\n    public <T> T read(String path, Class<T> type, Predicate... filters) {\n        return convert(read(path, filters), type, configuration);\n    }\n\n    @Override\n    public <T> T read(JsonPath path) {\n        notNull(path, \"path can not be null\");\n        return path.read(json, configuration);\n    }\n\n    @Override\n    public <T> T read(JsonPath path, Class<T> type) {\n        return convert(read(path), type, configuration);\n    }\n\n    @Override\n    public <T> T read(JsonPath path, TypeRef<T> type) {\n        return convert(read(path), type, configuration);\n    }\n\n    @Override\n    public <T> T read(String path, TypeRef<T> type) {\n        return convert(read(path), type, configuration);\n    }\n\n    @Override\n    public ReadContext limit(int maxResults) {\n        return withListeners(new LimitingEvaluationListener(maxResults));\n    }\n\n    @Override\n    public ReadContext withListeners(EvaluationListener... listener) {\n        return new JsonContext(json, configuration.setEvaluationListeners(listener));\n    }\n\n    private <T> T convert(Object obj, Class<T> targetType, Configuration configuration) {\n        return configuration.mappingProvider().map(obj, targetType, configuration);\n    }\n\n    private <T> T convert(Object obj, TypeRef<T> targetType, Configuration configuration) {\n        return configuration.mappingProvider().map(obj, targetType, configuration);\n    }\n\n    @Override\n    public DocumentContext set(String path, Object newValue, Predicate... filters) {\n        return set(pathFromCache(path, filters), newValue);\n    }\n\n    @Override\n    public DocumentContext set(JsonPath path, Object newValue) {\n        List<String> modified = path.set(json, newValue, configuration.addOptions(Option.AS_PATH_LIST));\n        if (logger.isDebugEnabled()) {\n            for (String p : modified) {\n                logger.debug(\"Set path {} new value {}\", p, newValue);\n            }\n        }\n        return this;\n    }\n\n    @Override\n    public DocumentContext map(String path, MapFunction mapFunction, Predicate... filters) {\n        map(pathFromCache(path, filters), mapFunction);\n        return this;\n    }\n\n    @Override\n    public DocumentContext map(JsonPath path, MapFunction mapFunction) {\n        Object obj = path.map(json, mapFunction, configuration);\n        return obj==null ? null:this;\n    }\n\n    @Override\n    public DocumentContext delete(String path, Predicate... filters) {\n        return delete(pathFromCache(path, filters));\n    }\n\n    @Override\n    public DocumentContext delete(JsonPath path) {\n        List<String> modified = path.delete(json, configuration.addOptions(Option.AS_PATH_LIST));\n        if (logger.isDebugEnabled()) {\n            for (String p : modified) {\n                logger.debug(\"Delete path {}\", p);\n            }\n        }\n        return this;\n    }\n\n    @Override\n    public DocumentContext add(String path, Object value, Predicate... filters) {\n        return add(pathFromCache(path, filters), value);\n    }\n\n    @Override\n    public DocumentContext add(JsonPath path, Object value) {\n        List<String> modified = path.add(json, value, configuration.addOptions(Option.AS_PATH_LIST));\n        if (logger.isDebugEnabled()) {\n            for (String p : modified) {\n                logger.debug(\"Add path {} new value {}\", p, value);\n            }\n        }\n        return this;\n    }\n\n    @Override\n    public DocumentContext put(String path, String key, Object value, Predicate... filters) {\n        return put(pathFromCache(path, filters), key, value);\n    }\n\n    @Override\n    public DocumentContext renameKey(String path, String oldKeyName, String newKeyName, Predicate... filters) {\n        return renameKey(pathFromCache(path, filters), oldKeyName, newKeyName);\n    }\n\n    @Override\n    public DocumentContext renameKey(JsonPath path, String oldKeyName, String newKeyName) {\n        List<String> modified = path.renameKey(json, oldKeyName, newKeyName, configuration.addOptions(Option.AS_PATH_LIST));\n        if (logger.isDebugEnabled()) {\n            for (String p : modified) {\n                logger.debug(\"Rename path {} new value {}\", p, newKeyName);\n            }\n        }\n        return this;\n    }\n\n    @Override\n    public DocumentContext put(JsonPath path, String key, Object value) {\n        List<String> modified = path.put(json, key, value, configuration.addOptions(Option.AS_PATH_LIST));\n        if (logger.isDebugEnabled()) {\n            for (String p : modified) {\n                logger.debug(\"Put path {} key {} value {}\", p, key, value);\n            }\n        }\n        return this;\n    }\n\n    private JsonPath pathFromCache(String path, Predicate[] filters) {\n        Cache cache = CacheProvider.getCache();\n        String cacheKey = filters == null || filters.length == 0\n            ? path : Utils.concat(path, Arrays.toString(filters));\n        JsonPath jsonPath = cache.get(cacheKey);\n        if (jsonPath == null) {\n            jsonPath = compile(path, filters);\n            cache.put(cacheKey, jsonPath);\n        }\n        return jsonPath;\n    }\n\n    private final static class LimitingEvaluationListener implements EvaluationListener {\n        final int limit;\n\n        private LimitingEvaluationListener(int limit) {\n            this.limit = limit;\n        }\n\n        @Override\n        public EvaluationContinuation resultFound(FoundResult found) {\n            if (found.index() == limit - 1) {\n                return EvaluationContinuation.ABORT;\n            } else {\n                return EvaluationContinuation.CONTINUE;\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/JsonFormatter.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal;\n\npublic class JsonFormatter {\n\n    private static final String INDENT = \"   \";\n\n    private static final String NEW_LINE = System.getProperty(\"line.separator\");\n\n    private static final int MODE_SINGLE = 100;\n    private static final int MODE_DOUBLE = 101;\n    private static final int MODE_ESCAPE_SINGLE = 102;\n    private static final int MODE_ESCAPE_DOUBLE = 103;\n    private static final int MODE_BETWEEN = 104;\n\n    private static void appendIndent(StringBuilder sb, int count) {\n        for (; count > 0; --count) sb.append(INDENT);\n    }\n\n    public static String prettyPrint(String input) {\n\n        input = input.replaceAll(\"[\\\\r\\\\n]\", \"\");\n\n        StringBuilder output = new StringBuilder(input.length() * 2);\n        int mode = MODE_BETWEEN;\n        int depth = 0;\n\n        for (int i = 0; i < input.length(); ++i) {\n            char ch = input.charAt(i);\n\n            switch (mode) {\n                case MODE_BETWEEN:\n                    switch (ch) {\n                        case '{':\n                        case '[':\n                            output.append(ch);\n                            output.append(NEW_LINE);\n                            appendIndent(output, ++depth);\n                            break;\n                        case '}':\n                        case ']':\n                            output.append(NEW_LINE);\n                            appendIndent(output, --depth);\n                            output.append(ch);\n                            break;\n                        case ',':\n                            output.append(ch);\n                            output.append(NEW_LINE);\n                            appendIndent(output, depth);\n                            break;\n                        case ':':\n                            output.append(\" : \");\n                            break;\n                        case '\\'':\n                            output.append(ch);\n                            mode = MODE_SINGLE;\n                            break;\n                        case '\"':\n                            output.append(ch);\n                            mode = MODE_DOUBLE;\n                            break;\n                        case ' ':\n                            break;\n                        default:\n                            output.append(ch);\n                            break;\n                    }\n                    break;\n                case MODE_ESCAPE_SINGLE:\n                    output.append(ch);\n                    mode = MODE_SINGLE;\n                    break;\n                case MODE_ESCAPE_DOUBLE:\n                    output.append(ch);\n                    mode = MODE_DOUBLE;\n                    break;\n                case MODE_SINGLE:\n                    output.append(ch);\n                    switch (ch) {\n                        case '\\'':\n                            mode = MODE_BETWEEN;\n                            break;\n                        case '\\\\':\n                            mode = MODE_ESCAPE_SINGLE;\n                            break;\n                    }\n                    break;\n                case MODE_DOUBLE:\n                    output.append(ch);\n                    switch (ch) {\n                        case '\"':\n                            mode = MODE_BETWEEN;\n                            break;\n                        case '\\\\':\n                            mode = MODE_ESCAPE_DOUBLE;\n                            break;\n                    }\n                    break;\n            }\n        }\n        return output.toString();\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/ParseContextImpl.java",
    "content": "package com.jayway.jsonpath.internal;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.DocumentContext;\nimport com.jayway.jsonpath.ParseContext;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URL;\n\nimport static com.jayway.jsonpath.internal.Utils.notEmpty;\nimport static com.jayway.jsonpath.internal.Utils.notNull;\n\npublic class ParseContextImpl implements ParseContext {\n\n    private final Configuration configuration;\n\n    public ParseContextImpl() {\n        this(Configuration.defaultConfiguration());\n    }\n\n    public ParseContextImpl(Configuration configuration) {\n        this.configuration = configuration;\n    }\n\n    @Override\n    public DocumentContext parse(Object json) {\n        notNull(json, \"json object can not be null\");\n        return new JsonContext(json, configuration);\n    }\n\n    @Override\n    public DocumentContext parse(String json) {\n        notEmpty(json, \"json string can not be null or empty\");\n        Object obj = configuration.jsonProvider().parse(json);\n        return new JsonContext(obj, configuration);\n    }\n\n    @Override\n    public DocumentContext parseUtf8(byte[] json) {\n        notEmpty(json, \"json bytes can not be null or empty\");\n        Object obj = configuration.jsonProvider().parse(json);\n        return new JsonContext(obj, configuration);\n    }\n\n    @Override\n    public DocumentContext parse(InputStream json) {\n        return parse(json, \"UTF-8\");\n    }\n\n    @Override\n    public DocumentContext parse(InputStream json, String charset) {\n        notNull(json, \"json input stream can not be null\");\n        notNull(charset, \"charset can not be null\");\n        try {\n            Object obj = configuration.jsonProvider().parse(json, charset);\n            return new JsonContext(obj, configuration);\n        } finally {\n            Utils.closeQuietly(json);\n        }\n    }\n\n    @Override\n    public DocumentContext parse(File json) throws IOException {\n        notNull(json, \"json file can not be null\");\n        FileInputStream fis = null;\n        try {\n            fis = new FileInputStream(json);\n            return parse(fis);\n        } finally {\n            Utils.closeQuietly(fis);\n        }\n    }\n\n    @Override\n    @Deprecated\n    public DocumentContext parse(URL url) throws IOException {\n        notNull(url, \"url can not be null\");\n        InputStream fis = null;\n        try {\n            fis = url.openStream();\n            return parse(fis);\n        } finally {\n            Utils.closeQuietly(fis);\n        }\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/Path.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal;\n\nimport com.jayway.jsonpath.Configuration;\n\n/**\n *\n */\npublic interface Path {\n\n\n    /**\n     * Evaluates this path\n     *\n     * @param document the json document to apply the path on\n     * @param rootDocument the root json document that started this evaluation\n     * @param configuration configuration to use\n     * @return EvaluationContext containing results of evaluation\n     */\n    EvaluationContext evaluate(Object document, Object rootDocument, Configuration configuration);\n\n    /**\n     * Evaluates this path\n     *\n     * @param document the json document to apply the path on\n     * @param rootDocument the root json document that started this evaluation\n     * @param configuration configuration to use\n     * @param forUpdate is this a read or a write operation\n     * @return EvaluationContext containing results of evaluation\n     */\n    EvaluationContext evaluate(Object document, Object rootDocument, Configuration configuration, boolean forUpdate);\n\n    /**\n     *\n     * @return true id this path is definite\n     */\n    boolean isDefinite();\n\n    /**\n     *\n     * @return true id this path is a function\n     */\n    boolean isFunctionPath();\n\n    /**\n     *\n     * @return true id this path is starts with '$' and false if the path starts with '@'\n     */\n    boolean isRootPath();\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/PathRef.java",
    "content": "package com.jayway.jsonpath.internal;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.InvalidModificationException;\nimport com.jayway.jsonpath.MapFunction;\nimport com.jayway.jsonpath.PathNotFoundException;\nimport com.jayway.jsonpath.spi.json.JsonProvider;\n\nimport java.util.Collection;\n\npublic abstract class PathRef implements Comparable<PathRef>  {\n\n    public static final PathRef NO_OP = new PathRef(null){\n        @Override\n        public Object getAccessor() {\n            return null;\n        }\n\n        @Override\n        public void set(Object newVal, Configuration configuration) {}\n\n        @Override\n        public void convert(MapFunction mapFunction, Configuration configuration) {}\n\n        @Override\n        public void delete(Configuration configuration) {}\n\n        @Override\n        public void add(Object newVal, Configuration configuration) {}\n\n        @Override\n        public void put(String key, Object newVal, Configuration configuration) {}\n\n        @Override\n        public void renameKey(String oldKeyName, String newKeyName, Configuration configuration) {}\n\n    };\n\n    protected Object parent;\n\n\n    private PathRef(Object parent) {\n        this.parent = parent;\n    }\n\n    abstract Object getAccessor();\n\n    public abstract void set(Object newVal, Configuration configuration);\n\n    public abstract void convert(MapFunction mapFunction, Configuration configuration);\n\n    public abstract void delete(Configuration configuration);\n\n    public abstract void add(Object newVal, Configuration configuration);\n\n    public abstract void put(String key, Object newVal, Configuration configuration);\n\n    public abstract void renameKey(String oldKey,String newKeyName, Configuration configuration);\n\n    protected void renameInMap(Object targetMap, String oldKeyName, String newKeyName, Configuration configuration){\n        if(configuration.jsonProvider().isMap(targetMap)){\n            if(configuration.jsonProvider().getMapValue(targetMap, oldKeyName) == JsonProvider.UNDEFINED){\n                throw new PathNotFoundException(\"No results for Key \"+oldKeyName+\" found in map!\");\n            }\n            configuration.jsonProvider().setProperty(targetMap, newKeyName, configuration.jsonProvider().getMapValue(targetMap, oldKeyName));\n            configuration.jsonProvider().removeProperty(targetMap, oldKeyName);\n        } else {\n            throw new InvalidModificationException(\"Can only rename properties in a map\");\n        }\n    }\n\n    protected boolean targetInvalid(Object target){\n        return target == JsonProvider.UNDEFINED || target == null;\n    }\n\n    @Override\n    public int compareTo(PathRef o) {\n        return this.getAccessor().toString().compareTo(o.getAccessor().toString()) * -1;\n    }\n\n    public static PathRef create(Object obj, String property){\n        return new ObjectPropertyPathRef(obj, property);\n    }\n\n    public static PathRef create(Object obj, Collection<String> properties){\n        return new ObjectMultiPropertyPathRef(obj, properties);\n    }\n\n    public static PathRef create(Object array, int index){\n        return new ArrayIndexPathRef(array, index);\n    }\n\n    public static PathRef createRoot(Object root){\n        return new RootPathRef(root);\n    }\n\n    private static class RootPathRef extends PathRef {\n\n        private RootPathRef(Object parent) {\n            super(parent);\n        }\n\n        @Override\n        Object getAccessor() {\n            return \"$\";\n        }\n\n        @Override\n        public void set(Object newVal, Configuration configuration) {\n            throw new InvalidModificationException(\"Invalid set operation\");\n        }\n\n        public void convert(MapFunction mapFunction, Configuration configuration){\n            throw new InvalidModificationException(\"Invalid map operation\");\n        }\n\n        @Override\n        public void delete(Configuration configuration) {\n            throw new InvalidModificationException(\"Invalid delete operation\");\n        }\n\n        @Override\n        public void add(Object newVal, Configuration configuration) {\n            if(configuration.jsonProvider().isArray(parent)){\n                configuration.jsonProvider().setArrayIndex(parent, configuration.jsonProvider().length(parent), newVal);\n            } else {\n                throw new InvalidModificationException(\"Invalid add operation. $ is not an array\");\n            }\n        }\n\n        @Override\n        public void put(String key, Object newVal, Configuration configuration) {\n            if(configuration.jsonProvider().isMap(parent)){\n                configuration.jsonProvider().setProperty(parent, key, newVal);\n            } else {\n                throw new InvalidModificationException(\"Invalid put operation. $ is not a map\");\n            }\n        }\n\n        @Override\n        public void renameKey(String oldKeyName, String newKeyName, Configuration configuration) {\n            Object target = parent;\n            if(targetInvalid(target)){\n                return;\n            }\n            renameInMap(target, oldKeyName, newKeyName, configuration);\n        }\n\n    }\n\n    private static class ArrayIndexPathRef extends PathRef {\n\n        private int index;\n\n        private ArrayIndexPathRef(Object parent, int index) {\n            super(parent);\n            this.index = index;\n        }\n\n        public void set(Object newVal, Configuration configuration){\n            configuration.jsonProvider().setArrayIndex(parent, index, newVal);\n        }\n\n        public void convert(MapFunction mapFunction, Configuration configuration){\n            Object currentValue = configuration.jsonProvider().getArrayIndex(parent, index);\n            configuration.jsonProvider().setArrayIndex(parent, index, mapFunction.map(currentValue, configuration));\n        }\n\n        public void delete(Configuration configuration){\n            configuration.jsonProvider().removeProperty(parent, index);\n        }\n\n        public void add(Object value, Configuration configuration){\n            Object target = configuration.jsonProvider().getArrayIndex(parent, index);\n            if(targetInvalid(target)){\n                return;\n            }\n            if(configuration.jsonProvider().isArray(target)){\n                configuration.jsonProvider().setProperty(target, null, value);\n            } else {\n                throw new InvalidModificationException(\"Can only add to an array\");\n            }\n        }\n\n        public void put(String key, Object value, Configuration configuration){\n            Object target = configuration.jsonProvider().getArrayIndex(parent, index);\n            if(targetInvalid(target)){\n                return;\n            }\n            if(configuration.jsonProvider().isMap(target)){\n                configuration.jsonProvider().setProperty(target, key, value);\n            } else {\n                throw new InvalidModificationException(\"Can only add properties to a map\");\n            }\n        }\n\n        @Override\n        public void renameKey(String oldKeyName, String newKeyName, Configuration configuration) {\n            Object target = configuration.jsonProvider().getArrayIndex(parent, index);\n            if(targetInvalid(target)){\n                return;\n            }\n            renameInMap(target, oldKeyName, newKeyName, configuration);\n        }\n\n        @Override\n        public Object getAccessor() {\n            return index;\n        }\n\n        @Override\n        public int compareTo(PathRef o) {\n            if(o instanceof ArrayIndexPathRef){\n                ArrayIndexPathRef pf = (ArrayIndexPathRef) o;\n                return Integer.compare(pf.index, this.index);\n            }\n            return super.compareTo(o);\n        }\n    }\n\n    private static class ObjectPropertyPathRef extends PathRef {\n\n        private String property;\n\n        private ObjectPropertyPathRef(Object parent, String property) {\n            super(parent);\n            this.property = property;\n        }\n\n        public void set(Object newVal, Configuration configuration){\n            configuration.jsonProvider().setProperty(parent, property, newVal);\n        }\n\n        @Override\n        public void convert(MapFunction mapFunction, Configuration configuration) {\n            Object currentValue = configuration.jsonProvider().getMapValue(parent, property);\n            configuration.jsonProvider().setProperty(parent, property, mapFunction.map(currentValue, configuration));\n        }\n\n\n        public void delete(Configuration configuration){\n            configuration.jsonProvider().removeProperty(parent, property);\n        }\n\n        public void add(Object value, Configuration configuration){\n            Object target = configuration.jsonProvider().getMapValue(parent, property);\n            if(targetInvalid(target)){\n                return;\n            }\n            if(configuration.jsonProvider().isArray(target)){\n                configuration.jsonProvider().setArrayIndex(target, configuration.jsonProvider().length(target), value);\n            } else {\n                throw new InvalidModificationException(\"Can only add to an array\");\n            }\n        }\n\n        public void put(String key, Object value, Configuration configuration){\n            Object target = configuration.jsonProvider().getMapValue(parent, property);\n            if(targetInvalid(target)){\n                return;\n            }\n            if(configuration.jsonProvider().isMap(target)){\n                configuration.jsonProvider().setProperty(target, key, value);\n            } else {\n                throw new InvalidModificationException(\"Can only add properties to a map\");\n            }\n        }\n\n        @Override\n        public void renameKey(String oldKeyName, String newKeyName, Configuration configuration) {\n            Object target = configuration.jsonProvider().getMapValue(parent, property);\n            if(targetInvalid(target)){\n                return;\n            }\n            renameInMap(target, oldKeyName, newKeyName, configuration);\n        }\n\n        @Override\n        public Object getAccessor() {\n            return property;\n        }\n    }\n\n    private static class ObjectMultiPropertyPathRef extends PathRef {\n\n        private Collection<String> properties;\n\n        private ObjectMultiPropertyPathRef(Object parent, Collection<String> properties) {\n            super(parent);\n            this.properties = properties;\n        }\n\n        public void set(Object newVal, Configuration configuration){\n            for (String property : properties) {\n                configuration.jsonProvider().setProperty(parent, property, newVal);\n            }\n        }\n        public void convert(MapFunction mapFunction, Configuration configuration) {\n            for (String property : properties) {\n                Object currentValue = configuration.jsonProvider().getMapValue(parent, property);\n                if (currentValue != JsonProvider.UNDEFINED) {\n                    configuration.jsonProvider().setProperty(parent, property, mapFunction.map(currentValue, configuration));\n                }\n            }\n        }\n\n        public void delete(Configuration configuration){\n            for (String property : properties) {\n                configuration.jsonProvider().removeProperty(parent, property);\n            }\n        }\n\n        @Override\n        public void add(Object newVal, Configuration configuration) {\n            throw new InvalidModificationException(\"Add can not be performed to multiple properties\");\n        }\n\n        @Override\n        public void put(String key, Object newVal, Configuration configuration) {\n            throw new InvalidModificationException(\"Put can not be performed to multiple properties\");\n        }\n\n        @Override\n        public void renameKey(String oldKeyName, String newKeyName, Configuration configuration) {\n            throw new InvalidModificationException(\"Rename can not be performed to multiple properties\");\n        }\n\n        @Override\n        public Object getAccessor() {\n            return Utils.join(\"&&\", properties);\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/Utils.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal;\n\nimport com.jayway.jsonpath.JsonPathException;\n\nimport java.io.Closeable;\nimport java.io.IOException;\nimport java.io.StringWriter;\nimport java.util.Iterator;\n\npublic final class Utils {\n\n    // accept a collection of objects, since all objects have toString()\n    public static String join(String delimiter, String wrap, Iterable<?> objs) {\n        Iterator<?> iter = objs.iterator();\n        if (!iter.hasNext()) {\n            return \"\";\n        }\n        StringBuilder buffer = new StringBuilder();\n        buffer.append(wrap).append(iter.next()).append(wrap);\n        while (iter.hasNext()) {\n            buffer.append(delimiter).append(wrap).append(iter.next()).append(wrap);\n        }\n        return buffer.toString();\n    }\n\n    // accept a collection of objects, since all objects have toString()\n    public static String join(String delimiter, Iterable<?> objs) {\n        return join(delimiter, \"\", objs);\n    }\n\n    public static String concat(CharSequence... strings) {\n        if (strings.length == 0) {\n            return \"\";\n        }\n        if (strings.length == 1) {\n            return strings[0].toString();\n        }\n        int length = 0;\n        // -1 = no result, -2 = multiple results\n        int indexOfSingleNonEmptyString = -1;\n        for (int i = 0; i < strings.length; i++) {\n            CharSequence charSequence = strings[i];\n            int len = charSequence.length();\n            length += len;\n            if (indexOfSingleNonEmptyString != -2 && len > 0) {\n                if (indexOfSingleNonEmptyString == -1) {\n                    indexOfSingleNonEmptyString = i;\n                } else {\n                    indexOfSingleNonEmptyString = -2;\n                }\n            }\n        }\n        if (length == 0) {\n            return \"\";\n        }\n        if (indexOfSingleNonEmptyString > 0) {\n            return strings[indexOfSingleNonEmptyString].toString();\n        }\n        StringBuilder sb = new StringBuilder(length);\n        for (CharSequence charSequence : strings) {\n            sb.append(charSequence);\n        }\n        return sb.toString();\n\n    }\n\n    //---------------------------------------------------------\n    //\n    // IO\n    //\n    //---------------------------------------------------------\n\n    public static void closeQuietly(Closeable closeable) {\n        try {\n            if (closeable != null) {\n                closeable.close();\n            }\n        } catch (IOException ignore) {\n        }\n    }\n\n    public static String escape(String str, boolean escapeSingleQuote) {\n        if (str == null) {\n            return null;\n        }\n        int len = str.length();\n        StringWriter writer = new StringWriter(len * 2);\n\n        for (int i = 0; i < len; i++) {\n            char ch = str.charAt(i);\n\n            // handle unicode\n            if (ch > 0xfff) {\n                writer.write(\"\\\\u\" + hex(ch));\n            } else if (ch > 0xff) {\n                writer.write(\"\\\\u0\" + hex(ch));\n            } else if (ch > 0x7f) {\n                writer.write(\"\\\\u00\" + hex(ch));\n            } else if (ch < 32) {\n                switch (ch) {\n                    case '\\b':\n                        writer.write('\\\\');\n                        writer.write('b');\n                        break;\n                    case '\\n':\n                        writer.write('\\\\');\n                        writer.write('n');\n                        break;\n                    case '\\t':\n                        writer.write('\\\\');\n                        writer.write('t');\n                        break;\n                    case '\\f':\n                        writer.write('\\\\');\n                        writer.write('f');\n                        break;\n                    case '\\r':\n                        writer.write('\\\\');\n                        writer.write('r');\n                        break;\n                    default :\n                        if (ch > 0xf) {\n                            writer.write(\"\\\\u00\" + hex(ch));\n                        } else {\n                            writer.write(\"\\\\u000\" + hex(ch));\n                        }\n                        break;\n                }\n            } else {\n                switch (ch) {\n                    case '\\'':\n                        if (escapeSingleQuote) {\n                            writer.write('\\\\');\n                        }\n                        writer.write('\\'');\n                        break;\n                    case '\"':\n                        writer.write('\\\\');\n                        writer.write('\"');\n                        break;\n                    case '\\\\':\n                        writer.write('\\\\');\n                        writer.write('\\\\');\n                        break;\n                    case '/':\n                        writer.write('\\\\');\n                        writer.write('/');\n                        break;\n                    default :\n                        writer.write(ch);\n                        break;\n                }\n            }\n        }\n        return writer.toString();\n    }\n\n    public static String unescape(String str) {\n        if (str == null) {\n            return null;\n        }\n        int len = str.length();\n        StringWriter writer = new StringWriter(len);\n        StringBuilder unicode = new StringBuilder(4);\n        boolean hadSlash = false;\n        boolean inUnicode = false;\n        for (int i = 0; i < len; i++) {\n            char ch = str.charAt(i);\n            if (inUnicode) {\n                unicode.append(ch);\n                if (unicode.length() == 4) {\n                    try {\n                        int value = Integer.parseInt(unicode.toString(), 16);\n                        writer.write((char) value);\n                        unicode.setLength(0);\n                        inUnicode = false;\n                        hadSlash = false;\n                    } catch (NumberFormatException nfe) {\n                        throw new JsonPathException(\"Unable to parse unicode value: \" + unicode, nfe);\n                    }\n                }\n                continue;\n            }\n            if (hadSlash) {\n                hadSlash = false;\n                switch (ch) {\n                    case '\\\\':\n                        writer.write('\\\\');\n                        break;\n                    case '\\'':\n                        writer.write('\\'');\n                        break;\n                    case '\\\"':\n                        writer.write('\"');\n                        break;\n                    case 'r':\n                        writer.write('\\r');\n                        break;\n                    case 'f':\n                        writer.write('\\f');\n                        break;\n                    case 't':\n                        writer.write('\\t');\n                        break;\n                    case 'n':\n                        writer.write('\\n');\n                        break;\n                    case 'b':\n                        writer.write('\\b');\n                        break;\n                    case 'u':\n                    {\n                        inUnicode = true;\n                        break;\n                    }\n                    default :\n                        writer.write(ch);\n                        break;\n                }\n                continue;\n            } else if (ch == '\\\\') {\n                hadSlash = true;\n                continue;\n            }\n            writer.write(ch);\n        }\n        if (hadSlash) {\n            writer.write('\\\\');\n        }\n        return writer.toString();\n    }\n\n    /**\n     * Returns an upper case hexadecimal <code>String</code> for the given\n     * character.\n     *\n     * @param ch The character to map.\n     * @return An upper case hexadecimal <code>String</code>\n     */\n    public static String hex(char ch) {\n        return Integer.toHexString(ch).toUpperCase();\n    }\n\n    /**\n     * <p>Checks if a CharSequence is empty (\"\") or null.</p>\n     * <p/>\n     * <pre>\n     * StringUtils.isEmpty(null)      = true\n     * StringUtils.isEmpty(\"\")        = true\n     * StringUtils.isEmpty(\" \")       = false\n     * StringUtils.isEmpty(\"bob\")     = false\n     * StringUtils.isEmpty(\"  bob  \") = false\n     * </pre>\n     * <p/>\n     * <p>NOTE: This method changed in Lang version 2.0.\n     * It no longer trims the CharSequence.\n     * That functionality is available in isBlank().</p>\n     *\n     * @param cs the CharSequence to check, may be null\n     * @return {@code true} if the CharSequence is empty or null\n     * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)\n     */\n    public static boolean isEmpty(CharSequence cs) {\n        return cs == null || cs.length() == 0;\n    }\n\n    /**\n     * Used by the indexOf(CharSequence methods) as a green implementation of indexOf.\n     *\n     * @param cs         the {@code CharSequence} to be processed\n     * @param searchChar the {@code CharSequence} to be searched for\n     * @param start      the start index\n     * @return the index where the search sequence was found\n     */\n    static int indexOf(CharSequence cs, CharSequence searchChar, int start) {\n        return cs.toString().indexOf(searchChar.toString(), start);\n    }\n\n\n\n    //---------------------------------------------------------\n    //\n    // Validators\n    //\n    //---------------------------------------------------------\n\n    /**\n     * <p>Validate that the specified argument is not {@code null};\n     * otherwise throwing an exception with the specified message.\n     * <p/>\n     * <pre>Validate.notNull(myObject, \"The object must not be null\");</pre>\n     *\n     * @param <T>     the object type\n     * @param object  the object to check\n     * @param message the {@link String#format(String, Object...)} exception message if invalid, not null\n     * @return the validated object (never {@code null} for method chaining)\n     * @throws NullPointerException if the object is {@code null}\n     */\n    public static <T> T notNull(T object, String message) {\n        if (object == null) {\n            throw new IllegalArgumentException(message);\n        }\n        return object;\n    }\n\n    /**\n     * <p>Validate that the specified argument is not {@code null};\n     * otherwise throwing an exception with the specified message.\n     * <p/>\n     * <pre>Validate.notNull(myObject, \"The object must not be null\");</pre>\n     *\n     * @param <T>     the object type\n     * @param object  the object to check\n     * @param message the {@link String#format(String, Object...)} exception message if invalid, not null\n     * @param values  the optional values for the formatted exception message\n     * @return the validated object (never {@code null} for method chaining)\n     * @throws NullPointerException if the object is {@code null}\n     */\n    public static <T> T notNull(T object, String message, Object... values) {\n        if (object == null) {\n            throw new IllegalArgumentException(String.format(message, values));\n        }\n        return object;\n    }\n\n    /**\n     * <p>Validate that the argument condition is {@code true}; otherwise\n     * throwing an exception with the specified message. This method is useful when\n     * validating according to an arbitrary boolean expression, such as validating a\n     * primitive number or using your own custom validation expression.</p>\n     * <p/>\n     * <pre>Validate.isTrue(i > 0.0, \"The value must be greater than zero: %d\", i);</pre>\n     * <p/>\n     * <p>For performance reasons, the long value is passed as a separate parameter and\n     * appended to the exception message only in the case of an error.</p>\n     *\n     * @param expression the boolean expression to check\n     * @param message\n     * @throws IllegalArgumentException if expression is {@code false}\n     */\n    public static void isTrue(boolean expression, String message) {\n        if (expression == false) {\n            throw new IllegalArgumentException(message);\n        }\n    }\n\n    /**\n     * Check if one and only one condition is true; otherwise\n     * throw an exception with the specified message.\n     *\n     * @param message     error describing message\n     * @param expressions the boolean expressions to check\n     * @throws IllegalArgumentException if zero or more than one expressions are true\n     */\n    public static void onlyOneIsTrue(final String message, final boolean... expressions) {\n        if (!onlyOneIsTrueNonThrow(expressions)) {\n            throw new IllegalArgumentException(message);\n        }\n    }\n\n    public static boolean onlyOneIsTrueNonThrow(final boolean... expressions) {\n        int count = 0;\n        for (final boolean expression : expressions) {\n            if (expression && ++count > 1) {\n                return false;\n            }\n        }\n        return 1 == count;\n    }\n\n    /**\n     * <p>Validate that the specified argument character sequence is\n     * neither {@code null} nor a length of zero (no characters);\n     * otherwise throwing an exception with the specified message.\n     * <p/>\n     * <pre>Validate.notEmpty(myString, \"The string must not be empty\");</pre>\n     *\n     * @param <T>     the character sequence type\n     * @param chars   the character sequence to check, validated not null by this method\n     * @param message the {@link String#format(String, Object...)} exception message if invalid, not null\n     * @return the validated character sequence (never {@code null} method for chaining)\n     * @throws NullPointerException     if the character sequence is {@code null}\n     * @throws IllegalArgumentException if the character sequence is empty\n     */\n    public static <T extends CharSequence> T notEmpty(T chars, String message) {\n        if (chars == null || chars.length() == 0) {\n            throw new IllegalArgumentException(message);\n        }\n        return chars;\n    }\n\n    /**\n     * <p>Validate that the specified argument character sequence is\n     * neither {@code null} nor a length of zero (no characters);\n     * otherwise throwing an exception with the specified message.\n     * <p/>\n     * <pre>Validate.notEmpty(myString, \"The string must not be empty\");</pre>\n     *\n     * @param bytes   the bytes to check, validated not null by this method\n     * @param message the {@link String#format(String, Object...)} exception message if invalid, not null\n     * @return the validated character sequence (never {@code null} method for chaining)\n     * @throws NullPointerException     if the character sequence is {@code null}\n     * @throws IllegalArgumentException if the character sequence is empty\n     */\n    public static byte[] notEmpty(byte[] bytes, String message) {\n        if (bytes == null || bytes.length == 0) {\n            throw new IllegalArgumentException(message);\n        }\n        return bytes;\n    }\n\n    /**\n     * <p>Validate that the specified argument character sequence is\n     * neither {@code null} nor a length of zero (no characters);\n     * otherwise throwing an exception with the specified message.\n     * <p/>\n     * <pre>Validate.notEmpty(myString, \"The string must not be empty\");</pre>\n     *\n     * @param <T>     the character sequence type\n     * @param chars   the character sequence to check, validated not null by this method\n     * @param message the {@link String#format(String, Object...)} exception message if invalid, not null\n     * @param values  the optional values for the formatted exception message, null array not recommended\n     * @return the validated character sequence (never {@code null} method for chaining)\n     * @throws NullPointerException     if the character sequence is {@code null}\n     * @throws IllegalArgumentException if the character sequence is empty\n     */\n    public static <T extends CharSequence> T notEmpty(T chars, String message, Object... values) {\n        if (chars == null || chars.length() == 0) {\n            throw new IllegalArgumentException(String.format(message, values));\n        }\n        return chars;\n    }\n\n\n    //---------------------------------------------------------\n    //\n    // Converters\n    //\n    //---------------------------------------------------------\n    public static String toString(Object o) {\n        if (null == o) {\n            return null;\n        }\n        return o.toString();\n    }\n\n    private Utils() {\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/filter/Evaluator.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport com.jayway.jsonpath.Predicate;\n\npublic interface Evaluator {\n    boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx);\n}"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/filter/EvaluatorFactory.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport com.jayway.jsonpath.JsonPathException;\nimport com.jayway.jsonpath.Predicate;\n\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.regex.Pattern;\n\nimport static com.jayway.jsonpath.internal.filter.ValueNodes.PatternNode;\nimport static com.jayway.jsonpath.internal.filter.ValueNodes.ValueListNode;\n\npublic class EvaluatorFactory {\n\n    private static final Map<RelationalOperator, Evaluator> evaluators = new HashMap<RelationalOperator, Evaluator>();\n\n    static {\n        evaluators.put(RelationalOperator.EXISTS, new ExistsEvaluator());\n        evaluators.put(RelationalOperator.NE, new NotEqualsEvaluator());\n        evaluators.put(RelationalOperator.TSNE, new TypeSafeNotEqualsEvaluator());\n        evaluators.put(RelationalOperator.EQ, new EqualsEvaluator());\n        evaluators.put(RelationalOperator.TSEQ, new TypeSafeEqualsEvaluator());\n        evaluators.put(RelationalOperator.LT, new LessThanEvaluator());\n        evaluators.put(RelationalOperator.LTE, new LessThanEqualsEvaluator());\n        evaluators.put(RelationalOperator.GT, new GreaterThanEvaluator());\n        evaluators.put(RelationalOperator.GTE, new GreaterThanEqualsEvaluator());\n        evaluators.put(RelationalOperator.REGEX, new RegexpEvaluator());\n        evaluators.put(RelationalOperator.SIZE, new SizeEvaluator());\n        evaluators.put(RelationalOperator.EMPTY, new EmptyEvaluator());\n        evaluators.put(RelationalOperator.IN, new InEvaluator());\n        evaluators.put(RelationalOperator.NIN, new NotInEvaluator());\n        evaluators.put(RelationalOperator.ALL, new AllEvaluator());\n        evaluators.put(RelationalOperator.CONTAINS, new ContainsEvaluator());\n        evaluators.put(RelationalOperator.MATCHES, new PredicateMatchEvaluator());\n        evaluators.put(RelationalOperator.TYPE, new TypeEvaluator());\n        evaluators.put(RelationalOperator.SUBSETOF, new SubsetOfEvaluator());\n        evaluators.put(RelationalOperator.ANYOF, new AnyOfEvaluator());\n        evaluators.put(RelationalOperator.NONEOF, new NoneOfEvaluator());\n    }\n\n    public static Evaluator createEvaluator(RelationalOperator operator){\n        return evaluators.get(operator);\n    }\n\n    private static class ExistsEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            if(!left.isBooleanNode() && !right.isBooleanNode()){\n                throw new JsonPathException(\"Failed to evaluate exists expression\");\n            }\n            return left.asBooleanNode().getBoolean() == right.asBooleanNode().getBoolean();\n        }\n    }\n\n    private static class NotEqualsEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            return !evaluators.get(RelationalOperator.EQ).evaluate(left, right, ctx);\n        }\n    }\n\n    private static class TypeSafeNotEqualsEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            return !evaluators.get(RelationalOperator.TSEQ).evaluate(left, right, ctx);\n        }\n    }\n\n    private static class EqualsEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            if(left.isJsonNode() && right.isJsonNode()){\n                return left.asJsonNode().equals(right.asJsonNode(), ctx);\n            } else {\n                return left.equals(right);\n            }\n        }\n    }\n\n    private static class TypeSafeEqualsEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            if(!left.getClass().equals(right.getClass())){\n                return false;\n            }\n            return evaluators.get(RelationalOperator.EQ).evaluate(left, right, ctx);\n        }\n    }\n\n    private static class TypeEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            return right.asClassNode().getClazz() == left.type(ctx);\n        }\n    }\n\n    private static class LessThanEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            if(left.isNumberNode() && right.isNumberNode()){\n                return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) < 0;\n            } if(left.isStringNode() && right.isStringNode()){\n                return left.asStringNode().getString().compareTo(right.asStringNode().getString()) < 0;\n            } if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613\n                return left.asOffsetDateTimeNode().getDate().compareTo(right.asOffsetDateTimeNode().getDate()) < 0;\n            }\n            return false;\n        }\n    }\n\n    private static class LessThanEqualsEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            if(left.isNumberNode() && right.isNumberNode()){\n                return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) <= 0;\n            } if(left.isStringNode() && right.isStringNode()){\n                return left.asStringNode().getString().compareTo(right.asStringNode().getString()) <= 0;\n            } if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613\n                return left.asOffsetDateTimeNode().getDate().compareTo(right.asOffsetDateTimeNode().getDate()) <= 0;\n            }\n            return false;\n        }\n    }\n\n    private static class GreaterThanEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            if(left.isNumberNode() && right.isNumberNode()){\n                return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) > 0;\n            } else if(left.isStringNode() && right.isStringNode()){\n                return left.asStringNode().getString().compareTo(right.asStringNode().getString()) > 0;\n            } else if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613\n                return left.asOffsetDateTimeNode().getDate().compareTo(right.asOffsetDateTimeNode().getDate()) > 0;\n            }\n            return false;\n        }\n    }\n\n    private static class GreaterThanEqualsEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            if(left.isNumberNode() && right.isNumberNode()){\n                return left.asNumberNode().getNumber().compareTo(right.asNumberNode().getNumber()) >= 0;\n            } else if(left.isStringNode() && right.isStringNode()){\n                return left.asStringNode().getString().compareTo(right.asStringNode().getString()) >= 0;\n            } else if (left.isOffsetDateTimeNode() && right.isOffsetDateTimeNode()){ //workaround for issue: https://github.com/json-path/JsonPath/issues/613\n                return left.asOffsetDateTimeNode().getDate().compareTo(right.asOffsetDateTimeNode().getDate()) >= 0;\n            }\n            return false;\n        }\n    }\n\n    private static class SizeEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            if (! right.isNumberNode()) {\n                return false;\n            }\n            int expectedSize = right.asNumberNode().getNumber().intValue();\n\n            if(left.isStringNode()){\n                return left.asStringNode().length() == expectedSize;\n            } else if(left.isJsonNode()){\n                return left.asJsonNode().length(ctx) == expectedSize;\n            }\n            return false;\n        }\n    }\n\n    private static class EmptyEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            if(left.isStringNode()){\n                return left.asStringNode().isEmpty() == right.asBooleanNode().getBoolean();\n            } else if(left.isJsonNode()){\n                return left.asJsonNode().isEmpty(ctx) == right.asBooleanNode().getBoolean();\n            }\n            return false;\n        }\n    }\n\n    private static class InEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            ValueListNode valueListNode;\n            if(right.isJsonNode()){\n                ValueNode vn = right.asJsonNode().asValueListNode(ctx);\n                if(vn.isUndefinedNode()){\n                    return false;\n                } else {\n                    valueListNode = vn.asValueListNode();\n                }\n            } else {\n                valueListNode = right.asValueListNode();\n            }\n            return valueListNode.contains(left);\n        }\n    }\n\n    private static class NotInEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            return !evaluators.get(RelationalOperator.IN).evaluate(left, right, ctx);\n        }\n    }\n\n    private static class AllEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            ValueListNode requiredValues = right.asValueListNode();\n\n            if(left.isJsonNode()){\n                ValueNode valueNode = left.asJsonNode().asValueListNode(ctx); //returns UndefinedNode if conversion is not possible\n                if(valueNode.isValueListNode()){\n                    ValueListNode shouldContainAll = valueNode.asValueListNode();\n                    for (ValueNode required : requiredValues) {\n                        if(!shouldContainAll.contains(required)){\n                            return false;\n                        }\n                    }\n                }\n                return true;\n            }\n            return false;\n        }\n    }\n\n    private static class ContainsEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            if(left.isStringNode() && right.isStringNode()){\n                return left.asStringNode().contains(right.asStringNode().getString());\n            } else if(left.isJsonNode()){\n                ValueNode valueNode = left.asJsonNode().asValueListNode(ctx);\n                if(valueNode.isUndefinedNode()) return false;\n                else {\n                    boolean res = valueNode.asValueListNode().contains(right);\n                    return res;\n                }\n            }\n            return false;\n        }\n    }\n\n    private static class PredicateMatchEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            return right.asPredicateNode().getPredicate().apply(ctx);\n        }\n    }\n\n    private static class RegexpEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            if(!(left.isPatternNode() ^ right.isPatternNode())){\n                return false;\n            }\n\n            if (left.isPatternNode()) {\n                if (right.isValueListNode() || (right.isJsonNode() && right.asJsonNode().isArray(ctx))) {\n                    return matchesAny(left.asPatternNode(), right.asJsonNode().asValueListNode(ctx));\n                } else {\n                    return matches(left.asPatternNode(), getInput(right));\n                }\n            } else {\n                if (left.isValueListNode() || (left.isJsonNode() && left.asJsonNode().isArray(ctx))) {\n                    return matchesAny(right.asPatternNode(), left.asJsonNode().asValueListNode(ctx));\n                } else {\n                    return matches(right.asPatternNode(), getInput(left));\n                }\n            }\n        }\n\n        private boolean matches(PatternNode patternNode, String inputToMatch) {\n            return patternNode.getCompiledPattern().matcher(inputToMatch).matches();\n        }\n\n        private boolean matchesAny(PatternNode patternNode, ValueNode valueNode) {\n            if (!valueNode.isValueListNode()) {\n                return false;\n            }\n\n            ValueListNode listNode = valueNode.asValueListNode();\n            Pattern pattern = patternNode.getCompiledPattern();\n\n            for (Iterator<ValueNode> it = listNode.iterator(); it.hasNext(); ) {\n                String input = getInput(it.next());\n                if (pattern.matcher(input).matches()) {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        private String getInput(ValueNode valueNode) {\n            String input = \"\";\n\n            if (valueNode.isStringNode() || valueNode.isNumberNode()) {\n                input = valueNode.asStringNode().getString();\n            } else if (valueNode.isBooleanNode()) {\n                input = valueNode.asBooleanNode().toString();\n            }\n\n            return input;\n        }\n    }\n\n    private static class SubsetOfEvaluator implements Evaluator {\n       @Override\n       public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n           ValueListNode rightValueListNode;\n           if(right.isJsonNode()){\n               ValueNode vn = right.asJsonNode().asValueListNode(ctx);\n               if(vn.isUndefinedNode()){\n                   return false;\n               } else {\n                   rightValueListNode = vn.asValueListNode();\n               }\n           } else {\n               rightValueListNode = right.asValueListNode();\n           }\n           ValueListNode leftValueListNode;\n           if(left.isJsonNode()){\n               ValueNode vn = left.asJsonNode().asValueListNode(ctx);\n               if(vn.isUndefinedNode()){\n                   return false;\n               } else {\n                  leftValueListNode = vn.asValueListNode();\n               }\n           } else {\n              leftValueListNode = left.asValueListNode();\n           }\n           return leftValueListNode.subsetof(rightValueListNode);\n       }\n   }\n\n    private static class AnyOfEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            ValueListNode rightValueListNode;\n            if (right.isJsonNode()) {\n                ValueNode vn = right.asJsonNode().asValueListNode(ctx);\n                if (vn.isUndefinedNode()) {\n                    return false;\n                } else {\n                    rightValueListNode = vn.asValueListNode();\n                }\n            } else {\n                rightValueListNode = right.asValueListNode();\n            }\n            ValueListNode leftValueListNode;\n            if (left.isJsonNode()) {\n                ValueNode vn = left.asJsonNode().asValueListNode(ctx);\n                if (vn.isUndefinedNode()) {\n                    return false;\n                } else {\n                    leftValueListNode = vn.asValueListNode();\n                }\n            } else {\n                leftValueListNode = left.asValueListNode();\n            }\n\n            for (ValueNode leftValueNode : leftValueListNode) {\n                for (ValueNode rightValueNode : rightValueListNode) {\n                    if (leftValueNode.equals(rightValueNode)) {\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n    }\n\n    private static class NoneOfEvaluator implements Evaluator {\n        @Override\n        public boolean evaluate(ValueNode left, ValueNode right, Predicate.PredicateContext ctx) {\n            ValueListNode rightValueListNode;\n            if (right.isJsonNode()) {\n                ValueNode vn = right.asJsonNode().asValueListNode(ctx);\n                if (vn.isUndefinedNode()) {\n                    return false;\n                } else {\n                    rightValueListNode = vn.asValueListNode();\n                }\n            } else {\n                rightValueListNode = right.asValueListNode();\n            }\n            ValueListNode leftValueListNode;\n            if (left.isJsonNode()) {\n                ValueNode vn = left.asJsonNode().asValueListNode(ctx);\n                if (vn.isUndefinedNode()) {\n                    return false;\n                } else {\n                    leftValueListNode = vn.asValueListNode();\n                }\n            } else {\n                leftValueListNode = left.asValueListNode();\n            }\n\n            for (ValueNode leftValueNode : leftValueListNode) {\n                for (ValueNode rightValueNode : rightValueListNode) {\n                    if (leftValueNode.equals(rightValueNode)) {\n                        return false;\n                    }\n                }\n            }\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/filter/ExpressionNode.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport com.jayway.jsonpath.Predicate;\n\npublic abstract class ExpressionNode implements Predicate {\n\n    public static ExpressionNode createExpressionNode(ExpressionNode right, LogicalOperator operator,  ExpressionNode left){\n        if(operator == LogicalOperator.AND){\n            if((right instanceof LogicalExpressionNode) && ((LogicalExpressionNode)right).getOperator() == LogicalOperator.AND ){\n                LogicalExpressionNode len = (LogicalExpressionNode) right;\n                return len.append(left);\n            } else {\n                return LogicalExpressionNode.createLogicalAnd(left, right);\n            }\n        } else {\n            if((right instanceof LogicalExpressionNode) && ((LogicalExpressionNode)right).getOperator() == LogicalOperator.OR ){\n                LogicalExpressionNode len = (LogicalExpressionNode) right;\n                return len.append(left);\n            } else {\n                return LogicalExpressionNode.createLogicalOr(left, right);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport com.jayway.jsonpath.Filter;\nimport com.jayway.jsonpath.InvalidPathException;\nimport com.jayway.jsonpath.Predicate;\nimport com.jayway.jsonpath.internal.CharacterIndex;\nimport static com.jayway.jsonpath.internal.filter.ValueNodes.*;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class FilterCompiler  {\n    private static final Logger logger = LoggerFactory.getLogger(FilterCompiler.class);\n\n    private static final char DOC_CONTEXT = '$';\n    private static final char EVAL_CONTEXT = '@';\n\n    private static final char OPEN_SQUARE_BRACKET = '[';\n    private static final char CLOSE_SQUARE_BRACKET = ']';\n    private static final char OPEN_PARENTHESIS = '(';\n    private static final char CLOSE_PARENTHESIS = ')';\n    private static final char OPEN_OBJECT = '{';\n    private static final char CLOSE_OBJECT = '}';\n    private static final char OPEN_ARRAY = '[';\n    private static final char CLOSE_ARRAY = ']';\n\n    private static final char SINGLE_QUOTE = '\\'';\n    private static final char DOUBLE_QUOTE = '\"';\n\n    private static final char SPACE = ' ';\n    private static final char PERIOD = '.';\n\n    private static final char AND = '&';\n    private static final char OR = '|';\n\n    private static final char MINUS = '-';\n    private static final char LT = '<';\n    private static final char GT = '>';\n    private static final char EQ = '=';\n    private static final char TILDE = '~';\n    private static final char TRUE = 't';\n    private static final char FALSE = 'f';\n    private static final char NULL = 'n';\n    private static final char NOT = '!';\n    private static final char PATTERN = '/';\n    private static final char IGNORE_CASE = 'i';\n\n    private CharacterIndex filter;\n\n    public static Filter compile(String filterString) {\n        FilterCompiler compiler = new FilterCompiler(filterString);\n        return new CompiledFilter(compiler.compile());\n    }\n\n    private FilterCompiler(String filterString) {\n        filter = new CharacterIndex(filterString);\n        filter.trim();\n        if (!filter.currentCharIs('[') || !filter.lastCharIs(']')) {\n            throw new InvalidPathException(\"Filter must start with '[' and end with ']'. \" + filterString);\n        }\n        filter.incrementPosition(1);\n        filter.decrementEndPosition(1);\n        filter.trim();\n        if (!filter.currentCharIs('?')) {\n            throw new InvalidPathException(\"Filter must start with '[?' and end with ']'. \" + filterString);\n        }\n        filter.incrementPosition(1);\n        filter.trim();\n        if (!filter.currentCharIs('(') || !filter.lastCharIs(')')) {\n            throw new InvalidPathException(\"Filter must start with '[?(' and end with ')]'. \" + filterString);\n        }\n    }\n\n    public Predicate compile() {\n        try {\n             final ExpressionNode result = readLogicalOR();\n             filter.skipBlanks();\n             if (filter.inBounds()) {\n                 throw new InvalidPathException(String.format(\"Expected end of filter expression instead of: %s\",\n                         filter.subSequence(filter.position(), filter.length())));\n             }\n\n             return result;\n        } catch (InvalidPathException e){\n            throw e;\n        } catch (Exception e) {\n            throw new InvalidPathException(\"Failed to parse filter: \" + filter + \", error on position: \" + filter.position() + \", char: \" + filter.currentChar());\n        }\n    }\n\n    private ValueNode readValueNode() {\n        switch (filter.skipBlanks().currentChar()) {\n            case DOC_CONTEXT  : return readPath();\n            case EVAL_CONTEXT : return readPath();\n            case NOT:\n                filter.incrementPosition(1);\n                switch (filter.skipBlanks().currentChar()) {\n                    case DOC_CONTEXT  : return readPath();\n                    case EVAL_CONTEXT : return readPath();\n                    default: throw new InvalidPathException(String.format(\"Unexpected character: %c\", NOT));\n                }\n            default : return readLiteral();\n        }\n    }\n\n    private ValueNode readLiteral(){\n        switch (filter.skipBlanks().currentChar()){\n            case SINGLE_QUOTE:  return readStringLiteral(SINGLE_QUOTE);\n            case DOUBLE_QUOTE: return readStringLiteral(DOUBLE_QUOTE);\n            case TRUE:  return readBooleanLiteral();\n            case FALSE: return readBooleanLiteral();\n            case MINUS: return readNumberLiteral();\n            case NULL:  return readNullLiteral();\n            case OPEN_OBJECT: return readJsonLiteral();\n            case OPEN_ARRAY: return readJsonLiteral();\n            case PATTERN: return readPattern();\n            default:    return readNumberLiteral();\n        }\n    }\n\n    /*\n     *  LogicalOR               = LogicalAND { '||' LogicalAND }\n     *  LogicalAND              = LogicalANDOperand { '&&' LogicalANDOperand }\n     *  LogicalANDOperand       = RelationalExpression | '(' LogicalOR ')' | '!' LogicalANDOperand\n     *  RelationalExpression    = Value [ RelationalOperator Value ]\n     */\n\n    private ExpressionNode readLogicalOR() {\n        final List<ExpressionNode> ops = new ArrayList<ExpressionNode>();\n        ops.add(readLogicalAND());\n\n        while (true) {\n            int savepoint = filter.position();\n            if (filter.hasSignificantSubSequence(LogicalOperator.OR.getOperatorString())) {\n                ops.add(readLogicalAND());\n            } else {\n                filter.setPosition(savepoint);\n                break;\n            }\n        }\n\n        return 1 == ops.size() ? ops.get(0) : LogicalExpressionNode.createLogicalOr(ops);\n    }\n\n    private ExpressionNode readLogicalAND() {\n        /// @fixme copy-pasted\n        final List<ExpressionNode> ops = new ArrayList<ExpressionNode>();\n        ops.add(readLogicalANDOperand());\n\n        while (true) {\n            int savepoint = filter.position();\n            if (filter.hasSignificantSubSequence(LogicalOperator.AND.getOperatorString())) {\n                ops.add(readLogicalANDOperand());\n            } else {\n                filter.setPosition(savepoint);\n                break;\n            }\n        }\n\n        return 1 == ops.size() ? ops.get(0) : LogicalExpressionNode.createLogicalAnd(ops);\n    }\n\n    private ExpressionNode readLogicalANDOperand() {\n        int savepoint = filter.skipBlanks().position();\n        if (filter.skipBlanks().currentCharIs(NOT)) {\n            filter.readSignificantChar(NOT);\n            switch (filter.skipBlanks().currentChar()) {\n                case DOC_CONTEXT:\n                case EVAL_CONTEXT:\n                    filter.setPosition(savepoint);\n                    break;\n            default:\n                final ExpressionNode op = readLogicalANDOperand();\n                return LogicalExpressionNode.createLogicalNot(op);\n            }\n        }\n        if (filter.skipBlanks().currentCharIs(OPEN_PARENTHESIS)) {\n            filter.readSignificantChar(OPEN_PARENTHESIS);\n            final ExpressionNode op = readLogicalOR();\n            filter.readSignificantChar(CLOSE_PARENTHESIS);\n            return op;\n        }\n\n        return readExpression();\n    }\n\n    private RelationalExpressionNode readExpression() {\n        ValueNode left = readValueNode();\n        int savepoint = filter.position();\n        try {\n            RelationalOperator operator = readRelationalOperator();\n            ValueNode right = readValueNode();\n            return new RelationalExpressionNode(left, operator, right);\n        }\n        catch (InvalidPathException exc) {\n            filter.setPosition(savepoint);\n        }\n\n        PathNode pathNode = left.asPathNode();\n        left = pathNode.asExistsCheck(pathNode.shouldExists());\n        RelationalOperator operator = RelationalOperator.EXISTS;\n        ValueNode right = left.asPathNode().shouldExists() ? ValueNodes.TRUE : ValueNodes.FALSE;\n        return new RelationalExpressionNode(left, operator, right);\n    }\n\n    private LogicalOperator readLogicalOperator(){\n        int begin = filter.skipBlanks().position();\n        int end = begin+1;\n\n        if(!filter.inBounds(end)){\n            throw new InvalidPathException(\"Expected boolean literal\");\n        }\n        CharSequence logicalOperator = filter.subSequence(begin, end+1);\n        if(!logicalOperator.equals(\"||\") && !logicalOperator.equals(\"&&\")){\n            throw new InvalidPathException(\"Expected logical operator\");\n        }\n        filter.incrementPosition(logicalOperator.length());\n        logger.trace(\"LogicalOperator from {} to {} -> [{}]\", begin, end, logicalOperator);\n\n        return LogicalOperator.fromString(logicalOperator.toString());\n    }\n\n    private RelationalOperator readRelationalOperator() {\n        int begin = filter.skipBlanks().position();\n\n        if(isRelationalOperatorChar(filter.currentChar())){\n            while (filter.inBounds() && isRelationalOperatorChar(filter.currentChar())) {\n                filter.incrementPosition(1);\n            }\n        } else {\n            while (filter.inBounds() && filter.currentChar() != SPACE) {\n                filter.incrementPosition(1);\n            }\n        }\n\n        CharSequence operator = filter.subSequence(begin, filter.position());\n        logger.trace(\"Operator from {} to {} -> [{}]\", begin, filter.position()-1, operator);\n        return RelationalOperator.fromString(operator.toString());\n    }\n\n    private NullNode readNullLiteral() {\n        int begin = filter.position();\n        if(filter.currentChar() == NULL && filter.inBounds(filter.position() + 3)){\n            CharSequence nullValue = filter.subSequence(filter.position(), filter.position() + 4);\n            if(\"null\".equals(nullValue.toString())){\n                logger.trace(\"NullLiteral from {} to {} -> [{}]\", begin, filter.position()+3, nullValue);\n                filter.incrementPosition(nullValue.length());\n                return ValueNode.createNullNode();\n            }\n        }\n        throw new InvalidPathException(\"Expected <null> value\");\n    }\n\n    private JsonNode readJsonLiteral(){\n        int begin = filter.position();\n\n        char openChar = filter.currentChar();\n\n        assert openChar == OPEN_ARRAY || openChar == OPEN_OBJECT;\n\n        char closeChar = openChar == OPEN_ARRAY ? CLOSE_ARRAY : CLOSE_OBJECT;\n\n        int closingIndex = filter.indexOfMatchingCloseChar(filter.position(), openChar, closeChar, true, false);\n        if (closingIndex == -1) {\n            throw new InvalidPathException(\"String not closed. Expected \" + SINGLE_QUOTE + \" in \" + filter);\n        } else {\n            filter.setPosition(closingIndex + 1);\n        }\n        CharSequence json = filter.subSequence(begin, filter.position());\n        logger.trace(\"JsonLiteral from {} to {} -> [{}]\", begin, filter.position(), json);\n        return ValueNode.createJsonNode(json);\n\n    }\n\n    private int endOfFlags(int position) {\n        int endIndex = position;\n        char[] currentChar = new char[1];\n        while (filter.inBounds(endIndex)) {\n            currentChar[0] = filter.charAt(endIndex);\n            if (PatternFlag.parseFlags(currentChar) > 0) {\n                endIndex++;\n                continue;\n            }\n            break;\n        }\n        return endIndex;\n    }\n\n    private PatternNode readPattern() {\n        int begin = filter.position();\n        int closingIndex = filter.nextIndexOfUnescaped(PATTERN);\n        if (closingIndex == -1) {\n            throw new InvalidPathException(\"Pattern not closed. Expected \" + PATTERN + \" in \" + filter);\n        } else {\n            if (filter.inBounds(closingIndex+1)) {\n                int endFlagsIndex = endOfFlags(closingIndex + 1);\n                if (endFlagsIndex > closingIndex) {\n                    CharSequence flags = filter.subSequence(closingIndex + 1, endFlagsIndex);\n                    closingIndex += flags.length();\n                }\n            }\n            filter.setPosition(closingIndex + 1);\n        }\n        CharSequence pattern = filter.subSequence(begin, filter.position());\n        logger.trace(\"PatternNode from {} to {} -> [{}]\", begin, filter.position(), pattern);\n        return ValueNode.createPatternNode(pattern);\n    }\n\n    private StringNode readStringLiteral(char endChar) {\n        int begin = filter.position();\n\n        int closingSingleQuoteIndex = filter.nextIndexOfUnescaped(endChar);\n        if (closingSingleQuoteIndex == -1) {\n            throw new InvalidPathException(\"String literal does not have matching quotes. Expected \" + endChar + \" in \" + filter);\n        } else {\n            filter.setPosition(closingSingleQuoteIndex + 1);\n        }\n        CharSequence stringLiteral = filter.subSequence(begin, filter.position());\n        logger.trace(\"StringLiteral from {} to {} -> [{}]\", begin, filter.position(), stringLiteral);\n        return ValueNode.createStringNode(stringLiteral, true);\n    }\n\n    private NumberNode readNumberLiteral() {\n        int begin = filter.position();\n\n        while (filter.inBounds() && filter.isNumberCharacter(filter.position())) {\n            filter.incrementPosition(1);\n        }\n        CharSequence numberLiteral = filter.subSequence(begin, filter.position());\n        logger.trace(\"NumberLiteral from {} to {} -> [{}]\", begin, filter.position(), numberLiteral);\n        return ValueNode.createNumberNode(numberLiteral);\n    }\n\n    private BooleanNode readBooleanLiteral() {\n        int begin = filter.position();\n        int end = filter.currentChar() == TRUE ? filter.position() + 3 : filter.position() + 4;\n\n        if(!filter.inBounds(end)){\n            throw new InvalidPathException(\"Expected boolean literal\");\n        }\n        CharSequence boolValue = filter.subSequence(begin, end+1);\n        if(!boolValue.equals(\"true\") && !boolValue.equals(\"false\")){\n            throw new InvalidPathException(\"Expected boolean literal\");\n        }\n        filter.incrementPosition(boolValue.length());\n        logger.trace(\"BooleanLiteral from {} to {} -> [{}]\", begin, end, boolValue);\n\n        return ValueNode.createBooleanNode(boolValue);\n    }\n\n    private PathNode readPath() {\n        char previousSignificantChar = filter.previousSignificantChar();\n        int begin = filter.position();\n\n        filter.incrementPosition(1); //skip $ and @\n        while (filter.inBounds()) {\n            if (filter.currentChar() == OPEN_SQUARE_BRACKET) {\n                int closingSquareBracketIndex = filter.indexOfMatchingCloseChar(filter.position(), OPEN_SQUARE_BRACKET, CLOSE_SQUARE_BRACKET, true, false);\n                if (closingSquareBracketIndex == -1) {\n                    throw new InvalidPathException(\"Square brackets does not match in filter \" + filter);\n                } else {\n                    filter.setPosition(closingSquareBracketIndex + 1);\n                }\n            }\n            boolean closingFunctionBracket = (filter.currentChar() == CLOSE_PARENTHESIS && currentCharIsClosingFunctionBracket(begin));\n            boolean closingLogicalBracket  = (filter.currentChar() == CLOSE_PARENTHESIS && !closingFunctionBracket);\n\n            if (!filter.inBounds() || isRelationalOperatorChar(filter.currentChar()) || filter.currentChar() == SPACE || closingLogicalBracket) {\n                break;\n            } else {\n                filter.incrementPosition(1);\n            }\n        }\n\n        boolean shouldExists = !(previousSignificantChar == NOT);\n        CharSequence path = filter.subSequence(begin, filter.position());\n        return ValueNode.createPathNode(path, false, shouldExists);\n    }\n\n    private boolean expressionIsTerminated(){\n        char c = filter.currentChar();\n        if(c == CLOSE_PARENTHESIS || isLogicalOperatorChar(c)){\n            return true;\n        }\n        c = filter.nextSignificantChar();\n        if(c == CLOSE_PARENTHESIS || isLogicalOperatorChar(c)){\n            return true;\n        }\n        return false;\n    }\n\n    private boolean currentCharIsClosingFunctionBracket(int lowerBound){\n        if(filter.currentChar() != CLOSE_PARENTHESIS){\n            return false;\n        }\n        int idx = filter.indexOfPreviousSignificantChar();\n        if(idx == -1 || filter.charAt(idx) != OPEN_PARENTHESIS){\n            return false;\n        }\n        idx--;\n        while(filter.inBounds(idx) && idx > lowerBound){\n            if(filter.charAt(idx) == PERIOD){\n                return true;\n            }\n            idx--;\n        }\n        return false;\n    }\n\n    private boolean isLogicalOperatorChar(char c) {\n        return c == AND || c == OR;\n    }\n\n    private boolean isRelationalOperatorChar(char c) {\n        return c == LT || c == GT || c == EQ || c == TILDE || c == NOT;\n    }\n\n    private static final class CompiledFilter extends Filter {\n\n        private final Predicate predicate;\n\n        private CompiledFilter(Predicate predicate) {\n            this.predicate = predicate;\n        }\n\n        @Override\n        public boolean apply(Predicate.PredicateContext ctx) {\n            return predicate.apply(ctx);\n        }\n\n        @Override\n        public String toString() {\n            String predicateString = predicate.toString();\n            if(predicateString.startsWith(\"(\")){\n                return \"[?\" + predicateString + \"]\";\n            } else {\n                return \"[?(\" + predicateString + \")]\";\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/filter/LogicalExpressionNode.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport com.jayway.jsonpath.internal.Utils;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\n\npublic class LogicalExpressionNode extends ExpressionNode {\n    protected List<ExpressionNode> chain = new ArrayList<ExpressionNode>();\n    private final LogicalOperator operator;\n\n    public static ExpressionNode createLogicalNot(ExpressionNode op) {\n       return new LogicalExpressionNode(op, LogicalOperator.NOT, null);\n    }\n\n    public static LogicalExpressionNode createLogicalOr(ExpressionNode left,ExpressionNode right){\n        return new LogicalExpressionNode(left, LogicalOperator.OR, right);\n    }\n\n    public static LogicalExpressionNode createLogicalOr(Collection<ExpressionNode> operands){\n        return new LogicalExpressionNode(LogicalOperator.OR, operands);\n    }\n\n    public static LogicalExpressionNode createLogicalAnd(ExpressionNode left,ExpressionNode right){\n        return new LogicalExpressionNode(left, LogicalOperator.AND, right);\n    }\n\n    public static LogicalExpressionNode createLogicalAnd(Collection<ExpressionNode> operands){\n        return new LogicalExpressionNode(LogicalOperator.AND, operands);\n    }\n\n    private LogicalExpressionNode(ExpressionNode left, LogicalOperator operator, ExpressionNode right) {\n        chain.add(left);\n        chain.add(right);\n        this.operator = operator;\n    }\n\n    private LogicalExpressionNode(LogicalOperator operator, Collection<ExpressionNode> operands) {\n        chain.addAll(operands);\n        this.operator = operator;\n    }\n\n    public LogicalExpressionNode and(LogicalExpressionNode other){\n        return createLogicalAnd(this, other);\n    }\n\n    public LogicalExpressionNode or(LogicalExpressionNode other){\n        return createLogicalOr(this, other);\n    }\n\n    public LogicalOperator getOperator() {\n        return operator;\n    }\n\n    public LogicalExpressionNode append(ExpressionNode expressionNode) {\n        chain.add(0, expressionNode);\n        return this;\n    }\n\n    @Override\n    public String toString() {\n        return \"(\" + Utils.join(\" \" + operator.getOperatorString() + \" \", chain) + \")\";\n    }\n\n    @Override\n    public boolean apply(PredicateContext ctx) {\n        if(operator == LogicalOperator.OR){\n            for (ExpressionNode expression : chain) {\n                if(expression.apply(ctx)){\n                    return true;\n                }\n            }\n            return false;\n        } else if (operator == LogicalOperator.AND) {\n            for (ExpressionNode expression : chain) {\n                if(!expression.apply(ctx)){\n                    return false;\n                }\n            }\n            return true;\n        } else {\n            ExpressionNode expression = chain.get(0);\n            return !expression.apply(ctx);\n        }\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/filter/LogicalOperator.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport com.jayway.jsonpath.InvalidPathException;\n\npublic enum LogicalOperator {\n\n    AND(\"&&\"),\n    NOT(\"!\"),\n    OR(\"||\");\n\n    private final String operatorString;\n\n    LogicalOperator(String operatorString) {\n        this.operatorString = operatorString;\n    }\n\n    public String getOperatorString() {\n        return operatorString;\n    }\n\n    @Override\n    public String toString() {\n        return operatorString;\n    }\n\n    public static LogicalOperator fromString(String operatorString){\n        if(AND.operatorString.equals(operatorString)) return AND;\n        else if(NOT.operatorString.equals(operatorString)) return NOT;\n        else if(OR.operatorString.equals(operatorString)) return OR;\n        else throw new InvalidPathException(\"Failed to parse operator \" + operatorString);\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/filter/PatternFlag.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport java.util.regex.Pattern;\n\npublic enum PatternFlag {\n    UNIX_LINES(Pattern.UNIX_LINES, 'd'),\n    CASE_INSENSITIVE(Pattern.CASE_INSENSITIVE, 'i'),\n    COMMENTS(Pattern.COMMENTS, 'x'),\n    MULTILINE(Pattern.MULTILINE, 'm'),\n    DOTALL(Pattern.DOTALL, 's'),\n    UNICODE_CASE(Pattern.UNICODE_CASE, 'u'),\n    UNICODE_CHARACTER_CLASS(Pattern.UNICODE_CHARACTER_CLASS, 'U');\n\n    private final int code;\n    private final char flag;\n\n    private PatternFlag(int code, char flag) {\n        this.code = code;\n        this.flag = flag;\n    }\n\n    public static int parseFlags(char[] flags) {\n        int flagsValue = 0;\n        for (char flag : flags) {\n            flagsValue |= getCodeByFlag(flag);\n        }\n        return flagsValue;\n    }\n\n    public static String parseFlags(int flags) {\n        StringBuilder builder = new StringBuilder();\n        for (PatternFlag patternFlag : PatternFlag.values()) {\n            if ((patternFlag.code & flags) == patternFlag.code) {\n                builder.append(patternFlag.flag);\n            }\n        }\n        return builder.toString();\n    }\n\n    private static int getCodeByFlag(char flag) {\n        for (PatternFlag patternFlag : PatternFlag.values()) {\n            if (patternFlag.flag == flag) {\n                return patternFlag.code;\n            }\n        }\n        return 0;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/filter/RelationalExpressionNode.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class RelationalExpressionNode extends ExpressionNode {\n\n    private static final Logger logger = LoggerFactory.getLogger(RelationalExpressionNode.class);\n\n    private final ValueNode left;\n    private final RelationalOperator relationalOperator;\n    private final ValueNode right;\n\n    public RelationalExpressionNode(ValueNode left, RelationalOperator relationalOperator, ValueNode right) {\n        this.left = left;\n        this.relationalOperator = relationalOperator;\n        this.right = right;\n\n        logger.trace(\"ExpressionNode {}\", toString());\n    }\n\n    @Override\n    public String toString() {\n        if(relationalOperator == RelationalOperator.EXISTS){\n            return left.toString();\n        } else {\n            return left.toString() + \" \" + relationalOperator.toString() + \" \" + right.toString();\n        }\n    }\n\n    @Override\n    public boolean apply(PredicateContext ctx) {\n        ValueNode l = left;\n        ValueNode r = right;\n\n        if(left.isPathNode()){\n            l = left.asPathNode().evaluate(ctx);\n        }\n        if(right.isPathNode()){\n            r = right.asPathNode().evaluate(ctx);\n        }\n        Evaluator evaluator = EvaluatorFactory.createEvaluator(relationalOperator);\n        if(evaluator != null){\n            return evaluator.evaluate(l, r, ctx);\n        }\n        return false;\n    }\n}"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/filter/RelationalOperator.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport com.jayway.jsonpath.InvalidPathException;\n\nimport java.util.Locale;\n\npublic enum RelationalOperator {\n\n    GTE(\">=\"),\n    LTE(\"<=\"),\n    EQ(\"==\"),\n\n    /**\n     * Type safe equals\n     */\n    TSEQ(\"===\"),\n    NE(\"!=\"),\n\n    /**\n     * Type safe not equals\n     */\n    TSNE(\"!==\"),\n    LT(\"<\"),\n    GT(\">\"),\n    REGEX(\"=~\"),\n    NIN(\"NIN\"),\n    IN(\"IN\"),\n    CONTAINS(\"CONTAINS\"),\n    ALL(\"ALL\"),\n    SIZE(\"SIZE\"),\n    EXISTS(\"EXISTS\"),\n    TYPE(\"TYPE\"),\n    MATCHES(\"MATCHES\"),\n    EMPTY(\"EMPTY\"),\n    SUBSETOF(\"SUBSETOF\"),\n    ANYOF(\"ANYOF\"),\n    NONEOF(\"NONEOF\");\n\n    private final String operatorString;\n\n    RelationalOperator(String operatorString) {\n        this.operatorString = operatorString;\n    }\n\n    public static RelationalOperator fromString(String operatorString) {\n        String upperCaseOperatorString = operatorString.toUpperCase(Locale.ROOT);\n        for (RelationalOperator operator : RelationalOperator.values()) {\n            if(operator.operatorString.equals(upperCaseOperatorString) ){\n                return operator;\n            }\n        }\n        throw new InvalidPathException(\"Filter operator \" + operatorString + \" is not supported!\");\n    }\n\n    @Override\n    public String toString() {\n        return operatorString;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport com.jayway.jsonpath.InvalidPathException;\nimport com.jayway.jsonpath.JsonPathException;\nimport com.jayway.jsonpath.Predicate;\nimport com.jayway.jsonpath.internal.Path;\nimport com.jayway.jsonpath.internal.path.PathCompiler;\nimport net.minidev.json.parser.JSONParser;\n\nimport java.time.OffsetDateTime;\nimport java.util.regex.Pattern;\n\nimport static com.jayway.jsonpath.internal.filter.ValueNodes.*;\n\npublic abstract class ValueNode {\n\n    public abstract Class<?> type(Predicate.PredicateContext ctx);\n\n    public boolean isPatternNode() {\n        return false;\n    }\n\n    public PatternNode asPatternNode() {\n        throw new InvalidPathException(\"Expected regexp node\");\n    }\n\n    public boolean isPathNode() {\n        return false;\n    }\n\n    public PathNode asPathNode() {\n        throw new InvalidPathException(\"Expected path node\");\n    }\n\n    public boolean isNumberNode() {\n        return false;\n    }\n\n    public NumberNode asNumberNode() {\n        throw new InvalidPathException(\"Expected number node\");\n    }\n\n    public boolean isStringNode() {\n        return false;\n    }\n\n    public StringNode asStringNode() {\n        throw new InvalidPathException(\"Expected string node\");\n    }\n\n    public boolean isBooleanNode() {\n        return false;\n    }\n\n    public BooleanNode asBooleanNode() {\n        throw new InvalidPathException(\"Expected boolean node\");\n    }\n\n    public boolean isJsonNode() {\n        return false;\n    }\n\n    public JsonNode asJsonNode() {\n        throw new InvalidPathException(\"Expected json node\");\n    }\n\n    public boolean isPredicateNode() {\n        return false;\n    }\n\n    public PredicateNode asPredicateNode() {\n        throw new InvalidPathException(\"Expected predicate node\");\n    }\n\n    public boolean isValueListNode() {\n        return false;\n    }\n\n    public ValueListNode asValueListNode() {\n        throw new InvalidPathException(\"Expected value list node\");\n    }\n\n    public boolean isNullNode() {\n        return false;\n    }\n\n    public NullNode asNullNode() {\n        throw new InvalidPathException(\"Expected null node\");\n    }\n\n    public UndefinedNode asUndefinedNode() {\n        throw new InvalidPathException(\"Expected undefined node\");\n    }\n\n    public boolean isUndefinedNode() {\n        return false;\n    }\n\n    public boolean isClassNode() {\n        return false;\n    }\n\n    public ClassNode asClassNode() {\n        throw new InvalidPathException(\"Expected class node\");\n    }\n\n    //workaround for issue: https://github.com/json-path/JsonPath/issues/613\n    public boolean isOffsetDateTimeNode(){\n        return false;\n    }\n\n    public OffsetDateTimeNode asOffsetDateTimeNode(){\n        throw new InvalidPathException(\"Expected offsetDateTime node\");\n    }\n\n\n    private static boolean isPath(Object o) {\n        if(o == null || !(o instanceof String)){\n            return false;\n        }\n        String str = o.toString().trim();\n        if (str.length() <= 0) {\n            return false;\n        }\n        char c0 = str.charAt(0);\n        if(c0 == '@' || c0 == '$'){\n            try {\n                PathCompiler.compile(str);\n                return true;\n            } catch(Exception e){\n                return false;\n            }\n        }\n        return false;\n    }\n\n    private static boolean isJson(Object o) {\n        if(o == null || !(o instanceof String)){\n            return false;\n        }\n        String str = o.toString().trim();\n        if (str.length() <= 1) {\n            return false;\n        }\n        char c0 = str.charAt(0);\n        char c1 = str.charAt(str.length() - 1);\n        if ((c0 == '[' && c1 == ']') || (c0 == '{' && c1 == '}')){\n            try {\n                new JSONParser(JSONParser.MODE_PERMISSIVE).parse(str);\n                return true;\n            } catch(Exception e){\n                return false;\n            }\n        }\n        return false;\n    }\n\n\n\n    //----------------------------------------------------\n    //\n    // Factory methods\n    //\n    //----------------------------------------------------\n    public static ValueNode toValueNode(Object o){\n\n        if(o == null) return NULL_NODE;\n        if(o instanceof ValueNode) return (ValueNode)o;\n        if(o instanceof Class) return createClassNode((Class)o);\n        else if(isPath(o)) return new PathNode(o.toString(), false, false);\n        else if(isJson(o)) return createJsonNode(o.toString());\n        else if(o instanceof String) return createStringNode(o.toString(), true);\n        else if(o instanceof Character) return createStringNode(o.toString(), false);\n        else if(o instanceof Number) return createNumberNode(o.toString());\n        else if(o instanceof Boolean) return createBooleanNode(o.toString());\n        else if(o instanceof Pattern) return createPatternNode((Pattern)o);\n        else if (o instanceof OffsetDateTime) return createOffsetDateTimeNode(o.toString());  //workaround for issue: https://github.com/json-path/JsonPath/issues/613\n        else throw new JsonPathException(\"Could not determine value type\");\n\n    }\n\n    public static StringNode createStringNode(CharSequence charSequence, boolean escape){\n        return new StringNode(charSequence, escape);\n    }\n\n    public static ClassNode createClassNode(Class<?> clazz){\n        return new ClassNode(clazz);\n    }\n\n    public static NumberNode createNumberNode(CharSequence charSequence){\n        return new NumberNode(charSequence);\n    }\n\n    public static BooleanNode createBooleanNode(CharSequence charSequence){\n        return Boolean.parseBoolean(charSequence.toString()) ? TRUE : FALSE;\n    }\n\n    public static NullNode createNullNode(){\n        return NULL_NODE;\n    }\n\n    public static JsonNode createJsonNode(CharSequence json) {\n        return new JsonNode(json);\n    }\n\n    public static JsonNode createJsonNode(Object parsedJson) {\n        return new JsonNode(parsedJson);\n    }\n\n    public static PatternNode createPatternNode(CharSequence pattern) {\n        return new PatternNode(pattern);\n    }\n\n    public static PatternNode createPatternNode(Pattern pattern) {\n        return new PatternNode(pattern);\n    }\n\n    //workaround for issue: https://github.com/json-path/JsonPath/issues/613\n    public static OffsetDateTimeNode createOffsetDateTimeNode(CharSequence charSequence){\n        return new OffsetDateTimeNode(charSequence);\n    }\n\n\n    public static UndefinedNode createUndefinedNode() {\n        return UNDEFINED;\n    }\n\n    public static PathNode createPathNode(CharSequence path, boolean existsCheck, boolean shouldExists) {\n        return new PathNode(path, existsCheck, shouldExists);\n    }\n\n    public static ValueNode createPathNode(Path path) {\n        return new PathNode(path);\n    }\n\n\n}\n\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNodes.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport java.math.BigDecimal;\nimport java.time.OffsetDateTime;\nimport java.util.*;\nimport java.util.regex.Pattern;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.JsonPathException;\nimport com.jayway.jsonpath.Option;\nimport com.jayway.jsonpath.PathNotFoundException;\nimport com.jayway.jsonpath.Predicate;\nimport com.jayway.jsonpath.internal.Path;\nimport com.jayway.jsonpath.internal.Utils;\nimport com.jayway.jsonpath.internal.path.PathCompiler;\nimport com.jayway.jsonpath.internal.path.PredicateContextImpl;\nimport com.jayway.jsonpath.spi.json.JsonProvider;\nimport net.minidev.json.parser.JSONParser;\nimport net.minidev.json.parser.ParseException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Moved these nodes out of the ValueNode abstract class.\n * This is to avoid this possible issue:\n *\n * Classes that refer to their own subclasses in their static initializers or in static fields.\n * Such references can cause JVM-level deadlocks in multithreaded environment, when\n * one thread tries to load superclass and another thread tries to load subclass at the same time.\n */\npublic interface ValueNodes {\n\n    NullNode NULL_NODE = new NullNode();\n    BooleanNode TRUE = new BooleanNode(\"true\");\n    BooleanNode FALSE = new BooleanNode(\"false\");\n    UndefinedNode UNDEFINED = new UndefinedNode();\n\n    //----------------------------------------------------\n    //\n    // ValueNode Implementations\n    //\n    //----------------------------------------------------\n    class PatternNode extends ValueNode {\n        private final String pattern;\n        private final Pattern compiledPattern;\n        private final String flags;\n\n        PatternNode(CharSequence charSequence) {\n            String tmp = charSequence.toString();\n            int begin = tmp.indexOf('/');\n            int end = tmp.lastIndexOf('/');\n            this.pattern = tmp.substring(begin + 1, end);\n            int flagsIndex = end + 1;\n            this.flags = tmp.length() > flagsIndex ? tmp.substring(flagsIndex) : \"\";\n            this.compiledPattern = Pattern.compile(pattern, PatternFlag.parseFlags(flags.toCharArray()));\n        }\n\n        PatternNode(Pattern pattern) {\n            this.pattern = pattern.pattern();\n            this.compiledPattern = pattern;\n            this.flags = PatternFlag.parseFlags(pattern.flags());\n        }\n\n\n        Pattern getCompiledPattern() {\n            return compiledPattern;\n        }\n\n        @Override\n        public Class<?> type(Predicate.PredicateContext ctx) {\n            return Void.TYPE;\n        }\n\n        public boolean isPatternNode() {\n            return true;\n        }\n\n        public PatternNode asPatternNode() {\n            return this;\n        }\n\n        @Override\n        public String toString() {\n\n            if(!pattern.startsWith(\"/\")){\n                return \"/\" + pattern + \"/\" + flags;\n            } else {\n                return pattern;\n            }\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (!(o instanceof PatternNode)) return false;\n\n            PatternNode that = (PatternNode) o;\n\n            return !(compiledPattern != null ? !compiledPattern.equals(that.compiledPattern) : that.compiledPattern != null);\n\n        }\n    }\n\n    class JsonNode extends ValueNode {\n        private final Object json;\n        private final boolean parsed;\n\n        JsonNode(CharSequence charSequence) {\n            json = charSequence.toString();\n            parsed = false;\n        }\n\n        JsonNode(Object parsedJson) {\n            json = parsedJson;\n            parsed = true;\n        }\n\n        @Override\n        public Class<?> type(Predicate.PredicateContext ctx) {\n            if(isArray(ctx)) return List.class;\n            else if(isMap(ctx)) return Map.class;\n            else if(parse(ctx) instanceof Number) return Number.class;\n            else if(parse(ctx) instanceof String) return String.class;\n            else if(parse(ctx) instanceof Boolean) return Boolean.class;\n            else return Void.class;\n        }\n\n        public boolean isJsonNode() {\n            return true;\n        }\n\n        public JsonNode asJsonNode() {\n            return this;\n        }\n\n        public ValueNode asValueListNode(Predicate.PredicateContext ctx){\n            if(!isArray(ctx)){\n                return UNDEFINED;\n            } else {\n                return new ValueListNode(Collections.unmodifiableList((List) parse(ctx)));\n            }\n        }\n\n        public Object parse(Predicate.PredicateContext ctx){\n            try {\n              return parsed ? json : new JSONParser(JSONParser.MODE_PERMISSIVE).parse(json.toString());\n            } catch (ParseException e) {\n              throw new IllegalArgumentException(e);\n            }\n        }\n\n        public boolean isParsed() {\n            return parsed;\n        }\n\n        public Object getJson() {\n            return json;\n        }\n\n        public boolean isArray(Predicate.PredicateContext ctx) {\n            return parse(ctx) instanceof List;\n        }\n\n        public boolean isMap(Predicate.PredicateContext ctx) {\n            return parse(ctx) instanceof Map;\n        }\n\n        public int length(Predicate.PredicateContext ctx) {\n            return isArray(ctx) ? ((List<?>) parse(ctx)).size() : -1;\n        }\n\n        public boolean isEmpty(Predicate.PredicateContext ctx) {\n            if (isArray(ctx) || isMap(ctx)) return ((Collection<?>) parse(ctx)).size() == 0;\n            else if((parse(ctx) instanceof String)) return ((String)parse(ctx)).length() == 0;\n            return true;\n        }\n\n        @Override\n        public String toString() {\n            return json.toString();\n        }\n\n        public boolean equals(JsonNode jsonNode, Predicate.PredicateContext ctx) {\n            if (this == jsonNode) return true;\n            return !(json != null ? !json.equals(jsonNode.parse(ctx)) : jsonNode.json != null);\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (!(o instanceof JsonNode)) return false;\n\n            JsonNode jsonNode = (JsonNode) o;\n\n            return !(json != null ? !json.equals(jsonNode.json) : jsonNode.json != null);\n        }\n    }\n\n    class StringNode extends ValueNode {\n        private final String string;\n        private boolean useSingleQuote = true;\n\n        StringNode(CharSequence charSequence, boolean escape) {\n            if (escape && charSequence.length() > 1) {\n                char open = charSequence.charAt(0);\n                char close = charSequence.charAt(charSequence.length()-1);\n                if (open == '\\'' && close == '\\'') {\n                    charSequence = charSequence.subSequence(1, charSequence.length()-1);\n                } else if (open == '\"' && close == '\"') {\n                    charSequence = charSequence.subSequence(1, charSequence.length()-1);\n                    useSingleQuote = false;\n                }\n                string = Utils.unescape(charSequence.toString());\n            } else {\n                string = charSequence.toString();\n            }\n        }\n\n        @Override\n        public NumberNode asNumberNode() {\n            BigDecimal number = null;\n            try {\n                number = new BigDecimal(string);\n            } catch (NumberFormatException nfe){\n                return NumberNode.NAN;\n            }\n            return new NumberNode(number);\n        }\n\n        public String getString() {\n            return string;\n        }\n\n        public int length(){\n            return getString().length();\n        }\n\n        public boolean isEmpty(){\n            return getString().isEmpty();\n        }\n\n        public boolean contains(String str) {\n            return getString().contains(str);\n        }\n\n        @Override\n        public Class<?> type(Predicate.PredicateContext ctx) {\n            return String.class;\n        }\n\n        public boolean isStringNode() {\n            return true;\n        }\n\n        public StringNode asStringNode() {\n            return this;\n        }\n\n        @Override\n        public String toString() {\n            String quote = useSingleQuote ? \"'\" : \"\\\"\";\n            return quote + Utils.escape(string, true) + quote;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (!(o instanceof StringNode) && !(o instanceof NumberNode)) return false;\n\n            StringNode that = ((ValueNode) o).asStringNode();\n\n            return !(string != null ? !string.equals(that.getString()) : that.getString() != null);\n\n        }\n    }\n\n    class NumberNode extends ValueNode {\n\n        public static NumberNode NAN = new NumberNode((BigDecimal)null);\n\n        private final BigDecimal number;\n\n        NumberNode(BigDecimal number) {\n            this.number = number;\n        }\n        NumberNode(CharSequence num) {\n            number = new BigDecimal(num.toString());\n        }\n\n        @Override\n        public StringNode asStringNode() {\n            return new StringNode(number.toString(), false);\n        }\n\n        public BigDecimal getNumber() {\n            return number;\n        }\n\n        @Override\n        public Class<?> type(Predicate.PredicateContext ctx) {\n            return Number.class;\n        }\n\n        public boolean isNumberNode() {\n            return true;\n        }\n\n        public NumberNode asNumberNode() {\n            return this;\n        }\n\n        @Override\n        public String toString() {\n            return number.toString();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (!(o instanceof NumberNode) && !(o instanceof StringNode)) return false;\n\n            NumberNode that = ((ValueNode)o).asNumberNode();\n\n            if(that == NumberNode.NAN){\n                return false;\n            } else {\n                return number.compareTo(that.number) == 0;\n            }\n        }\n    }\n\n    //workaround for issue: https://github.com/json-path/JsonPath/issues/613\n    class OffsetDateTimeNode extends ValueNode {\n\n        private final OffsetDateTime dateTime;\n\n\n        OffsetDateTimeNode(OffsetDateTime dateTime) {\n            this.dateTime = dateTime;\n        }\n\n        OffsetDateTimeNode(CharSequence date) {\n            dateTime = OffsetDateTime.parse(date);\n        }\n\n        @Override\n        public StringNode asStringNode() {\n            return new StringNode(dateTime.toString(), false);\n        }\n\n        public OffsetDateTime getDate() {\n            return dateTime;\n        }\n\n        @Override\n        public Class<?> type(Predicate.PredicateContext ctx) {\n            return OffsetDateTimeNode.class;\n        }\n\n        public boolean isOffsetDateTimeNode() {\n            return true;\n        }\n\n        public OffsetDateTimeNode asOffsetDateTimeNode() {\n            return this;\n        }\n\n        @Override\n        public String toString() {\n            return dateTime.toString();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (!(o instanceof OffsetDateTimeNode) && !(o instanceof StringNode)) return false;\n            OffsetDateTimeNode that = ((ValueNode)o).asOffsetDateTimeNode();\n            return dateTime.compareTo(that.dateTime) == 0;\n        }\n    }\n\n\n\n    class BooleanNode extends ValueNode {\n        private final Boolean value;\n\n        private BooleanNode(CharSequence boolValue) {\n            value = Boolean.parseBoolean(boolValue.toString());\n        }\n\n        @Override\n        public Class<?> type(Predicate.PredicateContext ctx) {\n            return Boolean.class;\n        }\n\n        public boolean isBooleanNode() {\n            return true;\n        }\n\n        public BooleanNode asBooleanNode() {\n            return this;\n        }\n\n        public boolean getBoolean() {\n            return value;\n        }\n\n        @Override\n        public String toString() {\n            return value.toString();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (!(o instanceof BooleanNode)) return false;\n\n            BooleanNode that = (BooleanNode) o;\n\n            return !(value != null ? !value.equals(that.value) : that.value != null);\n        }\n    }\n\n\n\n\n\n    class ClassNode extends ValueNode {\n        private final Class clazz;\n\n        ClassNode(Class clazz) {\n            this.clazz = clazz;\n        }\n\n        @Override\n        public Class<?> type(Predicate.PredicateContext ctx) {\n            return Class.class;\n        }\n\n        public boolean isClassNode() {\n            return true;\n        }\n\n        public ClassNode asClassNode() {\n            return this;\n        }\n\n        public Class getClazz() {\n            return clazz;\n        }\n\n        @Override\n        public String toString() {\n            return clazz.getName();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (!(o instanceof ClassNode)) return false;\n\n            ClassNode that = (ClassNode) o;\n\n            return !(clazz != null ? !clazz.equals(that.clazz) : that.clazz != null);\n        }\n    }\n\n    class NullNode extends ValueNode {\n\n        private NullNode() {}\n\n        @Override\n        public Class<?> type(Predicate.PredicateContext ctx) {\n            return Void.class;\n        }\n\n        @Override\n        public boolean isNullNode() {\n            return true;\n        }\n\n        @Override\n        public NullNode asNullNode() {\n            return this;\n        }\n\n        @Override\n        public String toString() {\n            return \"null\";\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (!(o instanceof NullNode)) return false;\n\n            return true;\n        }\n    }\n\n    class UndefinedNode extends ValueNode {\n\n        @Override\n        public Class<?> type(Predicate.PredicateContext ctx) {\n            return Void.class;\n        }\n\n        public UndefinedNode asUndefinedNode() {\n            return this;\n        }\n\n        public boolean isUndefinedNode() {\n            return true;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            return false;\n        }\n    }\n\n    class PredicateNode extends ValueNode {\n\n        private final Predicate predicate;\n\n        public PredicateNode(Predicate predicate) {\n            this.predicate = predicate;\n        }\n\n        public Predicate getPredicate() {\n            return predicate;\n        }\n\n        public PredicateNode asPredicateNode() {\n            return this;\n        }\n\n        @Override\n        public Class<?> type(Predicate.PredicateContext ctx) {\n            return Void.class;\n        }\n\n        public boolean isPredicateNode() {\n            return true;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            return false;\n        }\n\n        @Override\n        public String toString() {\n            return predicate.toString();\n        }\n    }\n\n    class ValueListNode extends ValueNode implements Iterable<ValueNode> {\n\n        private List<ValueNode> nodes = new ArrayList<ValueNode>();\n\n        public ValueListNode(Collection<?> values) {\n            for (Object value : values) {\n                nodes.add(toValueNode(value));\n            }\n        }\n\n        public boolean contains(ValueNode node){\n            return nodes.contains(node);\n        }\n\n        public boolean subsetof(ValueListNode right) {\n            for (ValueNode leftNode : nodes) {\n                if (!right.nodes.contains(leftNode)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        public List<ValueNode> getNodes() {\n            return Collections.unmodifiableList(nodes);\n        }\n\n        @Override\n        public Class<?> type(Predicate.PredicateContext ctx) {\n            return List.class;\n        }\n\n        public boolean isValueListNode() {\n            return true;\n        }\n\n        public ValueListNode asValueListNode() {\n            return this;\n        }\n\n        @Override\n        public String toString() {\n            return \"[\" + Utils.join(\",\", nodes) + \"]\";\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (!(o instanceof ValueListNode)) return false;\n\n            ValueListNode that = (ValueListNode) o;\n\n            return nodes.equals(that.nodes);\n        }\n\n        @Override\n        public Iterator<ValueNode> iterator() {\n            return nodes.iterator();\n        }\n    }\n\n    class PathNode extends ValueNode {\n\n        private static final Logger logger = LoggerFactory.getLogger(PathNode.class);\n\n        private final Path path;\n        private final boolean existsCheck;\n        private final boolean shouldExist;\n\n        PathNode(Path path) {\n            this(path, false, false);\n        }\n\n        PathNode(CharSequence charSequence, boolean existsCheck, boolean shouldExist) {\n            this(PathCompiler.compile(charSequence.toString()), existsCheck, shouldExist);\n        }\n\n        PathNode(Path path, boolean existsCheck, boolean shouldExist) {\n            this.path = path;\n            this.existsCheck = existsCheck;\n            this.shouldExist = shouldExist;\n            logger.trace(\"PathNode {} existsCheck: {}\", path, existsCheck);\n        }\n\n        public Path getPath() {\n            return path;\n        }\n\n        public boolean isExistsCheck() {\n            return existsCheck;\n        }\n\n        public boolean shouldExists() {\n            return shouldExist;\n        }\n\n        @Override\n        public Class<?> type(Predicate.PredicateContext ctx) {\n            return Void.class;\n        }\n\n        public boolean isPathNode() {\n            return true;\n        }\n\n        public PathNode asPathNode() {\n            return this;\n        }\n\n        public PathNode asExistsCheck(boolean shouldExist) {\n            return new PathNode(path, true, shouldExist);\n        }\n\n        @Override\n        public String toString() {\n            return existsCheck && ! shouldExist ? Utils.concat(\"!\" , path.toString()) : path.toString();\n        }\n\n        public ValueNode evaluate(Predicate.PredicateContext ctx) {\n            if (isExistsCheck()) {\n                try {\n                    Configuration c = Configuration.builder().jsonProvider(ctx.configuration().jsonProvider()).options(Option.REQUIRE_PROPERTIES).build();\n                    Object result = path.evaluate(ctx.item(), ctx.root(), c).getValue(false);\n                    return result == JsonProvider.UNDEFINED ? FALSE : TRUE;\n                } catch (PathNotFoundException e) {\n                    return FALSE;\n                }\n            } else {\n                try {\n                    Object res;\n                    if (ctx instanceof PredicateContextImpl) {\n                        //This will use cache for document ($) queries\n                        PredicateContextImpl ctxi = (PredicateContextImpl) ctx;\n                        res = ctxi.evaluate(path);\n                    } else {\n                        Object doc = path.isRootPath() ? ctx.root() : ctx.item();\n                        res = path.evaluate(doc, ctx.root(), ctx.configuration()).getValue();\n                    }\n                    res = ctx.configuration().jsonProvider().unwrap(res);\n\n                    if (res instanceof Number) return ValueNode.createNumberNode(res.toString());\n                    else if (res instanceof String) return ValueNode.createStringNode(res.toString(), false);\n                    else if (res instanceof Boolean) return ValueNode.createBooleanNode(res.toString());\n                    else if (res instanceof OffsetDateTime) return ValueNode.createOffsetDateTimeNode(res.toString()); //workaround for issue: https://github.com/json-path/JsonPath/issues/613\n                    else if (res == null) return NULL_NODE;\n                    else if (ctx.configuration().jsonProvider().isArray(res)) return ValueNode.createJsonNode(ctx.configuration().mappingProvider().map(res, List.class, ctx.configuration()));\n                    else if (ctx.configuration().jsonProvider().isMap(res)) return ValueNode.createJsonNode(ctx.configuration().mappingProvider().map(res, Map.class, ctx.configuration()));\n                    else throw new JsonPathException(\"Could not convert \" + res.getClass().toString()+\":\"+ res.toString() + \" to a ValueNode\");\n                } catch (PathNotFoundException e) {\n                    return UNDEFINED;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/ParamType.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\n/**\n * Created by mgreenwood on 12/11/15.\n */\npublic enum ParamType {\n    JSON,\n    PATH\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/Parameter.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.Path;\nimport com.jayway.jsonpath.internal.function.latebinding.ILateBindingValue;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * Defines a parameter as passed to a function with late binding support for lazy evaluation.\n */\npublic class Parameter {\n    private ParamType type;\n    private Path path;\n    private ILateBindingValue lateBinding;\n    private Boolean evaluated = false;\n    private String json;\n\n    public Parameter() {}\n\n    public Parameter(String json) {\n        this.json = json;\n        this.type = ParamType.JSON;\n    }\n\n    public Parameter(Path path) {\n        this.path = path;\n        this.type = ParamType.PATH;\n    }\n\n    public Object getValue() {\n        return lateBinding.get();\n    }\n\n    public void setLateBinding(ILateBindingValue lateBinding) {\n        this.lateBinding = lateBinding;\n    }\n\n    public Path getPath() {\n        return path;\n    }\n\n    public void setEvaluated(Boolean evaluated) {\n        this.evaluated = evaluated;\n    }\n\n    public boolean hasEvaluated() {\n        return evaluated;\n    }\n\n    public ParamType getType() {\n        return type;\n    }\n\n    public void setType(ParamType type) {\n        this.type = type;\n    }\n\n    public void setPath(Path path) {\n        this.path = path;\n    }\n\n    public String getJson() {\n        return json;\n    }\n\n    public void setJson(String json) {\n        this.json = json;\n    }\n\n    public ILateBindingValue getILateBingValue(){\n        return lateBinding;\n    }\n\n    /**\n     * Translate the collection of parameters into a collection of values of type T.\n     *\n     * @param type\n     *      The type to translate the collection into.\n     *\n     * @param ctx\n     *      Context.\n     *\n     * @param parameters\n     *      Collection of parameters.\n     *\n     * @param <T>\n     *      Type T returned as a List of T.\n     *\n     * @return\n     *      List of T either empty or containing contents.\n     */\n    public static <T> List<T> toList(final Class<T> type, final EvaluationContext ctx, final List<Parameter> parameters) {\n        List<T> values = new ArrayList();\n        if (null != parameters) {\n            for (Parameter param : parameters) {\n                consume(type, ctx, values, param.getValue());\n            }\n        }\n        return values;\n    }\n\n    /**\n     * Either consume the object as an array and add each element to the collection, or alternatively add each element\n     *\n     * @param expectedType\n     *      the expected class type to consume, if null or not of this type the element is not added to the array.\n     *\n     * @param ctx\n     *      the JSON context to determine if this is an array or value.\n     *\n     * @param collection\n     *      The collection to append into.\n     *\n     * @param value\n     *      The value to evaluate.\n     */\n    public static void consume(Class expectedType, EvaluationContext ctx, Collection collection, Object value) {\n        if (ctx.configuration().jsonProvider().isArray(value)) {\n            for (Object o : ctx.configuration().jsonProvider().toIterable(value)) {\n                if (o != null && expectedType.isAssignableFrom(o.getClass())) {\n                    collection.add(o);\n                } else if (o != null && expectedType == String.class) {\n                    collection.add(o.toString());\n                }\n            }\n        } else {\n            if (value != null && expectedType.isAssignableFrom(value.getClass())) {\n                collection.add(value);\n            } else if (value != null && expectedType == String.class) {\n                collection.add(value.toString());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/PassthruPathFunction.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.PathRef;\n\nimport java.util.List;\n\n/**\n * Defines the default behavior which is to return the model that is provided as input as output\n *\n * Created by mattg on 6/26/15.\n */\npublic class PassthruPathFunction implements PathFunction {\n\n    @Override\n    public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {\n        return model;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/PathFunction.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.PathRef;\n\nimport java.util.List;\n\n/**\n * Defines the pattern by which a function can be executed over the result set in the particular path\n * being grabbed.  The Function's input is the content of the data from the json path selector and its output\n * is defined via the functions behavior.  Thus transformations in types can take place.  Additionally, functions\n * can accept multiple selectors in order to produce their output.\n *\n * Created by matt@mjgreenwood.net on 6/26/15.\n */\npublic interface PathFunction {\n\n    /**\n     * Invoke the function and output a JSON object (or scalar) value which will be the result of executing the path\n     *\n     * @param currentPath\n     *      The current path location inclusive of the function name\n     * @param parent\n     *      The path location above the current function\n     *\n     * @param model\n     *      The JSON model as input to this particular function\n     *\n     * @param ctx\n     *      Eval context, state bag used as the path is traversed, maintains the result of executing\n     *\n     * @param parameters\n     * @return result\n     */\n    Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters);\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/PathFunctionFactory.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.InvalidPathException;\nimport com.jayway.jsonpath.internal.function.json.Append;\nimport com.jayway.jsonpath.internal.function.json.KeySetFunction;\nimport com.jayway.jsonpath.internal.function.numeric.Average;\nimport com.jayway.jsonpath.internal.function.numeric.Max;\nimport com.jayway.jsonpath.internal.function.numeric.Min;\nimport com.jayway.jsonpath.internal.function.numeric.StandardDeviation;\nimport com.jayway.jsonpath.internal.function.numeric.Sum;\nimport com.jayway.jsonpath.internal.function.sequence.First;\nimport com.jayway.jsonpath.internal.function.sequence.Index;\nimport com.jayway.jsonpath.internal.function.sequence.Last;\nimport com.jayway.jsonpath.internal.function.text.Concatenate;\nimport com.jayway.jsonpath.internal.function.text.Length;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Implements a factory that given a name of the function will return the Function implementation, or null\n * if the value is not obtained.\n *\n * Leverages the function's name in order to determine which function to execute which is maintained internally\n * here via a static map\n *\n */\npublic class PathFunctionFactory {\n\n    public static final Map<String, Class> FUNCTIONS;\n\n    static {\n        // New functions should be added here and ensure the name is not overridden\n        Map<String, Class> map = new HashMap<String, Class>();\n\n        // Math Functions\n        map.put(\"avg\", Average.class);\n        map.put(\"stddev\", StandardDeviation.class);\n        map.put(\"sum\", Sum.class);\n        map.put(\"min\", Min.class);\n        map.put(\"max\", Max.class);\n\n        // Text Functions\n        map.put(\"concat\", Concatenate.class);\n\n        // JSON Entity Functions\n        map.put(Length.TOKEN_NAME, Length.class);\n        map.put(\"size\", Length.class);\n        map.put(\"append\", Append.class);\n        map.put(\"keys\", KeySetFunction.class);\n        \n        // Sequential Functions\n        map.put(\"first\", First.class);\n        map.put(\"last\", Last.class);\n        map.put(\"index\", Index.class);\n\n\n        FUNCTIONS = Collections.unmodifiableMap(map);\n    }\n\n    /**\n     * Returns the function by name or throws InvalidPathException if function not found.\n     *\n     * @see #FUNCTIONS\n     * @see PathFunction\n     *\n     * @param name\n     *      The name of the function\n     *\n     * @return\n     *      The implementation of a function\n     *\n     * @throws InvalidPathException\n     */\n    public static PathFunction newFunction(String name) throws InvalidPathException {\n        Class functionClazz = FUNCTIONS.get(name);\n        if(functionClazz == null){\n            throw new InvalidPathException(\"Function with name: \" + name + \" does not exist.\");\n        } else {\n            try {\n                return (PathFunction)functionClazz.newInstance();\n            } catch (Exception e) {\n                throw new InvalidPathException(\"Function of name: \" + name + \" cannot be created\", e);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/json/Append.java",
    "content": "package com.jayway.jsonpath.internal.function.json;\n\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.PathRef;\nimport com.jayway.jsonpath.internal.function.Parameter;\nimport com.jayway.jsonpath.internal.function.PathFunction;\nimport com.jayway.jsonpath.spi.json.JsonProvider;\n\nimport java.util.List;\n\n/**\n * Appends JSON structure to the current document so that you can utilize the JSON added thru another function call.\n * If there are multiple parameters then this function call will add each element that is json to the structure\n *\n * Created by mgreenwood on 12/14/15.\n */\npublic class Append implements PathFunction {\n    @Override\n    public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {\n        JsonProvider jsonProvider = ctx.configuration().jsonProvider();\n        if (parameters != null && parameters.size() > 0) {\n            for (Parameter param : parameters) {\n                if (jsonProvider.isArray(model)) {\n                    int len = jsonProvider.length(model);\n                    jsonProvider.setArrayIndex(model, len, param.getValue());\n                }\n            }\n        }\n        return model;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/json/KeySetFunction.java",
    "content": "package com.jayway.jsonpath.internal.function.json;\n\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.PathRef;\nimport com.jayway.jsonpath.internal.function.Parameter;\nimport com.jayway.jsonpath.internal.function.PathFunction;\n\nimport java.util.List;\n\n/**\n * Author: Sergey Saiyan sergey.sova42@gmail.com\n * Created at 21/02/2018.\n */\npublic class KeySetFunction implements PathFunction {\n\n    @Override\n    public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {\n        if (ctx.configuration().jsonProvider().isMap(model)) {\n            return ctx.configuration().jsonProvider().getPropertyKeys(model);\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/latebinding/ILateBindingValue.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.function.latebinding;\n\n/**\n * Obtain the late binding value at runtime rather than storing the value in the cache thus trashing the cache\n *\n */\npublic interface ILateBindingValue {\n    /**\n     * Obtain the value of the parameter at runtime using the parameter state and invocation of other late binding values\n     * rather than maintaining cached state which ends up in a global store and won't change as a result of external\n     * reference changes.\n     *\n     * @return\n     *      The value of evaluating the context at runtime.\n     */\n    Object get();\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/latebinding/JsonLateBindingValue.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.function.latebinding;\n\nimport com.jayway.jsonpath.internal.function.Parameter;\nimport com.jayway.jsonpath.spi.json.JsonProvider;\n\n/**\n * Defines the JSON document Late binding approach to function arguments.\n *\n */\npublic class JsonLateBindingValue implements ILateBindingValue {\n    private final JsonProvider jsonProvider;\n    private final Parameter jsonParameter;\n\n    public JsonLateBindingValue(JsonProvider jsonProvider, Parameter jsonParameter) {\n        this.jsonProvider = jsonProvider;\n        this.jsonParameter = jsonParameter;\n    }\n\n    /**\n     * Evaluate the JSON document at the point of need using the JSON parameter and associated document model which may\n     * itself originate from yet another function thus recursively invoking late binding methods.\n     *\n     * @return the late value\n     */\n    @Override\n    public Object get() {\n        return jsonProvider.parse(jsonParameter.getJson());\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/latebinding/PathLateBindingValue.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.function.latebinding;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.internal.Path;\n\nimport java.util.Objects;\n\n/**\n * Defines the contract for late bindings, provides document state and enough context to perform the evaluation at a later\n * date such that we can operate on a dynamically changing value.\n *\n * Acts like a lambda function with references, but since we're supporting JDK 6+, we're left doing this...\n *\n */\npublic class PathLateBindingValue implements ILateBindingValue {\n    private final Path path;\n    private final String rootDocument;\n    private final Configuration configuration;\n    private final Object result;\n    public PathLateBindingValue(final Path path, final Object rootDocument, final Configuration configuration) {\n        this.path = path;\n        this.rootDocument = rootDocument.toString();\n        this.configuration = configuration;\n        this.result = path.evaluate(rootDocument, rootDocument, configuration).getValue();\n    }\n\n    /**\n     *\n     * @return the late value\n     */\n    public Object get() {\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        PathLateBindingValue that = (PathLateBindingValue) o;\n        return Objects.equals(path, that.path) &&\n                rootDocument.equals(that.rootDocument) &&\n                Objects.equals(configuration, that.configuration);\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/AbstractAggregation.java",
    "content": "package com.jayway.jsonpath.internal.function.numeric;\n\nimport com.jayway.jsonpath.JsonPathException;\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.PathRef;\nimport com.jayway.jsonpath.internal.function.Parameter;\nimport com.jayway.jsonpath.internal.function.PathFunction;\n\nimport java.util.List;\n\n/**\n * Defines the pattern for processing numerical values via an abstract implementation that iterates over the collection\n * of JSONArray entities and verifies that each is a numerical value and then passes that along the abstract methods\n *\n *\n * Created by mattg on 6/26/15.\n */\npublic abstract class AbstractAggregation implements PathFunction {\n\n    /**\n     * Defines the next value in the array to the mathmatical function\n     *\n     * @param value\n     *      The numerical value to process next\n     */\n    protected abstract void next(Number value);\n\n    /**\n     * Obtains the value generated via the series of next value calls\n     *\n     * @return\n     *      A numerical answer based on the input value provided\n     */\n    protected abstract Number getValue();\n\n    @Override\n    public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {\n        int count = 0;\n        if(ctx.configuration().jsonProvider().isArray(model)){\n\n            Iterable<?> objects = ctx.configuration().jsonProvider().toIterable(model);\n            for (Object obj : objects) {\n                if (obj instanceof Number) {\n                    Number value = (Number) obj;\n                    count++;\n                    next(value);\n                }\n            }\n        }\n        if (parameters != null) {\n            for (Number value : Parameter.toList(Number.class, ctx, parameters)) {\n                count++;\n                next(value);\n            }\n        }\n        if (count != 0) {\n            return getValue();\n        }\n        throw new JsonPathException(\"Aggregation function attempted to calculate value using empty array\");\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/Average.java",
    "content": "package com.jayway.jsonpath.internal.function.numeric;\n\n/**\n * Provides the average of a series of numbers in a JSONArray\n *\n * Created by mattg on 6/26/15.\n */\npublic class Average extends AbstractAggregation {\n\n    private Double summation = 0d;\n    private Double count = 0d;\n\n    @Override\n    protected void next(Number value) {\n        count++;\n        summation += value.doubleValue();\n    }\n\n    @Override\n    protected Number getValue() {\n        if (count != 0d) {\n            return summation / count;\n        }\n        return 0d;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/Max.java",
    "content": "package com.jayway.jsonpath.internal.function.numeric;\n\n/**\n * Defines the summation of a series of JSONArray numerical values\n *\n * Created by mattg on 6/26/15.\n */\npublic class Max extends AbstractAggregation {\n    private Double max = Double.MIN_VALUE;\n\n    @Override\n    protected void next(Number value) {\n        if (max < value.doubleValue()) {\n            max = value.doubleValue();\n        }\n    }\n\n    @Override\n    protected Number getValue() {\n        return max;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/Min.java",
    "content": "package com.jayway.jsonpath.internal.function.numeric;\n\n/**\n * Defines the summation of a series of JSONArray numerical values\n *\n * Created by mattg on 6/26/15.\n */\npublic class Min extends AbstractAggregation {\n    private Double min = Double.MAX_VALUE;\n\n    @Override\n    protected void next(Number value) {\n        if (min > value.doubleValue()) {\n            min = value.doubleValue();\n        }\n    }\n\n    @Override\n    protected Number getValue() {\n        return min;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/StandardDeviation.java",
    "content": "package com.jayway.jsonpath.internal.function.numeric;\n\n/**\n * Provides the standard deviation of a series of numbers\n *\n * Created by mattg on 6/27/15.\n */\npublic class StandardDeviation extends AbstractAggregation {\n    private Double sumSq = 0d;\n    private Double sum = 0d;\n    private Double count = 0d;\n\n    @Override\n    protected void next(Number value) {\n        sum += value.doubleValue();\n        sumSq += value.doubleValue() * value.doubleValue();\n        count++;\n    }\n\n    @Override\n    protected Number getValue() {\n        return Math.sqrt(sumSq/count - sum*sum/count/count);\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/numeric/Sum.java",
    "content": "package com.jayway.jsonpath.internal.function.numeric;\n\n/**\n * Defines the summation of a series of JSONArray numerical values\n *\n * Created by mattg on 6/26/15.\n */\npublic class Sum extends AbstractAggregation {\n    private Double summation = 0d;\n\n    @Override\n    protected void next(Number value) {\n        summation += value.doubleValue();\n    }\n\n    @Override\n    protected Number getValue() {\n        return summation;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/sequence/AbstractSequenceAggregation.java",
    "content": "package com.jayway.jsonpath.internal.function.sequence;\n\nimport com.jayway.jsonpath.JsonPathException;\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.PathRef;\nimport com.jayway.jsonpath.internal.function.Parameter;\nimport com.jayway.jsonpath.internal.function.PathFunction;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Defines the pattern for taking item from collection of JSONArray by index\n *\n * Created by git9527 on 6/11/22.\n */\npublic abstract class AbstractSequenceAggregation implements PathFunction {\n    \n    protected abstract int targetIndex(EvaluationContext ctx, List<Parameter> parameters);\n    \n    @Override\n    public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {\n        if(ctx.configuration().jsonProvider().isArray(model)){\n\n            Iterable<?> objects = ctx.configuration().jsonProvider().toIterable(model);\n            List<Object> objectList = new ArrayList<>();\n            objects.forEach(objectList::add);\n            int targetIndex = this.targetIndex(ctx, parameters);\n            if (targetIndex >= 0) {\n                return objectList.get(targetIndex);\n            } else {\n                int realIndex = objectList.size() + targetIndex;\n                if (realIndex > 0) {\n                    return objectList.get(realIndex);\n                } else {\n                    throw new JsonPathException(\"Target index:\" + targetIndex + \" larger than object count:\" + objectList.size());\n                }\n            }\n        }\n        throw new JsonPathException(\"Aggregation function attempted to calculate value using empty array\");\n    }\n    \n    protected int getIndexFromParameters(EvaluationContext ctx, List<Parameter> parameters) {\n        List<Number> numbers = Parameter.toList(Number.class, ctx, parameters);\n        return numbers.get(0).intValue();\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/sequence/First.java",
    "content": "package com.jayway.jsonpath.internal.function.sequence;\n\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.function.Parameter;\n\nimport java.util.List;\n\n/**\n * Take the first item from collection of JSONArray\n *\n * Created by git9527 on 6/11/22.\n */\npublic class First extends AbstractSequenceAggregation {\n    @Override\n    protected int targetIndex(EvaluationContext ctx, List<Parameter> parameters) {\n        return 0;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/sequence/Index.java",
    "content": "package com.jayway.jsonpath.internal.function.sequence;\n\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.function.Parameter;\n\nimport java.util.List;\n\n/**\n * Take the index from first Parameter, then the item from collection of JSONArray by index\n *\n * Created by git9527 on 6/11/22.\n */\npublic class Index extends AbstractSequenceAggregation {\n    @Override\n    protected int targetIndex(EvaluationContext ctx, List<Parameter> parameters) {\n        return getIndexFromParameters(ctx, parameters);\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/sequence/Last.java",
    "content": "package com.jayway.jsonpath.internal.function.sequence;\n\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.function.Parameter;\n\nimport java.util.List;\n\n/**\n * Take the first item from collection of JSONArray\n *\n * Created by git9527 on 6/11/22.\n */\npublic class Last extends AbstractSequenceAggregation {\n    @Override\n    protected int targetIndex(EvaluationContext ctx, List<Parameter> parameters) {\n        return -1;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/text/Concatenate.java",
    "content": "package com.jayway.jsonpath.internal.function.text;\n\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.PathRef;\nimport com.jayway.jsonpath.internal.function.Parameter;\nimport com.jayway.jsonpath.internal.function.PathFunction;\n\nimport java.util.List;\n\n/**\n * String function concat - simple takes a list of arguments and/or an array and concatenates them together to form a\n * single string\n *\n */\npublic class Concatenate implements PathFunction {\n    @Override\n    public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {\n        StringBuilder result = new StringBuilder();\n        if(ctx.configuration().jsonProvider().isArray(model)){\n            Iterable<?> objects = ctx.configuration().jsonProvider().toIterable(model);\n            for (Object obj : objects) {\n                if (obj instanceof String) {\n                    result.append(obj.toString());\n                }\n            }\n        }\n        if (parameters != null) {\n            for (String value : Parameter.toList(String.class, ctx, parameters)) {\n                result.append(value);\n            }\n        }\n        return result.toString();\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/function/text/Length.java",
    "content": "package com.jayway.jsonpath.internal.function.text;\n\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.Path;\nimport com.jayway.jsonpath.internal.PathRef;\nimport com.jayway.jsonpath.internal.function.Parameter;\nimport com.jayway.jsonpath.internal.function.PathFunction;\nimport com.jayway.jsonpath.internal.path.CompiledPath;\nimport com.jayway.jsonpath.internal.path.PathToken;\nimport com.jayway.jsonpath.internal.path.RootPathToken;\nimport com.jayway.jsonpath.internal.path.WildcardPathToken;\n\nimport java.util.List;\n\n/**\n * Provides the length of a JSONArray Object\n *\n * Created by mattg on 6/26/15.\n */\npublic class Length implements PathFunction {\n\n    public static final String TOKEN_NAME = \"length\";\n\n    /**\n     * When we calculate the length of a path, what we're asking is given the node we land on how many children does it\n     * have.  Thus when we wrote the original query what we really wanted was $..book.length() or $.length($..book.*)\n     *\n     * @param currentPath\n     *      The current path location inclusive of the function name\n     * @param parent\n     *      The path location above the current function\n     *\n     * @param model\n     *      The JSON model as input to this particular function\n     *\n     * @param ctx\n     *      Eval context, state bag used as the path is traversed, maintains the result of executing\n     *\n     * @param parameters\n     * @return\n     */\n    @Override\n    public Object invoke(String currentPath, PathRef parent, Object model, EvaluationContext ctx, List<Parameter> parameters) {\n        if (null != parameters && parameters.size() > 0) {\n\n            // Set the tail of the first parameter, when its not a function path parameter (which wouldn't make sense\n            // for length - to the wildcard such that we request all of its children so we can get back an array and\n            // take its length.\n            Parameter lengthOfParameter = parameters.get(0);\n            if (!lengthOfParameter.getPath().isFunctionPath()) {\n                Path path = lengthOfParameter.getPath();\n                if (path instanceof CompiledPath) {\n                    RootPathToken root = ((CompiledPath) path).getRoot();\n                    PathToken tail = root.getNext();\n                    while (null != tail && null != tail.getNext()) {\n                        tail = tail.getNext();\n                    }\n                    if (null != tail) {\n                        tail.setNext(new WildcardPathToken());\n                    }\n                }\n            }\n            Object innerModel = parameters.get(0).getPath().evaluate(model, model, ctx.configuration()).getValue();\n            if (ctx.configuration().jsonProvider().isArray(innerModel)) {\n                return ctx.configuration().jsonProvider().length(innerModel);\n            }\n        }\n        if (ctx.configuration().jsonProvider().isArray(model)) {\n            return ctx.configuration().jsonProvider().length(model);\n        } else if(ctx.configuration().jsonProvider().isMap(model)){\n            return ctx.configuration().jsonProvider().length(model);\n        }\n        return null;\n    }\n}"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/ArrayIndexOperation.java",
    "content": "package com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.InvalidPathException;\nimport com.jayway.jsonpath.internal.Utils;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.regex.Pattern;\n\nimport static java.lang.Character.isDigit;\n\npublic class ArrayIndexOperation {\n\n    private final static Pattern COMMA = Pattern.compile(\"\\\\s*,\\\\s*\");\n\n    private final List<Integer> indexes;\n\n    private ArrayIndexOperation(List<Integer> indexes) {\n        this.indexes = Collections.unmodifiableList(indexes);\n    }\n\n    public List<Integer> indexes() {\n        return indexes;\n    }\n\n    public boolean isSingleIndexOperation(){\n        return indexes.size() == 1;\n    }\n\n    @Override\n    public String toString() {\n        StringBuilder sb = new StringBuilder();\n        sb.append(\"[\");\n        sb.append(Utils.join(\",\", indexes));\n        sb.append(\"]\");\n\n        return sb.toString();\n    }\n\n    public static ArrayIndexOperation parse(String operation) {\n        //check valid chars\n        for (int i = 0; i < operation.length(); i++) {\n            char c = operation.charAt(i);\n            if (!isDigit(c) && c != ',' && c != ' ' && c != '-') {\n                throw new InvalidPathException(\"Failed to parse ArrayIndexOperation: \" + operation);\n            }\n        }\n        String[] tokens = COMMA.split(operation, -1);\n\n        List<Integer> tempIndexes = new ArrayList<Integer>(tokens.length);\n        for (String token : tokens) {\n            tempIndexes.add(parseInteger(token));\n        }\n\n        return new ArrayIndexOperation(tempIndexes);\n    }\n\n    private static Integer parseInteger(String token) {\n        try {\n            return Integer.parseInt(token);\n        } catch (Exception e){\n            throw new InvalidPathException(\"Failed to parse token in ArrayIndexOperation: \" + token, e);\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/ArrayIndexToken.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.internal.PathRef;\n\nimport static java.lang.String.format;\n\npublic class ArrayIndexToken extends ArrayPathToken {\n\n    private final ArrayIndexOperation arrayIndexOperation;\n\n    ArrayIndexToken(final ArrayIndexOperation arrayIndexOperation) {\n        this.arrayIndexOperation = arrayIndexOperation;\n    }\n\n    @Override\n    public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {\n        if (!checkArrayModel(currentPath, model, ctx))\n            return;\n        if (arrayIndexOperation.isSingleIndexOperation()) {\n            handleArrayIndex(arrayIndexOperation.indexes().get(0), currentPath, model, ctx);\n        } else {\n            for (Integer index : arrayIndexOperation.indexes()) {\n                handleArrayIndex(index, currentPath,  model, ctx);\n            }\n        }\n    }\n\n    @Override\n    public String getPathFragment() {\n        return arrayIndexOperation.toString();\n    }\n\n    @Override\n    public boolean isTokenDefinite() {\n        return arrayIndexOperation.isSingleIndexOperation();\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/ArrayPathToken.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.InvalidPathException;\nimport com.jayway.jsonpath.Option;\nimport com.jayway.jsonpath.PathNotFoundException;\n\nimport static java.lang.String.format;\n\npublic abstract class ArrayPathToken extends PathToken {\n\n    /**\n     * Check if model is non-null and array.\n     * @param currentPath\n     * @param model\n     * @param ctx\n     * @return false if current evaluation call must be skipped, true otherwise\n     * @throws PathNotFoundException if model is null and evaluation must be interrupted\n     * @throws InvalidPathException if model is not an array and evaluation must be interrupted\n     */\n    protected boolean checkArrayModel(String currentPath, Object model, EvaluationContextImpl ctx) {\n        if (model == null){\n            if (!isUpstreamDefinite()\n                    || ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)) {\n                return false;\n            } else {\n                throw new PathNotFoundException(\"The path \" + currentPath + \" is null\");\n            }\n        }\n        if (!ctx.jsonProvider().isArray(model)) {\n            if (!isUpstreamDefinite()\n                    || ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)) {\n                return false;\n            } else {\n                throw new PathNotFoundException(format(\"Filter: %s can only be applied to arrays. Current context is: %s\", toString(), model));\n            }\n        }\n        return true;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/ArraySliceOperation.java",
    "content": "package com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.InvalidPathException;\n\nimport static java.lang.Character.isDigit;\n\npublic class ArraySliceOperation {\n\n    public enum Operation {\n        SLICE_FROM,\n        SLICE_TO,\n        SLICE_BETWEEN\n    }\n\n    private final Integer from;\n    private final Integer to;\n    private final Operation operation;\n\n    private ArraySliceOperation(Integer from, Integer to, Operation operation) {\n        this.from = from;\n        this.to = to;\n        this.operation = operation;\n    }\n\n    public Integer from() {\n        return from;\n    }\n\n    public Integer to() {\n        return to;\n    }\n\n    public Operation operation() {\n        return operation;\n    }\n\n    @Override\n    public String toString() {\n        StringBuilder sb = new StringBuilder();\n        sb.append(\"[\");\n        sb.append(from == null ? \"\" : from.toString());\n        sb.append(\":\");\n        sb.append(to == null ? \"\" : to.toString());\n        sb.append(\"]\");\n\n        return sb.toString();\n    }\n\n    public static ArraySliceOperation parse(String operation){\n        //check valid chars\n        for (int i = 0; i < operation.length(); i++) {\n            char c = operation.charAt(i);\n            if( !isDigit(c)  && c != '-' && c != ':'){\n                throw new InvalidPathException(\"Failed to parse SliceOperation: \" + operation);\n            }\n        }\n        String[] tokens = operation.split(\":\");\n\n        Integer tempFrom = tryRead(tokens, 0);\n        Integer tempTo = tryRead(tokens, 1);\n        Operation tempOperation;\n\n        if (tempFrom != null && tempTo == null) {\n            tempOperation = Operation.SLICE_FROM;\n        } else if (tempFrom != null) {\n            tempOperation = Operation.SLICE_BETWEEN;\n        } else if (tempTo != null) {\n            tempOperation = Operation.SLICE_TO;\n        } else {\n            throw new InvalidPathException(\"Failed to parse SliceOperation: \" + operation);\n        }\n\n        return new ArraySliceOperation(tempFrom, tempTo, tempOperation);\n    }\n\n    private static Integer tryRead(String[] tokens, int idx){\n        if(tokens.length > idx){\n            if(tokens[idx].equals(\"\")){\n                return null;\n            }\n            return Integer.parseInt(tokens[idx]);\n        } else {\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/ArraySliceToken.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.internal.PathRef;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class ArraySliceToken extends ArrayPathToken {\n\n    private static final Logger logger = LoggerFactory.getLogger(ArraySliceToken.class);\n\n    private final ArraySliceOperation operation;\n\n    ArraySliceToken(final ArraySliceOperation operation) {\n        this.operation = operation;\n    }\n\n    @Override\n    public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {\n        if (!checkArrayModel(currentPath, model, ctx))\n            return;\n        switch (operation.operation()) {\n            case SLICE_FROM:\n                sliceFrom(currentPath, parent, model, ctx);\n                break;\n            case SLICE_BETWEEN:\n                sliceBetween(currentPath, parent, model, ctx);\n                break;\n            case SLICE_TO:\n                sliceTo(currentPath, parent, model, ctx);\n                break;\n        }\n    }\n\n    private void sliceFrom(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {\n        int length = ctx.jsonProvider().length(model);\n        int from = operation.from();\n        if (from < 0) {\n            //calculate slice start from array length\n            from = length + from;\n        }\n        from = Math.max(0, from);\n\n        logger.debug(\"Slice from index on array with length: {}. From index: {} to: {}. Input: {}\", length, from, length - 1, toString());\n\n        if (length == 0 || from >= length) {\n            return;\n        }\n        for (int i = from; i < length; i++) {\n            handleArrayIndex(i, currentPath, model, ctx);\n        }\n    }\n\n    private void sliceBetween(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {\n        int length = ctx.jsonProvider().length(model);\n        int from = operation.from();\n        int to = operation.to();\n\n        to = Math.min(length, to);\n\n        if (from >= to || length == 0) {\n            return;\n        }\n\n        logger.debug(\"Slice between indexes on array with length: {}. From index: {} to: {}. Input: {}\", length, from, to, toString());\n\n        for (int i = from; i < to; i++) {\n            handleArrayIndex(i, currentPath, model, ctx);\n        }\n    }\n\n    private void sliceTo(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {\n        int length = ctx.jsonProvider().length(model);\n        if (length == 0) {\n            return;\n        }\n        int to = operation.to();\n        if (to < 0) {\n            //calculate slice end from array length\n            to = length + to;\n        }\n        to = Math.min(length, to);\n\n        logger.debug(\"Slice to index on array with length: {}. From index: 0 to: {}. Input: {}\", length, to, toString());\n\n        for (int i = 0; i < to; i++) {\n            handleArrayIndex(i, currentPath, model, ctx);\n        }\n    }\n\n    @Override\n    public String getPathFragment() {\n        return operation.toString();\n    }\n\n    @Override\n    public boolean isTokenDefinite() {\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/CompiledPath.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.internal.EvaluationAbortException;\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.Path;\nimport com.jayway.jsonpath.internal.PathRef;\nimport com.jayway.jsonpath.internal.function.ParamType;\nimport com.jayway.jsonpath.internal.function.Parameter;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Arrays;\n\npublic class CompiledPath implements Path {\n\n    private static final Logger logger = LoggerFactory.getLogger(CompiledPath.class);\n\n    private final RootPathToken root;\n\n    private final boolean isRootPath;\n\n\n    public CompiledPath(RootPathToken root, boolean isRootPath) {\n        this.root = invertScannerFunctionRelationship(root);\n        this.isRootPath = isRootPath;\n    }\n\n    @Override\n    public boolean isRootPath() {\n        return isRootPath;\n    }\n\n\n\n    /**\n     * In the event the writer of the path referenced a function at the tail end of a scanner, augment the query such\n     * that the root node is the function and the parameter to the function is the scanner.   This way we maintain\n     * relative sanity in the path expression, functions either evaluate scalar values or arrays, they're\n     * not re-entrant nor should they maintain state, they do however take parameters.\n     *\n     * @param path\n     *      this is our old root path which will become a parameter (assuming there's a scanner terminated by a function\n     *\n     * @return\n     *      A function with the scanner as input, or if this situation doesn't exist just the input path\n     */\n    private RootPathToken invertScannerFunctionRelationship(final RootPathToken path) {\n        if (path.isFunctionPath() && path.next() instanceof ScanPathToken) {\n            PathToken token = path;\n            PathToken prior = null;\n            while (null != (token = token.next()) && !(token instanceof FunctionPathToken)) {\n                prior = token;\n            }\n            // Invert the relationship $..path.function() to $.function($..path)\n            if (token instanceof FunctionPathToken) {\n                prior.setNext(null);\n                path.setTail(prior);\n\n                // Now generate a new parameter from our path\n                Parameter parameter = new Parameter();\n                parameter.setPath(new CompiledPath(path, true));\n                parameter.setType(ParamType.PATH);\n                ((FunctionPathToken)token).setParameters(Arrays.asList(parameter));\n                RootPathToken functionRoot = new RootPathToken('$');\n                functionRoot.setTail(token);\n                functionRoot.setNext(token);\n\n                // Define the function as the root\n                return functionRoot;\n            }\n        }\n        return path;\n    }\n\n    @Override\n    public EvaluationContext evaluate(Object document, Object rootDocument, Configuration configuration, boolean forUpdate) {\n        if (logger.isDebugEnabled()) {\n            logger.debug(\"Evaluating path: {}\", toString());\n        }\n\n        EvaluationContextImpl ctx = new EvaluationContextImpl(this, rootDocument, configuration, forUpdate);\n        try {\n            PathRef op = ctx.forUpdate() ?  PathRef.createRoot(rootDocument) : PathRef.NO_OP;\n            root.evaluate(\"\", op, document, ctx);\n        } catch (EvaluationAbortException abort) {}\n\n        return ctx;\n    }\n\n    @Override\n    public EvaluationContext evaluate(Object document, Object rootDocument, Configuration configuration){\n        return evaluate(document, rootDocument, configuration, false);\n    }\n\n    @Override\n    public boolean isDefinite() {\n        return root.isPathDefinite();\n    }\n\n    @Override\n    public boolean isFunctionPath() {\n        return root.isFunctionPath();\n    }\n\n    @Override\n    public String toString() {\n        return root.toString();\n    }\n\n    public RootPathToken getRoot() {\n        return root;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/EvaluationContextImpl.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.EvaluationListener;\nimport com.jayway.jsonpath.Option;\nimport com.jayway.jsonpath.PathNotFoundException;\nimport com.jayway.jsonpath.internal.EvaluationAbortException;\nimport com.jayway.jsonpath.internal.EvaluationContext;\nimport com.jayway.jsonpath.internal.Path;\nimport com.jayway.jsonpath.internal.PathRef;\nimport com.jayway.jsonpath.spi.json.JsonProvider;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Set;\n\nimport static com.jayway.jsonpath.internal.Utils.notNull;\n\n/**\n *\n */\npublic class EvaluationContextImpl implements EvaluationContext {\n\n    private static final EvaluationAbortException ABORT_EVALUATION = new EvaluationAbortException();\n\n    private final Configuration configuration;\n    private final Object valueResult;\n    private final Object pathResult;\n    private final Path path;\n    private final Object rootDocument;\n    private final List<PathRef> updateOperations;\n    private final HashMap<Path, Object> documentEvalCache = new HashMap<Path, Object>();\n    private final boolean forUpdate;\n    private final boolean suppressExceptions;\n    private int resultIndex = 0;\n\n\n    public RootPathToken getRoot(){\n        return ((CompiledPath) path).getRoot();\n    }\n\n    public EvaluationContextImpl(Path path, Object rootDocument, Configuration configuration, boolean forUpdate) {\n        notNull(path, \"path can not be null\");\n        notNull(rootDocument, \"root can not be null\");\n        notNull(configuration, \"configuration can not be null\");\n        this.forUpdate = forUpdate;\n        this.path = path;\n        this.rootDocument = rootDocument;\n        this.configuration = configuration;\n        this.valueResult = configuration.jsonProvider().createArray();\n        this.pathResult = configuration.jsonProvider().createArray();\n        this.updateOperations = new ArrayList<>();\n        this.suppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);\n    }\n\n    public HashMap<Path, Object> documentEvalCache() {\n        return documentEvalCache;\n    }\n\n    public boolean forUpdate(){\n        return forUpdate;\n    }\n\n    public void addResult(String path, PathRef operation, Object model) {\n\n        if(forUpdate) {\n            updateOperations.add(operation);\n        }\n\n        configuration.jsonProvider().setArrayIndex(valueResult, resultIndex, model);\n        configuration.jsonProvider().setArrayIndex(pathResult, resultIndex, path);\n        resultIndex++;\n        if(!configuration().getEvaluationListeners().isEmpty()){\n            int idx = resultIndex - 1;\n            for (EvaluationListener listener : configuration().getEvaluationListeners()) {\n                EvaluationListener.EvaluationContinuation continuation = listener.resultFound(new FoundResultImpl(idx, path, model));\n                if(EvaluationListener.EvaluationContinuation.ABORT == continuation){\n                    throw ABORT_EVALUATION;\n                }\n            }\n        }\n    }\n\n\n    public JsonProvider jsonProvider() {\n        return configuration.jsonProvider();\n    }\n\n    public Set<Option> options() {\n        return configuration.getOptions();\n    }\n\n    @Override\n    public Configuration configuration() {\n        return configuration;\n    }\n\n    @Override\n    public Object rootDocument() {\n        return rootDocument;\n    }\n\n    public Collection<PathRef> updateOperations(){\n\n        Collections.sort(updateOperations);\n\n        return Collections.unmodifiableCollection(updateOperations);\n    }\n\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T getValue() {\n        return getValue(true);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T getValue(boolean unwrap) {\n        if (path.isDefinite()) {\n            if(resultIndex == 0) {\n                if (suppressExceptions) {\n                    return null;\n                }\n                throw new PathNotFoundException(\"No results for path: \" + path.toString());\n            }\n            int len = jsonProvider().length(valueResult);\n            Object value = (len > 0) ? jsonProvider().getArrayIndex(valueResult, len-1) : null;\n            if (value != null && unwrap){\n              value = jsonProvider().unwrap(value);\n            }\n            return (T) value;\n        }\n        return (T)valueResult;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T getPath() {\n        if(resultIndex == 0) {\n            if (suppressExceptions) {\n                return null;\n            }\n            throw new PathNotFoundException(\"No results for path: \" + path.toString());\n        }\n        return (T)pathResult;\n    }\n\n    @Override\n    public List<String> getPathList() {\n        List<String> res = new ArrayList<String>();\n        if(resultIndex > 0){\n            Iterable<?> objects = configuration.jsonProvider().toIterable(pathResult);\n            for (Object o : objects) {\n                res.add((String)o);\n            }\n        }\n        return res;\n    }\n\n    private static class FoundResultImpl implements EvaluationListener.FoundResult {\n\n        private final int index;\n        private final String path;\n        private final Object result;\n\n        private FoundResultImpl(int index, String path, Object result) {\n            this.index = index;\n            this.path = path;\n            this.result = result;\n        }\n\n        @Override\n        public int index() {\n            return index;\n        }\n\n        @Override\n        public String path() {\n            return path;\n        }\n\n        @Override\n        public Object result() {\n            return result;\n        }\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/FunctionPathToken.java",
    "content": "package com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.internal.Path;\nimport com.jayway.jsonpath.internal.PathRef;\nimport com.jayway.jsonpath.internal.function.Parameter;\nimport com.jayway.jsonpath.internal.function.PathFunction;\nimport com.jayway.jsonpath.internal.function.PathFunctionFactory;\nimport com.jayway.jsonpath.internal.function.latebinding.JsonLateBindingValue;\nimport com.jayway.jsonpath.internal.function.latebinding.PathLateBindingValue;\n\nimport java.util.List;\n\n/**\n * Token representing a Function call to one of the functions produced via the FunctionFactory\n *\n * @see PathFunctionFactory\n *\n * Created by mattg on 6/27/15.\n */\npublic class FunctionPathToken extends PathToken {\n\n    private final String functionName;\n    private final String pathFragment;\n    private List<Parameter> functionParams;\n\n    public FunctionPathToken(String pathFragment, List<Parameter> parameters) {\n        this.pathFragment = pathFragment + ((parameters != null && parameters.size() > 0) ? \"(...)\" : \"()\");\n        if(null != pathFragment){\n            functionName = pathFragment;\n            functionParams = parameters;\n        } else {\n            functionName = null;\n            functionParams = null;\n        }\n    }\n\n    @Override\n    public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {\n        PathFunction pathFunction = PathFunctionFactory.newFunction(functionName);\n        evaluateParameters(currentPath, parent, model, ctx);\n        Object result = pathFunction.invoke(currentPath, parent, model, ctx, functionParams);\n        ctx.addResult(currentPath + \".\" + functionName, parent, result);\n        cleanWildcardPathToken();\n        if (!isLeaf()) {\n            next().evaluate(currentPath, parent, result, ctx);\n        }\n    }\n\n    private void cleanWildcardPathToken() {\n        if (null != functionParams && functionParams.size() > 0) {\n            Path path = functionParams.get(0).getPath();\n            if (null != path && !path.isFunctionPath() && path instanceof CompiledPath) {\n                RootPathToken root = ((CompiledPath) path).getRoot();\n                PathToken tail = root.getNext();\n                while (null != tail && null != tail.getNext() ) {\n                    if(tail.getNext() instanceof WildcardPathToken){\n                        tail.setNext(tail.getNext().getNext());\n                        break;\n                    }\n                    tail = tail.getNext();\n                }\n            }\n        }\n    }\n\n    private void evaluateParameters(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {\n\n        if (null != functionParams) {\n            for (Parameter param : functionParams) {\n                switch (param.getType()) {\n                    case PATH:\n                        PathLateBindingValue pathLateBindingValue = new PathLateBindingValue(param.getPath(), ctx.rootDocument(), ctx.configuration());\n                        if (!param.hasEvaluated()||!pathLateBindingValue.equals(param.getILateBingValue())) {\n                            param.setLateBinding(pathLateBindingValue);\n                            param.setEvaluated(true);\n                        }\n                        break;\n                    case JSON:\n                        if (!param.hasEvaluated()) {\n                            param.setLateBinding(new JsonLateBindingValue(ctx.configuration().jsonProvider(), param));\n                            param.setEvaluated(true);\n                        }\n                        break;\n                }\n            }\n        }\n    }\n\n    /**\n     * Return the actual value by indicating true. If this return was false then we'd return the value in an array which\n     * isn't what is desired - true indicates the raw value is returned.\n     *\n     * @return true if token is definite\n     */\n    @Override\n    public boolean isTokenDefinite() {\n        return true;\n    }\n\n    @Override\n    public String getPathFragment() {\n        return \".\" + pathFragment;\n    }\n\n\n    public void setParameters(List<Parameter> parameters) {\n        this.functionParams = parameters;\n    }\n\n    public List<Parameter> getParameters() {\n        return this.functionParams;\n    }\n    public String getFunctionName() {\n        return this.functionName;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java",
    "content": "package com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.InvalidPathException;\nimport com.jayway.jsonpath.Predicate;\nimport com.jayway.jsonpath.internal.CharacterIndex;\nimport com.jayway.jsonpath.internal.Path;\nimport com.jayway.jsonpath.internal.Utils;\nimport com.jayway.jsonpath.internal.filter.FilterCompiler;\nimport com.jayway.jsonpath.internal.function.ParamType;\nimport com.jayway.jsonpath.internal.function.Parameter;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport static java.lang.Character.isDigit;\nimport static java.util.Arrays.asList;\n\npublic class PathCompiler {\n\n    private static final char DOC_CONTEXT = '$';\n    private static final char EVAL_CONTEXT = '@';\n\n    private static final char OPEN_SQUARE_BRACKET = '[';\n    private static final char CLOSE_SQUARE_BRACKET = ']';\n    private static final char OPEN_PARENTHESIS = '(';\n    private static final char CLOSE_PARENTHESIS = ')';\n    private static final char OPEN_BRACE = '{';\n    private static final char CLOSE_BRACE = '}';\n\n    private static final char WILDCARD = '*';\n    private static final char PERIOD = '.';\n    private static final char SPACE = ' ';\n    private static final char TAB = '\\t';\n    private static final char CR = '\\r';\n    private static final char LF = '\\n';\n    private static final char BEGIN_FILTER = '?';\n    private static final char COMMA = ',';\n    private static final char SPLIT = ':';\n    private static final char MINUS = '-';\n    private static final char SINGLE_QUOTE = '\\'';\n    private static final char DOUBLE_QUOTE = '\"';\n\n    private final LinkedList<Predicate> filterStack;\n    private final CharacterIndex path;\n\n    private PathCompiler(String path, LinkedList<Predicate> filterStack){\n        this(new CharacterIndex(path), filterStack);\n    }\n\n    private PathCompiler(CharacterIndex path, LinkedList<Predicate> filterStack){\n        this.filterStack = filterStack;\n        this.path = path;\n    }\n\n    private Path compile() {\n        RootPathToken root = readContextToken();\n        return new CompiledPath(root, root.getPathFragment().equals(\"$\"));\n    }\n\n    public static Path compile(String path, final Predicate... filters) {\n        try {\n            CharacterIndex ci = new CharacterIndex(path);\n            ci.trim();\n\n            if(!( ci.charAt(0) == DOC_CONTEXT)  && !( ci.charAt(0) == EVAL_CONTEXT)){\n                ci = new CharacterIndex(\"$.\" + path);\n                ci.trim();\n            }\n            if(ci.lastCharIs('.')){\n                fail(\"Path must not end with a '.' or '..'\");\n            }\n            LinkedList<Predicate> filterStack = new LinkedList<Predicate>(asList(filters));\n            return new PathCompiler(ci, filterStack).compile();\n        } catch (Exception e) {\n            InvalidPathException ipe;\n            if (e instanceof InvalidPathException) {\n                ipe = (InvalidPathException) e;\n            } else {\n                ipe = new InvalidPathException(e);\n            }\n            throw ipe;\n        }\n    }\n\n    private void readWhitespace() {\n        while (path.inBounds()) {\n            char c = path.currentChar();\n            if (!isWhitespace(c)) {\n                break;\n            }\n            path.incrementPosition(1);\n        }\n    }\n\n    private Boolean isPathContext(char c) {\n        return (c == DOC_CONTEXT || c == EVAL_CONTEXT);\n    }\n\n    //[$ | @]\n    private RootPathToken readContextToken() {\n\n        readWhitespace();\n\n        if (!isPathContext(path.currentChar())) {\n            throw new InvalidPathException(\"Path must start with '$' or '@'\");\n        }\n\n        RootPathToken pathToken = PathTokenFactory.createRootPathToken(path.currentChar());\n\n        if (path.currentIsTail()) {\n            return pathToken;\n        }\n\n        path.incrementPosition(1);\n\n        if(path.currentChar() != PERIOD && path.currentChar() != OPEN_SQUARE_BRACKET){\n            fail(\"Illegal character at position \" + path.position() + \" expected '.' or '['\");\n        }\n\n        PathTokenAppender appender = pathToken.getPathTokenAppender();\n        readNextToken(appender);\n\n        return pathToken;\n    }\n\n    //\n    //\n    //\n    private boolean readNextToken(PathTokenAppender appender) {\n\n        char c = path.currentChar();\n\n        switch (c) {\n            case OPEN_SQUARE_BRACKET:\n                if (!readBracketPropertyToken(appender) && !readArrayToken(appender) && !readWildCardToken(appender)\n                    && !readFilterToken(appender) && !readPlaceholderToken(appender)) {\n                    fail(\"Could not parse token starting at position \" + path.position() + \". Expected ?, ', 0-9, * \");\n                }\n                return true;\n            case PERIOD:\n                if (!readDotToken(appender)) {\n                    fail(\"Could not parse token starting at position \" + path.position());\n                }\n                return true;\n            case WILDCARD:\n                if (!readWildCardToken(appender)) {\n                    fail(\"Could not parse token starting at position \" + path.position());\n                }\n                return true;\n            default:\n                if (!readPropertyOrFunctionToken(appender)) {\n                    fail(\"Could not parse token starting at position \" + path.position());\n                }\n                return true;\n        }\n    }\n\n    //\n    // . and ..\n    //\n    private boolean readDotToken(PathTokenAppender appender) {\n        if (path.currentCharIs(PERIOD) && path.nextCharIs(PERIOD)) {\n            appender.appendPathToken(PathTokenFactory.crateScanToken());\n            path.incrementPosition(2);\n        } else if (!path.hasMoreCharacters()) {\n            throw new InvalidPathException(\"Path must not end with a '.\");\n        } else {\n            path.incrementPosition(1);\n        }\n        if(path.currentCharIs(PERIOD)){\n            throw new InvalidPathException(\"Character '.' on position \" + path.position() + \" is not valid.\");\n        }\n        return readNextToken(appender);\n    }\n\n    //\n    // fooBar or fooBar()\n    //\n    private boolean readPropertyOrFunctionToken(PathTokenAppender appender) {\n        if (path.currentCharIs(OPEN_SQUARE_BRACKET) || path.currentCharIs(WILDCARD) || path.currentCharIs(PERIOD) || path.currentCharIs(SPACE)) {\n            return false;\n        }\n        int startPosition = path.position();\n        int readPosition = startPosition;\n        int endPosition = 0;\n\n        boolean isFunction = false;\n\n        while (path.inBounds(readPosition)) {\n            char c = path.charAt(readPosition);\n            if (c == SPACE) {\n                throw new InvalidPathException(\"Use bracket notion ['my prop'] if your property contains blank characters. position: \" + path.position());\n            }\n            else if (c == PERIOD || c == OPEN_SQUARE_BRACKET) {\n                endPosition = readPosition;\n                break;\n            }\n            else if (c == OPEN_PARENTHESIS) {\n                isFunction = true;\n                endPosition = readPosition;\n                break;\n            }\n            readPosition++;\n        }\n        if (endPosition == 0) {\n            endPosition = path.length();\n        }\n\n\n        List<Parameter> functionParameters = null;\n        if (isFunction) {\n            int parenthesis_count = 1;\n            for(int i = readPosition + 1; i < path.length(); i++){\n                if (path.charAt(i) == CLOSE_PARENTHESIS)\n                    parenthesis_count--;\n                else if (path.charAt(i) == OPEN_PARENTHESIS)\n                    parenthesis_count++;\n                if (parenthesis_count == 0)\n                    break;\n            }\n\n            if (parenthesis_count != 0){\n                String functionName = path.subSequence(startPosition, endPosition).toString();\n                throw new InvalidPathException(\"Arguments to function: '\" + functionName + \"' are not closed properly.\");\n            }\n\n            if (path.inBounds(readPosition+1)) {\n                // read the next token to determine if we have a simple no-args function call\n                char c = path.charAt(readPosition + 1);\n                if (c != CLOSE_PARENTHESIS) {\n                    path.setPosition(endPosition+1);\n                    // parse the arguments of the function - arguments that are inner queries or JSON document(s)\n                    String functionName = path.subSequence(startPosition, endPosition).toString();\n                    functionParameters = parseFunctionParameters(functionName);\n                } else {\n                    path.setPosition(readPosition + 1);\n                }\n            }\n            else {\n                path.setPosition(readPosition);\n            }\n        }\n        else {\n            path.setPosition(endPosition);\n        }\n\n        String property = path.subSequence(startPosition, endPosition).toString();\n        if(isFunction){\n            appender.appendPathToken(PathTokenFactory.createFunctionPathToken(property, functionParameters));\n        } else {\n            appender.appendPathToken(PathTokenFactory.createSinglePropertyPathToken(property, SINGLE_QUOTE));\n        }\n\n        return path.currentIsTail() || readNextToken(appender);\n    }\n\n    /**\n     * Parse the parameters of a function call, either the caller has supplied JSON data, or the caller has supplied\n     * another path expression which must be evaluated and in turn invoked against the root document.  In this tokenizer\n     * we're only concerned with parsing the path thus the output of this function is a list of parameters with the Path\n     * set if the parameter is an expression.  If the parameter is a JSON document then the value of the cachedValue is\n     * set on the object.\n     *\n     * Sequence for parsing out the parameters:\n     *\n     * This code has its own tokenizer - it does some rudimentary level of lexing in that it can distinguish between JSON block parameters\n     * and sub-JSON blocks - it effectively regex's out the parameters into string blocks that can then be passed along to the appropriate parser.\n     * Since sub-jsonpath expressions can themselves contain other function calls this routine needs to be sensitive to token counting to\n     * determine the boundaries.  Since the Path parser isn't aware of JSON processing this uber routine is needed.\n     *\n     * Parameters are separated by COMMAs ','\n     *\n     * <pre>\n     * doc = {\"numbers\": [1,2,3,4,5,6,7,8,9,10]}\n     *\n     * $.sum({10}, $.numbers.avg())\n     * </pre>\n     *\n     * The above is a valid function call, we're first summing 10 + avg of 1...10 (5.5) so the total should be 15.5\n     *\n     * @return\n     *      An ordered list of parameters that are to processed via the function.  Typically functions either process\n     *      an array of values and/or can consume parameters in addition to the values provided from the consumption of\n     *      an array.\n     */\n    private List<Parameter> parseFunctionParameters(String funcName) {\n        ParamType type = null;\n\n        // Parenthesis starts at 1 since we're marking the start of a function call, the close paren will denote the\n        // last parameter boundary\n        int groupParen = 1, groupBracket = 0, groupBrace = 0, groupQuote = 0;\n        boolean endOfStream = false;\n        char priorChar = 0;\n        List<Parameter> parameters = new ArrayList<Parameter>();\n        StringBuilder parameter = new StringBuilder();\n        while (path.inBounds() && !endOfStream) {\n            char c = path.currentChar();\n            path.incrementPosition(1);\n\n            // we're at the start of the stream, and don't know what type of parameter we have\n            if (type == null) {\n                if (isWhitespace(c)) {\n                    continue;\n                }\n\n                if (c == OPEN_BRACE || isDigit(c) || DOUBLE_QUOTE == c || MINUS == c) {\n                    type = ParamType.JSON;\n                }\n                else if (isPathContext(c)) {\n                    type = ParamType.PATH; // read until we reach a terminating comma and we've reset grouping to zero\n                }\n            }\n\n            switch (c) {\n                case DOUBLE_QUOTE:\n                    if (priorChar != '\\\\' && groupQuote > 0) {\n                        groupQuote--;\n                    }\n                    else {\n                        groupQuote++;\n                    }\n                    break;\n                case OPEN_PARENTHESIS:\n                    groupParen++;\n                    break;\n                case OPEN_BRACE:\n                    groupBrace++;\n                    break;\n                case OPEN_SQUARE_BRACKET:\n                    groupBracket++;\n                    break;\n\n                case CLOSE_BRACE:\n                    if (0 == groupBrace) {\n                        throw new InvalidPathException(\"Unexpected close brace '}' at character position: \" + path.position());\n                    }\n                    groupBrace--;\n                    break;\n                case CLOSE_SQUARE_BRACKET:\n                    if (0 == groupBracket) {\n                        throw new InvalidPathException(\"Unexpected close bracket ']' at character position: \" + path.position());\n                    }\n                    groupBracket--;\n                    break;\n\n                // In either the close paren case where we have zero paren groups left, capture the parameter, or where\n                // we've encountered a COMMA do the same\n                case CLOSE_PARENTHESIS:\n                    groupParen--;\n                    //CS304 Issue link: https://github.com/json-path/JsonPath/issues/620\n                    if (0 > groupParen || priorChar == '(') {\n                        parameter.append(c);\n                    }\n                case COMMA:\n                    // In this state we've reach the end of a function parameter and we can pass along the parameter string\n                    // to the parser\n                    if ((0 == groupQuote && 0 == groupBrace && 0 == groupBracket\n                            && ((0 == groupParen && CLOSE_PARENTHESIS == c) || 1 == groupParen))) {\n                        endOfStream = (0 == groupParen);\n\n                        if (null != type) {\n                            Parameter param = null;\n                            switch (type) {\n                                case JSON:\n                                    // parse the json and set the value\n                                    param = new Parameter(parameter.toString());\n                                    break;\n                                case PATH:\n                                    LinkedList<Predicate> predicates = new LinkedList<>();\n                                    PathCompiler compiler = new PathCompiler(parameter.toString(), predicates);\n                                    param = new Parameter(compiler.compile());\n                                    break;\n                            }\n                            if (null != param) {\n                                parameters.add(param);\n                            }\n                            parameter.delete(0, parameter.length());\n                            type = null;\n                        }\n                    }\n                    break;\n            }\n\n            if (type != null && !(c == COMMA && 0 == groupBrace && 0 == groupBracket && 1 == groupParen)) {\n                parameter.append(c);\n            }\n            priorChar = c;\n        }\n        if (0 != groupBrace || 0 != groupParen || 0 != groupBracket) {\n            throw new InvalidPathException(\"Arguments to function: '\" + funcName + \"' are not closed properly.\");\n        }\n        return parameters;\n    }\n\n    private boolean isWhitespace(char c) {\n        return (c == SPACE || c == TAB || c == LF || c == CR);\n    }\n\n    //\n    // [?], [?,?, ..]\n    //\n    private boolean readPlaceholderToken(PathTokenAppender appender) {\n\n        if (!path.currentCharIs(OPEN_SQUARE_BRACKET)) {\n            return false;\n        }\n        int questionmarkIndex = path.indexOfNextSignificantChar(BEGIN_FILTER);\n        if (questionmarkIndex == -1) {\n            return false;\n        }\n        char nextSignificantChar = path.nextSignificantChar(questionmarkIndex);\n        if (nextSignificantChar != CLOSE_SQUARE_BRACKET && nextSignificantChar != COMMA) {\n            return false;\n        }\n\n        int expressionBeginIndex = path.position() + 1;\n        int expressionEndIndex = path.nextIndexOf(expressionBeginIndex, CLOSE_SQUARE_BRACKET);\n\n        if (expressionEndIndex == -1) {\n            return false;\n        }\n\n        String expression = path.subSequence(expressionBeginIndex, expressionEndIndex).toString();\n\n        String[] tokens = expression.split(\",\");\n\n        if (filterStack.size() < tokens.length) {\n            throw new InvalidPathException(\"Not enough predicates supplied for filter [\" + expression + \"] at position \" + path.position());\n        }\n\n        Collection<Predicate> predicates = new ArrayList<Predicate>();\n        for (String token : tokens) {\n            token = token != null ? token.trim() : null;\n            if (!\"?\".equals(token == null ? \"\" : token)) {\n                throw new InvalidPathException(\"Expected '?' but found \" + token);\n            }\n            predicates.add(filterStack.pop());\n        }\n\n        appender.appendPathToken(PathTokenFactory.createPredicatePathToken(predicates));\n\n        path.setPosition(expressionEndIndex + 1);\n\n        return path.currentIsTail() || readNextToken(appender);\n    }\n\n    //\n    // [?(...)]\n    //\n    private boolean readFilterToken(PathTokenAppender appender) {\n        if (!path.currentCharIs(OPEN_SQUARE_BRACKET) && !path.nextSignificantCharIs(BEGIN_FILTER)) {\n            return false;\n        }\n\n        int openStatementBracketIndex = path.position();\n        int questionMarkIndex = path.indexOfNextSignificantChar(BEGIN_FILTER);\n        if (questionMarkIndex == -1) {\n            return false;\n        }\n        int openBracketIndex = path.indexOfNextSignificantChar(questionMarkIndex, OPEN_PARENTHESIS);\n        if (openBracketIndex == -1) {\n            return false;\n        }\n        int closeBracketIndex = path.indexOfClosingBracket(openBracketIndex, true, true);\n        if (closeBracketIndex == -1) {\n            return false;\n        }\n        if (!path.nextSignificantCharIs(closeBracketIndex, CLOSE_SQUARE_BRACKET)) {\n            return false;\n        }\n        int closeStatementBracketIndex = path.indexOfNextSignificantChar(closeBracketIndex, CLOSE_SQUARE_BRACKET);\n\n        String criteria = path.subSequence(openStatementBracketIndex, closeStatementBracketIndex + 1).toString();\n\n\n        Predicate predicate = FilterCompiler.compile(criteria);\n        appender.appendPathToken(PathTokenFactory.createPredicatePathToken(predicate));\n\n        path.setPosition(closeStatementBracketIndex + 1);\n\n        return path.currentIsTail() || readNextToken(appender);\n\n    }\n\n    //\n    // [*]\n    // *\n    //\n    private boolean readWildCardToken(PathTokenAppender appender) {\n\n        boolean inBracket = path.currentCharIs(OPEN_SQUARE_BRACKET);\n\n        if (inBracket && !path.nextSignificantCharIs(WILDCARD)) {\n            return false;\n        }\n        if (!path.currentCharIs(WILDCARD) && path.isOutOfBounds(path.position() + 1)) {\n            return false;\n        }\n        if (inBracket) {\n            int wildCardIndex = path.indexOfNextSignificantChar(WILDCARD);\n            if (!path.nextSignificantCharIs(wildCardIndex, CLOSE_SQUARE_BRACKET)) {\n                int offset = wildCardIndex + 1;\n                throw new InvalidPathException(\"Expected wildcard token to end with ']' on position \" + offset);\n            }\n            int bracketCloseIndex = path.indexOfNextSignificantChar(wildCardIndex, CLOSE_SQUARE_BRACKET);\n            path.setPosition(bracketCloseIndex + 1);\n        } else {\n            path.incrementPosition(1);\n        }\n\n        appender.appendPathToken(PathTokenFactory.createWildCardPathToken());\n\n        return path.currentIsTail() || readNextToken(appender);\n    }\n\n    //\n    // [1], [1,2, n], [1:], [1:2], [:2]\n    //\n    private boolean readArrayToken(PathTokenAppender appender) {\n\n        if (!path.currentCharIs(OPEN_SQUARE_BRACKET)) {\n            return false;\n        }\n        char nextSignificantChar = path.nextSignificantChar();\n        if (!isDigit(nextSignificantChar) && nextSignificantChar != MINUS && nextSignificantChar != SPLIT) {\n            return false;\n        }\n\n        int expressionBeginIndex = path.position() + 1;\n        int expressionEndIndex = path.nextIndexOf(expressionBeginIndex, CLOSE_SQUARE_BRACKET);\n\n        if (expressionEndIndex == -1) {\n            return false;\n        }\n\n        String expression = path.subSequence(expressionBeginIndex, expressionEndIndex).toString().trim();\n\n        if (\"*\".equals(expression)) {\n            return false;\n        }\n\n        //check valid chars\n        for (int i = 0; i < expression.length(); i++) {\n            char c = expression.charAt(i);\n            if (!isDigit(c) && c != COMMA && c != MINUS && c != SPLIT && c != SPACE) {\n                return false;\n            }\n        }\n\n        boolean isSliceOperation = expression.contains(\":\");\n\n        if (isSliceOperation) {\n            ArraySliceOperation arraySliceOperation = ArraySliceOperation.parse(expression);\n            appender.appendPathToken(PathTokenFactory.createSliceArrayPathToken(arraySliceOperation));\n        } else {\n            ArrayIndexOperation arrayIndexOperation = ArrayIndexOperation.parse(expression);\n            appender.appendPathToken(PathTokenFactory.createIndexArrayPathToken(arrayIndexOperation));\n        }\n\n        path.setPosition(expressionEndIndex + 1);\n\n        return path.currentIsTail() || readNextToken(appender);\n    }\n\n    //\n    // ['foo']\n    //\n    private boolean readBracketPropertyToken(PathTokenAppender appender) {\n        if (!path.currentCharIs(OPEN_SQUARE_BRACKET)) {\n            return false;\n        }\n        char potentialStringDelimiter = path.nextSignificantChar();\n        if (potentialStringDelimiter != SINGLE_QUOTE && potentialStringDelimiter != DOUBLE_QUOTE) {\n          return false;\n        }\n\n        List<String> properties = new ArrayList<String>();\n\n        int startPosition = path.position() + 1;\n        int readPosition = startPosition;\n        int endPosition = 0;\n        boolean inProperty = false;\n        boolean inEscape = false;\n        boolean lastSignificantWasComma = false;\n\n        while (path.inBounds(readPosition)) {\n            char c = path.charAt(readPosition);\n\n            if(inEscape){\n                inEscape = false;\n            } else if('\\\\' == c){\n                inEscape = true;\n            } else if (c == CLOSE_SQUARE_BRACKET && !inProperty) {\n                if (lastSignificantWasComma){\n                  fail(\"Found empty property at index \"+readPosition);\n                }\n                break;\n            } else if (c == potentialStringDelimiter) {\n                if (inProperty) {\n                    char nextSignificantChar = path.nextSignificantChar(readPosition);\n                    if (nextSignificantChar != CLOSE_SQUARE_BRACKET && nextSignificantChar != COMMA) {\n                        fail(\"Property must be separated by comma or Property must be terminated close square bracket at index \"+readPosition);\n                    }\n                    endPosition = readPosition;\n                    String prop = path.subSequence(startPosition, endPosition).toString();\n                    properties.add(Utils.unescape(prop));\n                    inProperty = false;\n                } else {\n                    startPosition = readPosition + 1;\n                    inProperty = true;\n                    lastSignificantWasComma = false;\n                }\n            } else if (c == COMMA && !inProperty) {\n                if (lastSignificantWasComma){\n                    fail(\"Found empty property at index \"+readPosition);\n                }\n                lastSignificantWasComma = true;\n            }\n            readPosition++;\n        }\n\n        if (inProperty){\n            fail(\"Property has not been closed - missing closing \" + potentialStringDelimiter);\n        }\n\n        int endBracketIndex = path.indexOfNextSignificantChar(endPosition, CLOSE_SQUARE_BRACKET);\n        if(endBracketIndex == -1) {\n            fail(\"Property has not been closed - missing closing ]\");\n        }\n        endBracketIndex++;\n\n        path.setPosition(endBracketIndex);\n\n        appender.appendPathToken(PathTokenFactory.createPropertyPathToken(properties, potentialStringDelimiter));\n\n        return path.currentIsTail() || readNextToken(appender);\n    }\n\n    public static boolean fail(String message) {\n        throw new InvalidPathException(message);\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/PathToken.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.Option;\nimport com.jayway.jsonpath.PathNotFoundException;\nimport com.jayway.jsonpath.internal.PathRef;\nimport com.jayway.jsonpath.internal.Utils;\nimport com.jayway.jsonpath.internal.function.PathFunction;\nimport com.jayway.jsonpath.spi.json.JsonProvider;\n\nimport java.util.List;\n\npublic abstract class PathToken {\n\n    private PathToken prev;\n    private PathToken next;\n    private Boolean definite = null;\n    private Boolean upstreamDefinite = null;\n    private int upstreamArrayIndex = -1;\n\n\n    public void setUpstreamArrayIndex(int idx){\n        upstreamArrayIndex = idx;\n    }\n\n    PathToken appendTailToken(PathToken next) {\n        this.next = next;\n        this.next.prev = this;\n        return next;\n    }\n\n    void handleObjectProperty(String currentPath, Object model, EvaluationContextImpl ctx, List<String> properties) {\n\n        if(properties.size() == 1) {\n            String property = properties.get(0);\n            String evalPath = Utils.concat(currentPath, \"['\", property, \"']\");\n            Object propertyVal = readObjectProperty(property, model, ctx);\n            if(propertyVal == JsonProvider.UNDEFINED){\n                // Conditions below heavily depend on current token type (and its logic) and are not \"universal\",\n                // so this code is quite dangerous (I'd rather rewrite it & move to PropertyPathToken and implemented\n                // WildcardPathToken as a dynamic multi prop case of PropertyPathToken).\n                // Better safe than sorry.\n                assert this instanceof PropertyPathToken : \"only PropertyPathToken is supported\";\n\n                if(isLeaf()) {\n                    if(ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)){\n                        propertyVal =  null;\n                    } else {\n                        if(ctx.options().contains(Option.SUPPRESS_EXCEPTIONS) ||\n                           !ctx.options().contains(Option.REQUIRE_PROPERTIES)){\n                            return;\n                        } else {\n                            throw new PathNotFoundException(\"No results for path: \" + evalPath);\n                        }\n                    }\n                } else {\n                    if (! (isUpstreamDefinite() && isTokenDefinite()) &&\n                       !ctx.options().contains(Option.REQUIRE_PROPERTIES) ||\n                       ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)){\n                        // If there is some indefiniteness in the path and properties are not required - we'll ignore\n                        // absent property. And also in case of exception suppression - so that other path evaluation\n                        // branches could be examined.\n                        return;\n                    } else {\n                        throw new PathNotFoundException(\"Missing property in path \" + evalPath);\n                    }\n                }\n            }\n            PathRef pathRef = ctx.forUpdate() ? PathRef.create(model, property) : PathRef.NO_OP;\n            if (isLeaf()) {\n                String idx = \"[\" + String.valueOf(upstreamArrayIndex) + \"]\";\n                if(idx.equals(\"[-1]\") || ctx.getRoot().getTail().prev().getPathFragment().equals(idx)){\n                    ctx.addResult(evalPath, pathRef, propertyVal);\n                }\n            }\n            else {\n                next().evaluate(evalPath, pathRef, propertyVal, ctx);\n            }\n        } else {\n            String evalPath = currentPath + \"[\" + Utils.join(\", \", \"'\", properties) + \"]\";\n\n            assert isLeaf() : \"non-leaf multi props handled elsewhere\";\n\n            Object merged = ctx.jsonProvider().createMap();\n            for (String property : properties) {\n                Object propertyVal;\n                if(hasProperty(property, model, ctx)) {\n                    propertyVal = readObjectProperty(property, model, ctx);\n                    if(propertyVal == JsonProvider.UNDEFINED){\n                        if(ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)) {\n                            propertyVal = null;\n                        } else {\n                            continue;\n                        }\n                    }\n                } else {\n                    if(ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)){\n                        propertyVal = null;\n                    } else if (ctx.options().contains(Option.REQUIRE_PROPERTIES)) {\n                        throw new PathNotFoundException(\"Missing property in path \" + evalPath);\n                    } else {\n                        continue;\n                    }\n                }\n                ctx.jsonProvider().setProperty(merged, property, propertyVal);\n            }\n            PathRef pathRef = ctx.forUpdate() ? PathRef.create(model, properties) : PathRef.NO_OP;\n            ctx.addResult(evalPath, pathRef, merged);\n        }\n    }\n\n    private static boolean hasProperty(String property, Object model, EvaluationContextImpl ctx) {\n        return ctx.jsonProvider().getPropertyKeys(model).contains(property);\n    }\n\n    private static Object readObjectProperty(String property, Object model, EvaluationContextImpl ctx) {\n        return ctx.jsonProvider().getMapValue(model, property);\n    }\n\n\n    protected void handleArrayIndex(int index, String currentPath, Object model, EvaluationContextImpl ctx) {\n        String evalPath = Utils.concat(currentPath, \"[\", String.valueOf(index), \"]\");\n        PathRef pathRef = ctx.forUpdate() ? PathRef.create(model, index) : PathRef.NO_OP;\n        int effectiveIndex = index < 0 ? ctx.jsonProvider().length(model) + index : index;\n        try {\n            Object evalHit = ctx.jsonProvider().getArrayIndex(model, effectiveIndex);\n            if (isLeaf()) {\n                ctx.addResult(evalPath, pathRef, evalHit);\n            } else {\n                next().evaluate(evalPath, pathRef, evalHit, ctx);\n            }\n        } catch (IndexOutOfBoundsException e) {\n        }\n    }\n\n    PathToken prev(){\n        return prev;\n    }\n\n    PathToken next() {\n        if (isLeaf()) {\n            throw new IllegalStateException(\"Current path token is a leaf\");\n        }\n        return next;\n    }\n\n    boolean isLeaf() {\n        return next == null;\n    }\n\n    boolean isRoot() {\n        return  prev == null;\n    }\n\n    boolean isUpstreamDefinite() {\n        if (upstreamDefinite == null) {\n            upstreamDefinite = isRoot() || prev.isTokenDefinite() && prev.isUpstreamDefinite();\n        }\n        return upstreamDefinite;\n    }\n\n    public int getTokenCount() {\n        int cnt = 1;\n        PathToken token = this;\n\n        while (!token.isLeaf()){\n            token = token.next();\n            cnt++;\n        }\n        return cnt;\n    }\n\n    public boolean isPathDefinite() {\n        if(definite != null){\n            return definite.booleanValue();\n        }\n        boolean isDefinite = isTokenDefinite();\n        if (isDefinite && !isLeaf()) {\n            isDefinite = next.isPathDefinite();\n        }\n        definite = isDefinite;\n        return isDefinite;\n    }\n\n    @Override\n    public String toString() {\n        if (isLeaf()) {\n            return getPathFragment();\n        } else {\n            return getPathFragment() + next().toString();\n        }\n    }\n\n    @Override\n    public int hashCode() {\n        return toString().hashCode();\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        return super.equals(obj);\n    }\n\n    public void invoke(PathFunction pathFunction, String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {\n        ctx.addResult(currentPath, parent, pathFunction.invoke(currentPath, parent, model, ctx, null));\n    }\n\n    public abstract void evaluate(String currentPath, PathRef parent,  Object model, EvaluationContextImpl ctx);\n\n    public abstract boolean isTokenDefinite();\n\n    protected abstract String getPathFragment();\n\n    public void setNext(final PathToken next) {\n        this.next = next;\n    }\n\n    public PathToken getNext() {\n        return this.next;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/PathTokenAppender.java",
    "content": "package com.jayway.jsonpath.internal.path;\n\npublic interface PathTokenAppender {\n    PathTokenAppender appendPathToken(PathToken next);\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/PathTokenFactory.java",
    "content": "package com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.Predicate;\nimport com.jayway.jsonpath.internal.function.Parameter;\n\nimport java.util.Collection;\nimport java.util.List;\n\nimport static java.util.Collections.singletonList;\n\npublic class PathTokenFactory {\n\n    public static RootPathToken createRootPathToken(char token) {\n        return new RootPathToken(token);\n    }\n\n    public static PathToken createSinglePropertyPathToken(String property, char stringDelimiter) {\n        return new PropertyPathToken(singletonList(property), stringDelimiter);\n    }\n\n    public static PathToken createPropertyPathToken(List<String> properties, char stringDelimiter) {\n        return new PropertyPathToken(properties, stringDelimiter);\n    }\n\n    public static PathToken createSliceArrayPathToken(final ArraySliceOperation arraySliceOperation) {\n        return new ArraySliceToken(arraySliceOperation);\n    }\n\n    public static PathToken createIndexArrayPathToken(final ArrayIndexOperation arrayIndexOperation) {\n        return new ArrayIndexToken(arrayIndexOperation);\n    }\n\n    public static PathToken createWildCardPathToken() {\n        return new WildcardPathToken();\n    }\n\n    public static PathToken crateScanToken() {\n        return new ScanPathToken();\n    }\n\n    public static PathToken createPredicatePathToken(Collection<Predicate> predicates) {\n        return new PredicatePathToken(predicates);\n    }\n\n    public static PathToken createPredicatePathToken(Predicate predicate) {\n        return new PredicatePathToken(predicate);\n    }\n\n    public static PathToken createFunctionPathToken(String function, List<Parameter> parameters) {\n        return new FunctionPathToken(function, parameters);\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/PredicateContextImpl.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.Predicate;\nimport com.jayway.jsonpath.internal.Path;\nimport com.jayway.jsonpath.spi.mapper.MappingException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.HashMap;\n\npublic class PredicateContextImpl implements Predicate.PredicateContext {\n\n    private static final Logger logger = LoggerFactory.getLogger(PredicateContextImpl.class);\n\n    private final Object contextDocument;\n    private final Object rootDocument;\n    private final Configuration configuration;\n    private final HashMap<Path, Object> documentPathCache;\n\n    public PredicateContextImpl(Object contextDocument, Object rootDocument, Configuration configuration, HashMap<Path, Object> documentPathCache) {\n        this.contextDocument = contextDocument;\n        this.rootDocument = rootDocument;\n        this.configuration = configuration;\n        this.documentPathCache = documentPathCache;\n    }\n\n    public Object evaluate(Path path){\n        Object result;\n        if(path.isRootPath()){\n            if(documentPathCache.containsKey(path)){\n                logger.debug(\"Using cached result for root path: \" + path.toString());\n                result = documentPathCache.get(path);\n            } else {\n                result = path.evaluate(rootDocument, rootDocument, configuration).getValue();\n                documentPathCache.put(path, result);\n            }\n        } else {\n            result = path.evaluate(contextDocument, rootDocument, configuration).getValue();\n        }\n        return result;\n    }\n\n    public HashMap<Path, Object> documentPathCache() {\n        return documentPathCache;\n    }\n\n    @Override\n    public Object item() {\n        return contextDocument;\n    }\n\n    @Override\n    public <T> T item(Class<T> clazz) throws MappingException {\n        return  configuration().mappingProvider().map(contextDocument, clazz, configuration);\n    }\n\n    @Override\n    public Object root() {\n        return rootDocument;\n    }\n\n    @Override\n    public Configuration configuration() {\n        return configuration;\n    }\n\n}"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/PredicatePathToken.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.InvalidPathException;\nimport com.jayway.jsonpath.Predicate;\nimport com.jayway.jsonpath.internal.PathRef;\n\nimport java.util.Collection;\nimport java.util.Collections;\n\nimport static java.lang.String.format;\nimport static java.util.Arrays.asList;\n\n/**\n *\n */\npublic class PredicatePathToken extends PathToken {\n\n\n    private final Collection<Predicate> predicates;\n\n    PredicatePathToken(Predicate filter) {\n        this.predicates = Collections.singletonList(filter);\n    }\n\n    PredicatePathToken(Collection<Predicate> predicates) {\n        this.predicates = predicates;\n    }\n\n    @Override\n    public void evaluate(String currentPath, PathRef ref, Object model, EvaluationContextImpl ctx) {\n        if (ctx.jsonProvider().isMap(model)) {\n            if (accept(model, ctx.rootDocument(), ctx.configuration(), ctx)) {\n                PathRef op = ctx.forUpdate() ? ref : PathRef.NO_OP;\n                if (isLeaf()) {\n                    ctx.addResult(currentPath, op, model);\n                } else {\n                    next().evaluate(currentPath, op, model, ctx);\n                }\n            }\n        } else if (ctx.jsonProvider().isArray(model)){\n            int idx = 0;\n            Iterable<?> objects = ctx.jsonProvider().toIterable(model);\n\n            for (Object idxModel : objects) {\n                if (accept(idxModel, ctx.rootDocument(),  ctx.configuration(), ctx)) {\n                    handleArrayIndex(idx, currentPath, model, ctx);\n                }\n                idx++;\n            }\n        } else {\n            if (isUpstreamDefinite()) {\n                throw new InvalidPathException(format(\"Filter: %s can not be applied to primitives. Current context is: %s\", toString(), model));\n            }\n        }\n    }\n\n    public boolean accept(final Object obj, final Object root, final Configuration configuration, EvaluationContextImpl evaluationContext) {\n        Predicate.PredicateContext ctx = new PredicateContextImpl(obj, root, configuration, evaluationContext.documentEvalCache());\n\n        for (Predicate predicate : predicates) {\n            try {\n                if (!predicate.apply(ctx)) {\n                    return false;\n                }\n            } catch (InvalidPathException e) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    @Override\n    public String getPathFragment() {\n        StringBuilder sb = new StringBuilder();\n        sb.append(\"[\");\n        for(int i = 0; i < predicates.size(); i++){\n            if(i != 0){\n                sb.append(\",\");\n            }\n            sb.append(\"?\");\n        }\n        sb.append(\"]\");\n        return sb.toString();\n    }\n\n    @Override\n    public boolean isTokenDefinite() {\n        return false;\n    }\n\n\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/PropertyPathToken.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.InvalidPathException;\nimport com.jayway.jsonpath.Option;\nimport com.jayway.jsonpath.PathNotFoundException;\nimport com.jayway.jsonpath.internal.PathRef;\nimport com.jayway.jsonpath.internal.Utils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.jayway.jsonpath.internal.Utils.onlyOneIsTrueNonThrow;\n\n/**\n *\n */\npublic class PropertyPathToken extends PathToken {\n\n    private final List<String> properties;\n    private final String stringDelimiter;\n\n    public PropertyPathToken(List<String> properties, char stringDelimiter) {\n        if (properties.isEmpty()) {\n            throw new InvalidPathException(\"Empty properties\");\n        }\n        this.properties = properties;\n        this.stringDelimiter = Character.toString(stringDelimiter);\n    }\n\n    public List<String> getProperties() {\n        return properties;\n    }\n\n    public boolean singlePropertyCase() {\n        return properties.size() == 1;\n    }\n\n    public boolean multiPropertyMergeCase() {\n        return isLeaf() && properties.size() > 1;\n    }\n\n    public boolean multiPropertyIterationCase() {\n        // Semantics of this case is the same as semantics of ArrayPathToken with INDEX_SEQUENCE operation.\n        return !isLeaf() && properties.size() > 1;\n    }\n\n    @Override\n    public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {\n        // Can't assert it in ctor because isLeaf() could be changed later on.\n        assert onlyOneIsTrueNonThrow(singlePropertyCase(), multiPropertyMergeCase(), multiPropertyIterationCase());\n\n        if (!ctx.jsonProvider().isMap(model)) {\n            if (!isUpstreamDefinite()\n                    || ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)) {\n                return;\n            } else {\n                String m = model == null ? \"null\" : model.getClass().getName();\n                throw new PathNotFoundException(String.format(\n                        \"Expected to find an object with property %s in path %s but found '%s'. \" +\n                                \"This is not a json object according to the JsonProvider: '%s'.\",\n                        getPathFragment(), currentPath, m, ctx.configuration().jsonProvider().getClass().getName()));\n            }\n        }\n\n        if (singlePropertyCase() || multiPropertyMergeCase()) {\n            handleObjectProperty(currentPath, model, ctx, properties);\n            return;\n        }\n\n        assert multiPropertyIterationCase();\n        final List<String> currentlyHandledProperty = new ArrayList<String>(1);\n        currentlyHandledProperty.add(null);\n        for (final String property : properties) {\n            currentlyHandledProperty.set(0, property);\n            handleObjectProperty(currentPath, model, ctx, currentlyHandledProperty);\n        }\n    }\n\n    @Override\n    public boolean isTokenDefinite() {\n        // in case of leaf multiprops will be merged, so it's kinda definite\n        return singlePropertyCase() || multiPropertyMergeCase();\n    }\n\n    @Override\n    public String getPathFragment() {\n        return new StringBuilder()\n                .append(\"[\")\n                .append(Utils.join(\",\", stringDelimiter, properties))\n                .append(\"]\").toString();\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/RootPathToken.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.internal.PathRef;\n\n/**\n *\n */\npublic class RootPathToken extends PathToken {\n\n    private PathToken tail;\n    private int tokenCount;\n    private final String rootToken;\n\n\n    RootPathToken(char rootToken) {\n        this.rootToken = Character.toString(rootToken);\n        this.tail = this;\n        this.tokenCount = 1;\n    }\n\n    public PathToken getTail(){\n        return this.tail;\n    }\n\n    @Override\n    public int getTokenCount() {\n        return tokenCount;\n    }\n\n    public RootPathToken append(PathToken next) {\n        this.tail = tail.appendTailToken(next);\n        this.tokenCount++;\n        return this;\n    }\n\n    public PathTokenAppender getPathTokenAppender(){\n        return new PathTokenAppender(){\n            @Override\n            public PathTokenAppender appendPathToken(PathToken next) {\n                append(next);\n                return this;\n            }\n        };\n    }\n\n    @Override\n    public void evaluate(String currentPath, PathRef pathRef, Object model, EvaluationContextImpl ctx) {\n        if (isLeaf()) {\n            PathRef op = ctx.forUpdate() ?  pathRef : PathRef.NO_OP;\n            ctx.addResult(rootToken, op, model);\n        } else {\n            next().evaluate(rootToken, pathRef, model, ctx);\n        }\n    }\n\n    @Override\n    public String getPathFragment() {\n        return rootToken;\n    }\n\n    @Override\n    public boolean isTokenDefinite() {\n        return true;\n    }\n\n    public boolean isFunctionPath() {\n        return (tail instanceof FunctionPathToken);\n    }\n\n    public void setTail(PathToken token) {\n        this.tail = token;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/ScanPathToken.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.Option;\nimport com.jayway.jsonpath.internal.PathRef;\nimport com.jayway.jsonpath.spi.json.JsonProvider;\n\nimport java.util.Collection;\n\n/**\n *\n */\npublic class ScanPathToken extends PathToken {\n\n    ScanPathToken() {\n    }\n\n    @Override\n    public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {\n\n        PathToken pt = next();\n\n        walk(pt, currentPath, parent,  model, ctx, createScanPredicate(pt, ctx));\n    }\n\n    public static void walk(PathToken pt, String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx, Predicate predicate) {\n        if (ctx.jsonProvider().isMap(model)) {\n            walkObject(pt, currentPath, parent, model, ctx, predicate);\n        } else if (ctx.jsonProvider().isArray(model)) {\n            walkArray(pt, currentPath, parent, model, ctx, predicate);\n        }\n    }\n\n    public static void walkArray(PathToken pt, String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx, Predicate predicate) {\n\n        if (predicate.matches(model)) {\n            if (pt.isLeaf()) {\n                pt.evaluate(currentPath, parent, model, ctx);\n            } else {\n                PathToken next = pt.next();\n                Iterable<?> models = ctx.jsonProvider().toIterable(model);\n                int idx = 0;\n                for (Object evalModel : models) {\n                    String evalPath = currentPath + \"[\" + idx + \"]\";\n                    next.setUpstreamArrayIndex(idx);\n                    next.evaluate(evalPath, parent, evalModel, ctx);\n                    idx++;\n                }\n            }\n        }\n\n        Iterable<?> models = ctx.jsonProvider().toIterable(model);\n        int idx = 0;\n        for (Object evalModel : models) {\n            String evalPath = currentPath + \"[\" + idx + \"]\";\n            walk(pt, evalPath, PathRef.create(model, idx), evalModel, ctx, predicate);\n            idx++;\n        }\n    }\n\n    public static void walkObject(PathToken pt, String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx, Predicate predicate) {\n\n        if (predicate.matches(model)) {\n            pt.evaluate(currentPath, parent, model, ctx);\n        }\n        Collection<String> properties = ctx.jsonProvider().getPropertyKeys(model);\n\n        for (String property : properties) {\n            String evalPath = currentPath + \"['\" + property + \"']\";\n            Object propertyModel = ctx.jsonProvider().getMapValue(model, property);\n            if (propertyModel != JsonProvider.UNDEFINED) {\n                walk(pt, evalPath, PathRef.create(model, property), propertyModel, ctx, predicate);\n            }\n        }\n    }\n\n    private static Predicate createScanPredicate(final PathToken target, final EvaluationContextImpl ctx) {\n        if (target instanceof PropertyPathToken) {\n            return new PropertyPathTokenPredicate(target, ctx);\n        } else if (target instanceof ArrayPathToken) {\n            return new ArrayPathTokenPredicate(ctx);\n        } else if (target instanceof WildcardPathToken) {\n            return new WildcardPathTokenPredicate();\n        } else if (target instanceof PredicatePathToken) {\n            return new FilterPathTokenPredicate(target, ctx);\n        } else {\n            return FALSE_PREDICATE;\n        }\n    }\n\n\n    @Override\n    public boolean isTokenDefinite() {\n        return false;\n    }\n\n    @Override\n    public String getPathFragment() {\n        return \"..\";\n    }\n\n    private interface Predicate {\n        boolean matches(Object model);\n    }\n\n    private static final Predicate FALSE_PREDICATE = new Predicate() {\n\n        @Override\n        public boolean matches(Object model) {\n            return false;\n        }\n    };\n\n    private static final class FilterPathTokenPredicate implements Predicate {\n        private final EvaluationContextImpl ctx;\n        private PredicatePathToken predicatePathToken;\n\n        private FilterPathTokenPredicate(PathToken target, EvaluationContextImpl ctx) {\n            this.ctx = ctx;\n            predicatePathToken = (PredicatePathToken) target;\n        }\n\n        @Override\n        public boolean matches(Object model) {\n            return predicatePathToken.accept(model, ctx.rootDocument(), ctx.configuration(), ctx);\n        }\n    }\n\n    private static final class WildcardPathTokenPredicate implements Predicate {\n\n        @Override\n        public boolean matches(Object model) {\n            return true;\n        }\n    }\n\n    private static final class ArrayPathTokenPredicate implements Predicate {\n        private final EvaluationContextImpl ctx;\n\n        private ArrayPathTokenPredicate(EvaluationContextImpl ctx) {\n            this.ctx = ctx;\n        }\n\n        @Override\n        public boolean matches(Object model) {\n            return ctx.jsonProvider().isArray(model);\n        }\n    }\n\n    private static final class PropertyPathTokenPredicate implements Predicate {\n        private final EvaluationContextImpl ctx;\n        private PropertyPathToken propertyPathToken;\n\n        private PropertyPathTokenPredicate(PathToken target, EvaluationContextImpl ctx) {\n            this.ctx = ctx;\n            propertyPathToken = (PropertyPathToken) target;\n        }\n\n        @Override\n        public boolean matches(Object model) {\n\n            if (! ctx.jsonProvider().isMap(model)) {\n                return false;\n            }\n\n//\n// The commented code below makes it really hard understand, use and predict the result\n// of deep scanning operations. It might be correct but was decided to be\n// left out until the behavior of REQUIRE_PROPERTIES is more strictly defined\n// in a deep scanning scenario. For details read conversation in commit\n// https://github.com/jayway/JsonPath/commit/1a72fc078deb16995e323442bfb681bd715ce45a#commitcomment-14616092\n//\n//            if (ctx.options().contains(Option.REQUIRE_PROPERTIES)) {\n//                // Have to require properties defined in path when an indefinite path is evaluated,\n//                // so have to go there and search for it.\n//                return true;\n//            }\n\n            if (! propertyPathToken.isTokenDefinite()) {\n                // It's responsibility of PropertyPathToken code to handle indefinite scenario of properties,\n                // so we'll allow it to do its job.\n                return true;\n            }\n\n            if (propertyPathToken.isLeaf() && ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)) {\n                // In case of DEFAULT_PATH_LEAF_TO_NULL missing properties is not a problem.\n                return true;\n            }\n\n            Collection<String> keys = ctx.jsonProvider().getPropertyKeys(model);\n            return keys.containsAll(propertyPathToken.getProperties());\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/internal/path/WildcardPathToken.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.internal.path;\n\nimport java.util.Collections;\n\nimport com.jayway.jsonpath.Option;\nimport com.jayway.jsonpath.PathNotFoundException;\nimport com.jayway.jsonpath.internal.PathRef;\n\nimport static java.util.Arrays.asList;\n\n/**\n *\n */\npublic class WildcardPathToken extends PathToken {\n\n    public WildcardPathToken() {\n    }\n\n    @Override\n    public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) {\n        if (ctx.jsonProvider().isMap(model)) {\n            for (String property : ctx.jsonProvider().getPropertyKeys(model)) {\n                handleObjectProperty(currentPath, model, ctx, Collections.singletonList(property));\n            }\n        } else if (ctx.jsonProvider().isArray(model)) {\n            for (int idx = 0; idx < ctx.jsonProvider().length(model); idx++) {\n                try {\n                    handleArrayIndex(idx, currentPath, model, ctx);\n                } catch (PathNotFoundException p){\n                    if(ctx.options().contains(Option.REQUIRE_PROPERTIES)){\n                        throw p;\n                    }\n                }\n            }\n        }\n    }\n\n\n    @Override\n    public boolean isTokenDefinite() {\n        return false;\n    }\n\n    @Override\n    public String getPathFragment() {\n        return \"[*]\";\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/cache/Cache.java",
    "content": "package com.jayway.jsonpath.spi.cache;\n\nimport com.jayway.jsonpath.InvalidJsonException;\nimport com.jayway.jsonpath.JsonPath;\n\npublic interface Cache {\n\n\t/**\n     * Get the Cached JsonPath\n     * @param key cache key to lookup the JsonPath\n     * @return JsonPath\n     */\n\t JsonPath get(String key);\n\t\n\t/**\n     * Add JsonPath to the cache\n     * @param key cache key to store the JsonPath\n     * @param value JsonPath to be cached\n     * @throws InvalidJsonException\n     */\n\t void put(String key, JsonPath value);\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/cache/CacheProvider.java",
    "content": "package com.jayway.jsonpath.spi.cache;\n\nimport com.jayway.jsonpath.JsonPathException;\n\nimport java.util.concurrent.atomic.AtomicReferenceFieldUpdater;\n\nimport static com.jayway.jsonpath.internal.Utils.notNull;\n\npublic class CacheProvider {\n\n    private static final AtomicReferenceFieldUpdater<CacheProvider, Cache> UPDATER =\n        AtomicReferenceFieldUpdater.newUpdater(CacheProvider.class, Cache.class, \"cache\");\n    private static final CacheProvider instance = new CacheProvider();\n\n    private volatile Cache cache;\n\n    private static class CacheHolder {\n        static final Cache CACHE;\n        static {\n            Cache cache = CacheProvider.instance.cache;\n            // the application is trying to use the cache\n            // and if no external implementation has been registered,\n            // we need to initialise it to the default LRUCache\n            if (cache == null) {\n                cache = getDefaultCache();\n                // on the off chance that the cache implementation was registered during\n                // initialisation of the holder, this should be respected, so if the\n                // default cache can't be written back, just read the user supplied value again\n                if (!UPDATER.compareAndSet(instance, null, cache)) {\n                    cache = CacheProvider.instance.cache;\n                }\n            }\n            CACHE = cache;\n        }\n    }\n\n    public static void setCache(Cache cache){\n        notNull(cache, \"Cache may not be null\");\n        if (!UPDATER.compareAndSet(instance, null, cache)) {\n            throw new JsonPathException(\"Cache provider must be configured before cache is accessed and must not be registered twice.\");\n        }\n    }\n\n    public static Cache getCache() {\n        return CacheHolder.CACHE;\n    }\n\n\n    private static Cache getDefaultCache(){\n        return new LRUCache(400);\n        //return new NOOPCache();\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/cache/LRUCache.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.cache;\n\nimport com.jayway.jsonpath.JsonPath;\n\nimport java.util.Deque;\nimport java.util.LinkedList;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.locks.ReentrantLock;\n\npublic class LRUCache implements Cache {\n\n    private final ReentrantLock lock = new ReentrantLock();\n\n    private final Map<String, JsonPath> map = new ConcurrentHashMap<String, JsonPath>();\n    private final Deque<String> queue = new LinkedList<String>();\n    private final int limit;\n\n    public LRUCache(int limit) {\n        this.limit = limit;\n    }\n\n    public void put(String key, JsonPath value) {\n        JsonPath oldValue = map.put(key, value);\n        if (oldValue != null) {\n            removeThenAddKey(key);\n        } else {\n            addKey(key);\n        }\n        if (map.size() > limit) {\n            map.remove(removeLast());\n        }\n    }\n\n    public JsonPath get(String key) {\n        JsonPath jsonPath = map.get(key);\n        if(jsonPath != null){\n            removeThenAddKey(key);\n        }\n        return jsonPath;\n    }\n\n    private void addKey(String key) {\n        lock.lock();\n        try {\n            queue.addFirst(key);\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    private String removeLast() {\n        lock.lock();\n        try {\n            final String removedKey = queue.removeLast();\n            return removedKey;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    private void removeThenAddKey(String key) {\n        lock.lock();\n        try {\n            queue.removeFirstOccurrence(key);\n            queue.addFirst(key);\n        } finally {\n            lock.unlock();\n        }\n\n    }\n\n    private void removeFirstOccurrence(String key) {\n        lock.lock();\n        try {\n            queue.removeFirstOccurrence(key);\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public JsonPath getSilent(String key) {\n        return map.get(key);\n    }\n\n    public void remove(String key) {\n        removeFirstOccurrence(key);\n        map.remove(key);\n    }\n\n    public int size() {\n        return map.size();\n    }\n\n    public String toString() {\n        return map.toString();\n    }\n}"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/cache/NOOPCache.java",
    "content": "package com.jayway.jsonpath.spi.cache;\n\nimport com.jayway.jsonpath.JsonPath;\n\npublic class NOOPCache implements Cache {\n\n    @Override\n    public JsonPath get(String key) {\n        return null;\n    }\n\n    @Override\n    public void put(String key, JsonPath value) {\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/json/AbstractJsonProvider.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.json;\n\nimport com.jayway.jsonpath.JsonPathException;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\n\npublic abstract class AbstractJsonProvider implements JsonProvider {\n\n    /**\n     * checks if object is an array\n     *\n     * @param obj object to check\n     * @return true if obj is an array\n     */\n    public boolean isArray(Object obj) {\n        return (obj instanceof List);\n    }\n\n    /**\n     * Extracts a value from an array\n     *\n     * @param obj an array\n     * @param idx index\n     * @return the entry at the given index\n     */\n    public Object getArrayIndex(Object obj, int idx) {\n        return ((List) obj).get(idx);\n    }\n\n    @Deprecated\n    public final Object getArrayIndex(Object obj, int idx, boolean unwrap){\n        return getArrayIndex(obj, idx);\n    }\n\n    public void setArrayIndex(Object array, int index, Object newValue) {\n        if (!isArray(array)) {\n            throw new UnsupportedOperationException();\n        } else {\n            List l = (List) array;\n            if (index == l.size()){\n                l.add(newValue);\n            }else {\n                l.set(index, newValue);\n            }\n        }\n    }\n\n\n    /**\n     * Extracts a value from an map\n     *\n     * @param obj a map\n     * @param key property key\n     * @return the map entry or {@link com.jayway.jsonpath.spi.json.JsonProvider#UNDEFINED} for missing properties\n     */\n    public Object getMapValue(Object obj, String key){\n        Map m = (Map) obj;\n        if(!m.containsKey(key)){\n            return JsonProvider.UNDEFINED;\n        } else {\n            return m.get(key);\n        }\n    }\n\n    /**\n     * Sets a value in an object\n     *\n     * @param obj   an object\n     * @param key   a String key\n     * @param value the value to set\n     */\n    @SuppressWarnings(\"unchecked\")\n    public void setProperty(Object obj, Object key, Object value) {\n        if (isMap(obj))\n            ((Map) obj).put(key.toString(), value);\n        else {\n            throw new JsonPathException(\"setProperty operation cannot be used with \" + obj!=null?obj.getClass().getName():\"null\");\n        }\n    }\n\n\n\n    /**\n     * Removes a value in an object or array\n     *\n     * @param obj   an array or an object\n     * @param key   a String key or a numerical index to remove\n     */\n    @SuppressWarnings(\"unchecked\")\n    public void removeProperty(Object obj, Object key) {\n        if (isMap(obj))\n            ((Map) obj).remove(key.toString());\n        else {\n            List list = (List) obj;\n            int index = key instanceof Integer ? (Integer) key : Integer.parseInt(key.toString());\n            list.remove(index);\n        }\n    }\n\n\n    /**\n     * checks if object is a map (i.e. no array)\n     *\n     * @param obj object to check\n     * @return true if the object is a map\n     */\n    public boolean isMap(Object obj) {\n        return (obj instanceof Map);\n    }\n\n    /**\n     * Returns the keys from the given object\n     *\n     * @param obj an object\n     * @return the keys for an object\n     */\n    @SuppressWarnings(\"unchecked\")\n    public Collection<String> getPropertyKeys(Object obj) {\n        if (isArray(obj)) {\n          throw new UnsupportedOperationException();\n        } else {\n            return ((Map) obj).keySet();\n        }\n    }\n\n    /**\n     * Get the length of an array or object\n     *\n     * @param obj an array or an object\n     * @return the number of entries in the array or object\n     */\n    public int length(Object obj) {\n        if (isArray(obj)) {\n            return ((List) obj).size();\n        } else if (isMap(obj)){\n            return getPropertyKeys(obj).size();\n        } else if(obj instanceof String){\n            return ((String)obj).length();\n        }\n        throw new JsonPathException(\"length operation cannot be applied to \" + (obj != null ? obj.getClass().getName()\n                : \"null\"));\n    }\n\n    /**\n     * Converts given array to an {@link Iterable}\n     *\n     * @param obj an array\n     * @return an Iterable that iterates over the entries of an array\n     */\n    @SuppressWarnings(\"unchecked\")\n    public Iterable<?> toIterable(Object obj) {\n        if (isArray(obj))\n            return ((Iterable) obj);\n        else\n            throw new JsonPathException(\"Cannot iterate over \" + obj!=null?obj.getClass().getName():\"null\");\n    }\n\n    @Override\n    public Object unwrap(Object obj) {\n        return obj;\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/json/GsonJsonProvider.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.json;\n\nimport com.google.gson.Gson;\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport com.google.gson.JsonParser;\nimport com.google.gson.JsonPrimitive;\nimport com.jayway.jsonpath.InvalidJsonException;\nimport com.jayway.jsonpath.JsonPathException;\n\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.UnsupportedEncodingException;\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\n\npublic class GsonJsonProvider extends AbstractJsonProvider {\n\n    private static final JsonParser PARSER = new JsonParser();\n    private final Gson gson;\n\n    /**\n     * Initializes the {@code GsonJsonProvider} using the default {@link Gson} object.\n     */\n    public GsonJsonProvider() {\n        this(new Gson());\n    }\n\n    /**\n     * Initializes the {@code GsonJsonProvider} using a customized {@link Gson} object.\n     *\n     * @param  gson  the customized Gson object.\n     */\n    public GsonJsonProvider(final Gson gson) {\n        this.gson = gson;\n    }\n\n    public Object unwrap(final Object o) {\n\n        if (o == null) {\n            return null;\n        }\n\n        if (!(o instanceof JsonElement)) {\n            return o;\n        }\n\n        JsonElement e = (JsonElement) o;\n\n        if (e.isJsonNull()) {\n            return null;\n        } else if (e.isJsonPrimitive()) {\n\n            JsonPrimitive p = e.getAsJsonPrimitive();\n            if (p.isString()) {\n                return p.getAsString();\n            } else if (p.isBoolean()) {\n                return p.getAsBoolean();\n            } else if (p.isNumber()) {\n                return unwrapNumber(p.getAsNumber());\n            }\n        }\n\n        return o;\n    }\n\n    private static boolean isPrimitiveNumber(final Number n) {\n        return n instanceof Integer ||\n                n instanceof Float ||\n                n instanceof Double ||\n                n instanceof Long ||\n                n instanceof BigDecimal ||\n                n instanceof BigInteger;\n    }\n\n    private static Number unwrapNumber(final Number n) {\n        Number unwrapped;\n\n        if (!isPrimitiveNumber(n)) {\n            BigDecimal bigDecimal = new BigDecimal(n.toString());\n            if (bigDecimal.scale() <= 0) {\n                if (bigDecimal.abs().compareTo(new BigDecimal(Integer.MAX_VALUE)) <= 0) {\n                    unwrapped = bigDecimal.intValue();\n                } else if (bigDecimal.abs().compareTo(new BigDecimal(Long.MAX_VALUE)) <= 0){\n                    unwrapped = bigDecimal.longValue();\n                } else {\n                    unwrapped = bigDecimal;\n                }\n            } else {\n                final double doubleValue = bigDecimal.doubleValue();\n                if (BigDecimal.valueOf(doubleValue).compareTo(bigDecimal) != 0) {\n                    unwrapped = bigDecimal;\n                } else {\n                    unwrapped = doubleValue;\n                }\n            }\n        } else {\n            unwrapped = n;\n        }\n        return unwrapped;\n    }\n\n    @Override\n    public Object parse(final String json) throws InvalidJsonException {\n        return PARSER.parse(json);\n    }\n\n    @Override\n    public Object parse(final InputStream jsonStream, final String charset) throws InvalidJsonException {\n\n        try {\n            return PARSER.parse(new InputStreamReader(jsonStream, charset));\n        } catch (UnsupportedEncodingException e) {\n            throw new JsonPathException(e);\n        }\n    }\n\n    @Override\n    public String toJson(final Object obj) {\n        return gson.toJson(obj);\n    }\n\n    @Override\n    public Object createArray() {\n        return new JsonArray();\n    }\n\n    @Override\n    public Object createMap() {\n        return new JsonObject();\n    }\n\n    @Override\n    public boolean isArray(final Object obj) {\n        return (obj instanceof JsonArray || obj instanceof List);\n    }\n\n    @Override\n    public Object getArrayIndex(final Object obj, final int idx) {\n        return toJsonArray(obj).get(idx);\n    }\n\n    @Override\n    public void setArrayIndex(final Object array, final int index, final Object newValue) {\n        if (!isArray(array)) {\n            throw new UnsupportedOperationException();\n        } else {\n            JsonArray arr = toJsonArray(array);\n            if (index == arr.size()) {\n                arr.add(createJsonElement(newValue));\n            } else {\n                arr.set(index, createJsonElement(newValue));\n            }\n        }\n    }\n\n    @Override\n    public Object getMapValue(final Object obj, final String key) {\n        JsonObject jsonObject = toJsonObject(obj);\n        Object o = jsonObject.get(key);\n        if (!jsonObject.has(key)) {\n            return UNDEFINED;\n        } else {\n            return unwrap(o);\n        }\n    }\n\n    @Override\n    public void setProperty(final Object obj, final Object key, final Object value) {\n        if (isMap(obj)) {\n            toJsonObject(obj).add(key.toString(), createJsonElement(value));\n        } else {\n            JsonArray array = toJsonArray(obj);\n            int index;\n            if (key != null) {\n                index = key instanceof Integer ? (Integer) key : Integer.parseInt(key.toString());\n            } else {\n                index = array.size();\n            }\n\n            if (index == array.size()) {\n                array.add(createJsonElement(value));\n            } else {\n                array.set(index, createJsonElement(value));\n            }\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public void removeProperty(final Object obj, final Object key) {\n        if (isMap(obj)) {\n            toJsonObject(obj).remove(key.toString());\n        } else {\n            JsonArray array = toJsonArray(obj);\n            int index = key instanceof Integer ? (Integer) key : Integer.parseInt(key.toString());\n            array.remove(index);\n        }\n    }\n\n    @Override\n    public boolean isMap(final Object obj) {\n\n        // return (obj instanceof JsonObject || obj instanceof Map);\n        return (obj instanceof JsonObject);\n    }\n\n    @Override\n    public Collection<String> getPropertyKeys(final Object obj) {\n        List<String> keys = new ArrayList<String>();\n        for (Map.Entry<String, JsonElement> entry : toJsonObject(obj).entrySet()) {\n            keys.add(entry.getKey());\n        }\n\n        return keys;\n    }\n\n    @Override\n    public int length(final Object obj) {\n        if (isArray(obj)) {\n            return toJsonArray(obj).size();\n        } else if (isMap(obj)) {\n            return toJsonObject(obj).entrySet().size();\n        } else {\n            if (obj instanceof JsonElement) {\n                JsonElement element = toJsonElement(obj);\n                if (element.isJsonPrimitive()) {\n                    return element.toString().length();\n                }\n            }\n        }\n        throw new JsonPathException(\"length operation can not applied to \" + (obj != null ? obj.getClass().getName()\n                                                                                         : \"null\"));\n    }\n\n    @Override\n    public Iterable<?> toIterable(final Object obj) {\n        JsonArray arr = toJsonArray(obj);\n        List<Object> values = new ArrayList<Object>(arr.size());\n        for (Object o : arr) {\n            values.add(unwrap(o));\n        }\n\n        return values;\n    }\n\n    private JsonElement createJsonElement(final Object o) {\n        return gson.toJsonTree(o);\n    }\n\n    private JsonArray toJsonArray(final Object o) {\n        return (JsonArray) o;\n    }\n\n    private JsonObject toJsonObject(final Object o) {\n        return (JsonObject) o;\n    }\n\n    private JsonElement toJsonElement(final Object o) {\n        return (JsonElement) o;\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/json/Jackson3JsonNodeJsonProvider.java",
    "content": "package com.jayway.jsonpath.spi.json;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.List;\n\nimport com.jayway.jsonpath.InvalidJsonException;\nimport com.jayway.jsonpath.JsonPathException;\nimport tools.jackson.core.JacksonException;\nimport tools.jackson.databind.JsonNode;\nimport tools.jackson.databind.ObjectMapper;\nimport tools.jackson.databind.node.ArrayNode;\nimport tools.jackson.databind.node.JsonNodeFactory;\nimport tools.jackson.databind.node.ObjectNode;\nimport tools.jackson.databind.node.StringNode;\n\npublic class Jackson3JsonNodeJsonProvider extends AbstractJsonProvider {\n\n    private static final ObjectMapper defaultObjectMapper = new ObjectMapper();\n\n    protected ObjectMapper objectMapper;\n\n    public ObjectMapper getObjectMapper() {\n        return objectMapper;\n    }\n\n    /**\n     * Initialize the JacksonJsonNodeJsonProvider with the default ObjectMapper and ObjectReader\n     */\n    public Jackson3JsonNodeJsonProvider() {\n        this(defaultObjectMapper);\n    }\n\n    /**\n     * Initialize the JacksonJsonNodeJsonProvider with a custom ObjectMapper and ObjectReader.\n     *\n     * @param objectMapper the ObjectMapper to use\n     */\n    public Jackson3JsonNodeJsonProvider(ObjectMapper objectMapper) {\n        this.objectMapper = objectMapper;\n    }\n\n    @Override\n    public Object parse(String json) throws InvalidJsonException {\n        try {\n            return objectMapper.readTree(json);\n        } catch (JacksonException e) {\n            throw new InvalidJsonException(e, json);\n        }\n    }\n\n    @Override\n    public Object parse(byte[] json) throws InvalidJsonException {\n        try {\n            return objectMapper.readTree(json);\n        } catch (JacksonException e) {\n            throw new InvalidJsonException(e, new String(json, StandardCharsets.UTF_8));\n        }\n    }\n\n    @Override\n    public Object parse(InputStream jsonStream, String charset) throws InvalidJsonException {\n        try {\n            return objectMapper.readTree(new InputStreamReader(jsonStream, charset));\n        } catch (IOException e) {\n            throw new InvalidJsonException(e);\n        }\n    }\n\n    @Override\n    public String toJson(Object obj) {\n        if (!(obj instanceof JsonNode)) {\n            throw new JsonPathException(\"Not a JSON Node\");\n        }\n        return obj.toString();\n    }\n\n    @Override\n    public Object createArray() {\n        return JsonNodeFactory.instance.arrayNode();\n    }\n\n    @Override\n    public Object createMap() {\n        return JsonNodeFactory.instance.objectNode();\n    }\n\n    public Object unwrap(Object o) {\n        if (o == null) {\n            return null;\n        }\n        if (!(o instanceof JsonNode)) {\n            return o;\n        }\n\n        JsonNode e = (JsonNode) o;\n\n        if (e.isValueNode()) {\n\n            if (e.isString()) {\n                return e.asString();\n            } else if (e.isBoolean()) {\n                return e.asBoolean();\n            } else if (e.isInt()) {\n                return e.asInt();\n            } else if (e.isLong()) {\n                return e.asLong();\n            } else if (e.isBigInteger()) {\n                return e.bigIntegerValue();\n            } else if (e.isDouble()) {\n                return e.doubleValue();\n            } else if (e.isFloat()) {\n                return e.floatValue();\n            } else if (e.isBigDecimal()) {\n                return e.decimalValue();\n            } else if (e.isNull()) {\n                return null;\n            }\n        }\n        return o;\n    }\n\n    @Override\n    public boolean isArray(Object obj) {\n        return (obj instanceof ArrayNode || obj instanceof List);\n    }\n\n    @Override\n    public Object getArrayIndex(Object obj, int idx) {\n        return toJsonArray(obj).get(idx);\n    }\n\n    @Override\n    public void setArrayIndex(Object array, int index, Object newValue) {\n        if (!isArray(array)) {\n            throw new UnsupportedOperationException();\n        } else {\n            ArrayNode arrayNode = toJsonArray(array);\n            if (index == arrayNode.size()) {\n                arrayNode.add(createJsonElement(newValue));\n            } else {\n                arrayNode.set(index, createJsonElement(newValue));\n            }\n        }\n    }\n\n    @Override\n    public Object getMapValue(Object obj, String key) {\n        ObjectNode jsonObject = toJsonObject(obj);\n        Object o = jsonObject.get(key);\n        if (!jsonObject.has(key)) {\n            return UNDEFINED;\n        } else {\n            return o;\n        }\n    }\n\n    @Override\n    public void setProperty(Object obj, Object key, Object value) {\n        // jlolling: Bug: #211 avoid create cloned nodes\n        if (isMap(obj)) {\n            setValueInObjectNode((ObjectNode) obj, key, value);\n        } else {\n            ArrayNode array = (ArrayNode) obj;\n            int index;\n            if (key != null) {\n                index = key instanceof Integer ? (Integer) key : Integer.parseInt(key.toString());\n            } else {\n                index = array.size();\n            }\n            if (index == array.size()) {\n                array.add(createJsonElement(value));\n            } else {\n                array.set(index, createJsonElement(value));\n            }\n        }\n    }\n\n    public void removeProperty(Object obj, Object key) {\n        if (isMap(obj)) {\n            toJsonObject(obj).remove(key.toString());\n        } else {\n            ArrayNode array = toJsonArray(obj);\n            int index = key instanceof Integer ? (Integer) key : Integer.parseInt(key.toString());\n            array.remove(index);\n        }\n    }\n\n    @Override\n    public boolean isMap(Object obj) {\n        return (obj instanceof ObjectNode);\n    }\n\n    @Override\n    public Collection<String> getPropertyKeys(Object obj) {\n        return toJsonObject(obj).propertyNames();\n    }\n\n    @Override\n    public int length(Object obj) {\n        if (isArray(obj)) {\n            return toJsonArray(obj).size();\n        } else if (isMap(obj)) {\n            return toJsonObject(obj).size();\n        } else {\n            if (obj instanceof StringNode) {\n                StringNode element = (StringNode) obj;\n                return element.size();\n            }\n        }\n        throw new JsonPathException(\"length operation can not applied to \" + (obj != null ? obj.getClass().getName() : \"null\"));\n    }\n\n    @Override\n    public Iterable<?> toIterable(Object obj) {\n        ArrayNode arr = toJsonArray(obj);\n        Iterator<?> iterator = arr.iterator();\n        return new Iterable<Object>() {\n            @Override\n            public Iterator<Object> iterator() {\n                return new Iterator<Object>() {\n                    @Override\n                    public boolean hasNext() {\n                        return iterator.hasNext();\n                    }\n\n                    @Override\n                    public Object next() {\n                        return unwrap(iterator.next());\n                    }\n                };\n            }\n        };\n    }\n\n    private JsonNode createJsonElement(Object o) {\n        if (o != null) {\n            // jlolling: avoid creating a cloned node: bug #211\n            if (o instanceof JsonNode) {\n                return (JsonNode) o;\n            } else {\n                return objectMapper.valueToTree(o);\n            }\n        } else {\n            return null;\n        }\n    }\n\n    private ArrayNode toJsonArray(Object o) {\n        return (ArrayNode) o;\n    }\n\n    private ObjectNode toJsonObject(Object o) {\n        return (ObjectNode) o;\n    }\n\n    private void setValueInObjectNode(ObjectNode objectNode, Object key, Object value) {\n        // jlolling: necessary to avoid deprecated methods and to avoid creating a cloned node. Bug: #211\n        if (value instanceof JsonNode) {\n            objectNode.set(key.toString(), (JsonNode) value);\n        } else if (value instanceof String) {\n            objectNode.put(key.toString(), (String) value);\n        } else if (value instanceof Integer) {\n            objectNode.put(key.toString(), (Integer) value);\n        } else if (value instanceof Long) {\n            objectNode.put(key.toString(), (Long) value);\n        } else if (value instanceof Short) {\n            objectNode.put(key.toString(), (Short) value);\n        } else if (value instanceof BigInteger) {\n            objectNode.put(key.toString(), (BigInteger) value);\n        } else if (value instanceof Double) {\n            objectNode.put(key.toString(), (Double) value);\n        } else if (value instanceof Float) {\n            objectNode.put(key.toString(), (Float) value);\n        } else if (value instanceof BigDecimal) {\n            objectNode.put(key.toString(), (BigDecimal) value);\n        } else if (value instanceof Boolean) {\n            objectNode.put(key.toString(), (Boolean) value);\n        } else if (value instanceof byte[]) {\n            objectNode.put(key.toString(), (byte[]) value);\n        } else if (value == null) {\n            objectNode.set(key.toString(), null); // this will create a null-node\n        } else {\n            objectNode.set(key.toString(), createJsonElement(value));\n        }\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/json/Jackson3JsonProvider.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.json;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.StringWriter;\nimport java.nio.charset.StandardCharsets;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport com.jayway.jsonpath.InvalidJsonException;\nimport tools.jackson.core.JacksonException;\nimport tools.jackson.databind.ObjectMapper;\nimport tools.jackson.databind.ObjectReader;\n\npublic class Jackson3JsonProvider extends AbstractJsonProvider {\n\n    private static final ObjectMapper defaultObjectMapper = new ObjectMapper();\n    private static final ObjectReader defaultObjectReader = defaultObjectMapper.reader().forType(Object.class);\n\n    protected ObjectMapper objectMapper;\n    protected ObjectReader objectReader;\n\n    public ObjectMapper getObjectMapper() {\n        return objectMapper;\n    }\n\n    /**\n     * Initialize the JacksonProvider with the default ObjectMapper and ObjectReader\n     */\n    public Jackson3JsonProvider() {\n        this(defaultObjectMapper, defaultObjectReader);\n    }\n\n    /**\n     * Initialize the JacksonProvider with a custom ObjectMapper.\n     *\n     * @param objectMapper the ObjectMapper to use\n     */\n    public Jackson3JsonProvider(ObjectMapper objectMapper) {\n        this(objectMapper, objectMapper.reader().forType(Object.class));\n    }\n\n    /**\n     * Initialize the JacksonProvider with a custom ObjectMapper and ObjectReader.\n     *\n     * @param objectMapper the ObjectMapper to use\n     * @param objectReader the ObjectReader to use\n     */\n    public Jackson3JsonProvider(ObjectMapper objectMapper, ObjectReader objectReader) {\n        this.objectMapper = objectMapper;\n        this.objectReader = objectReader;\n    }\n\n    @Override\n    public Object parse(String json) throws InvalidJsonException {\n        try {\n            return objectReader.readValue(json);\n        } catch (JacksonException e) {\n            throw new InvalidJsonException(e, json);\n        }\n    }\n\n    @Override\n    public Object parse(byte[] json) throws InvalidJsonException {\n        try {\n            return objectReader.readValue(json);\n        } catch (JacksonException e) {\n            throw new InvalidJsonException(e, new String(json, StandardCharsets.UTF_8));\n        }\n    }\n\n    @Override\n    public Object parse(InputStream jsonStream, String charset) throws InvalidJsonException {\n        try {\n            return objectReader.readValue(new InputStreamReader(jsonStream, charset));\n        } catch (IOException e) {\n            throw new InvalidJsonException(e);\n        }\n    }\n\n    @Override\n    public String toJson(Object obj) {\n        StringWriter writer = new StringWriter();\n        try {\n            objectMapper.writeValue(writer, obj);\n            writer.flush();\n            writer.close();\n            return writer.getBuffer().toString();\n        } catch (IOException e) {\n            throw new InvalidJsonException(e);\n        }\n    }\n\n    @Override\n    public List<Object> createArray() {\n        return new LinkedList<Object>();\n    }\n\n    @Override\n    public Object createMap() {\n        return new LinkedHashMap<String,Object>();\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/json/JacksonJsonNodeJsonProvider.java",
    "content": "package com.jayway.jsonpath.spi.json;\n\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.node.ArrayNode;\nimport com.fasterxml.jackson.databind.node.JsonNodeFactory;\nimport com.fasterxml.jackson.databind.node.ObjectNode;\nimport com.fasterxml.jackson.databind.node.TextNode;\nimport com.jayway.jsonpath.InvalidJsonException;\nimport com.jayway.jsonpath.JsonPathException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.nio.charset.StandardCharsets;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.List;\n\n\npublic class JacksonJsonNodeJsonProvider extends AbstractJsonProvider {\n\n    private static final ObjectMapper defaultObjectMapper = new ObjectMapper();\n\n    protected ObjectMapper objectMapper;\n\n    public ObjectMapper getObjectMapper() {\n        return objectMapper;\n    }\n\n    /**\n     * Initialize the JacksonJsonNodeJsonProvider with the default ObjectMapper and ObjectReader\n     */\n    public JacksonJsonNodeJsonProvider() {\n        this(defaultObjectMapper);\n    }\n\n    /**\n     * Initialize the JacksonJsonNodeJsonProvider with a custom ObjectMapper and ObjectReader.\n     *\n     * @param objectMapper the ObjectMapper to use\n     */\n    public JacksonJsonNodeJsonProvider(ObjectMapper objectMapper) {\n        this.objectMapper = objectMapper;\n    }\n\n    @Override\n    public Object parse(String json) throws InvalidJsonException {\n        try {\n            return objectMapper.readTree(json);\n        } catch (IOException e) {\n            throw new InvalidJsonException(e, json);\n        }\n    }\n\n    @Override\n    public Object parse(byte[] json)\n        throws InvalidJsonException {\n        try {\n            return objectMapper.readTree(json);\n        } catch (IOException e) {\n            throw new InvalidJsonException(e, new String(json, StandardCharsets.UTF_8));\n        }\n    }\n\n    @Override\n    public Object parse(InputStream jsonStream, String charset) throws InvalidJsonException {\n        try {\n            return objectMapper.readTree(new InputStreamReader(jsonStream, charset));\n        } catch (IOException e) {\n            throw new InvalidJsonException(e);\n        }\n    }\n\n    @Override\n    public String toJson(Object obj) {\n        if (!(obj instanceof JsonNode)) {\n            throw new JsonPathException(\"Not a JSON Node\");\n        }\n        return obj.toString();\n    }\n\n    @Override\n    public Object createArray() {\n        return JsonNodeFactory.instance.arrayNode();\n    }\n\n    @Override\n    public Object createMap() {\n        return JsonNodeFactory.instance.objectNode();\n    }\n\n    public Object unwrap(Object o) {\n        if (o == null) {\n            return null;\n        }\n        if (!(o instanceof JsonNode)) {\n            return o;\n        }\n\n        JsonNode e = (JsonNode) o;\n\n        if (e.isValueNode()) {\n\n            if (e.isTextual()) {\n                return e.asText();\n            } else if (e.isBoolean()) {\n                return e.asBoolean();\n            } else if (e.isInt()) {\n                return e.asInt();\n            } else if (e.isLong()) {\n                return e.asLong();\n            } else if (e.isBigInteger()) {\n                return e.bigIntegerValue();\n            } else if (e.isDouble()) {\n                return e.doubleValue();\n            } else if (e.isFloat()) {\n                return e.floatValue();\n            } else if (e.isBigDecimal()) {\n                return e.decimalValue();\n            } else if (e.isNull()) {\n                return null;\n            }\n        }\n        return o;\n    }\n\n\n    @Override\n    public boolean isArray(Object obj) {\n        return (obj instanceof ArrayNode || obj instanceof List);\n    }\n\n    @Override\n    public Object getArrayIndex(Object obj, int idx) {\n        return toJsonArray(obj).get(idx);\n    }\n\n    @Override\n    public void setArrayIndex(Object array, int index, Object newValue) {\n        if (!isArray(array)) {\n            throw new UnsupportedOperationException();\n        } else {\n            ArrayNode arrayNode = toJsonArray(array);\n            if (index == arrayNode.size()){\n                arrayNode.add(createJsonElement(newValue));\n            }else {\n                arrayNode.set(index, createJsonElement(newValue));\n            }\n        }\n    }\n\n    @Override\n    public Object getMapValue(Object obj, String key) {\n        ObjectNode jsonObject = toJsonObject(obj);\n        Object o = jsonObject.get(key);\n        if (!jsonObject.has(key)) {\n            return UNDEFINED;\n        } else {\n            return o;\n        }\n    }\n\n\t@Override\n\tpublic void setProperty(Object obj, Object key, Object value) {\n\t\t// jlolling: Bug: #211 avoid create cloned nodes\n        if (isMap(obj)) {\n        \tsetValueInObjectNode((ObjectNode) obj, key, value);\n        } else {\n            ArrayNode array = (ArrayNode) obj;\n            int index;\n            if (key != null) {\n                index = key instanceof Integer ? (Integer) key : Integer.parseInt(key.toString());\n            } else {\n                index = array.size();\n            }\n            if (index == array.size()) {\n                array.add(createJsonElement(value));\n            } else {\n                array.set(index, createJsonElement(value));\n            }\n        }\n\t}\n\n    public void removeProperty(Object obj, Object key) {\n        if (isMap(obj)) {\n            toJsonObject(obj).remove(key.toString());\n        } else {\n            ArrayNode array = toJsonArray(obj);\n            int index = key instanceof Integer ? (Integer) key : Integer.parseInt(key.toString());\n            array.remove(index);\n        }\n    }\n\n    @Override\n    public boolean isMap(Object obj) {\n        return (obj instanceof ObjectNode);\n    }\n\n    @Override\n    public Collection<String> getPropertyKeys(Object obj) {\n        List<String> keys = new ArrayList<String>();\n\n        Iterator<String> iter = toJsonObject(obj).fieldNames();\n        while (iter.hasNext()){\n            keys.add(iter.next());\n        }\n        return keys;\n    }\n\n    @Override\n    public int length(Object obj) {\n        if (isArray(obj)) {\n            return toJsonArray(obj).size();\n        } else if (isMap(obj)) {\n            return toJsonObject(obj).size();\n        } else {\n            if (obj instanceof TextNode) {\n                TextNode element = (TextNode) obj;\n                return element.size();\n            }\n        }\n        throw new JsonPathException(\"length operation can not applied to \" + (obj != null ? obj.getClass().getName()\n                : \"null\"));\n    }\n\n    @Override\n    public Iterable<?> toIterable(Object obj) {\n        ArrayNode arr = toJsonArray(obj);\n        Iterator<?> iterator = arr.iterator();\n        return new Iterable<Object>() {\n            @Override\n            public Iterator<Object> iterator() {\n                return new Iterator<Object>() {\n                    @Override\n                    public boolean hasNext() {\n                        return iterator.hasNext();\n                    }\n\n                    @Override\n                    public Object next() {\n                        return unwrap(iterator.next());\n                    }\n                };\n            }\n        };\n    }\n\n    private JsonNode createJsonElement(Object o) {\n    \tif (o != null) {\n    \t\t// jlolling: avoid creating a cloned node: bug #211\n    \t\tif (o instanceof JsonNode) {\n    \t\t\treturn (JsonNode) o;\n    \t\t} else {\n    \t        return objectMapper.valueToTree(o);\n    \t\t}\n    \t} else {\n    \t\treturn null;\n    \t}\n    }\n\n    private ArrayNode toJsonArray(Object o) {\n        return (ArrayNode) o;\n    }\n\n    private ObjectNode toJsonObject(Object o) {\n        return (ObjectNode) o;\n    }\n\n\tprivate void setValueInObjectNode(ObjectNode objectNode, Object key, Object value) {\n\t\t// jlolling: necessary to avoid deprecated methods and to avoid creating a cloned node. Bug: #211\n    \tif (value instanceof JsonNode) {\n            objectNode.set(key.toString(), (JsonNode) value);\n    \t} else if (value instanceof String) {\n    \t\tobjectNode.put(key.toString(), (String) value);\n    \t} else if (value instanceof Integer) {\n    \t\tobjectNode.put(key.toString(), (Integer) value);\n    \t} else if (value instanceof Long) {\n    \t\tobjectNode.put(key.toString(), (Long) value);\n    \t} else if (value instanceof Short) {\n    \t\tobjectNode.put(key.toString(), (Short) value);\n    \t} else if (value instanceof BigInteger) {\n            objectNode.put(key.toString(), (BigInteger) value);\n        } else if (value instanceof Double) {\n    \t\tobjectNode.put(key.toString(), (Double) value);\n    \t} else if (value instanceof Float) {\n    \t\tobjectNode.put(key.toString(), (Float) value);\n    \t} else if (value instanceof BigDecimal) {\n    \t\tobjectNode.put(key.toString(), (BigDecimal) value);\n    \t} else if (value instanceof Boolean) {\n    \t\tobjectNode.put(key.toString(), (Boolean) value);\n    \t} else if (value instanceof byte[]) {\n    \t\tobjectNode.put(key.toString(), (byte[]) value);\n    \t} else if (value == null) {\n    \t\tobjectNode.set(key.toString(), null); // this will create a null-node\n    \t} else {\n    \t\tobjectNode.set(key.toString(), createJsonElement(value));\n    \t}\n\t}\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/json/JacksonJsonProvider.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.json;\n\nimport com.fasterxml.jackson.core.JsonGenerator;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.ObjectReader;\nimport com.jayway.jsonpath.InvalidJsonException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.StringWriter;\nimport java.nio.charset.StandardCharsets;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedList;\nimport java.util.List;\n\n\npublic class JacksonJsonProvider extends AbstractJsonProvider {\n\n    private static final ObjectMapper defaultObjectMapper = new ObjectMapper();\n    private static final ObjectReader defaultObjectReader = defaultObjectMapper.reader().forType(Object.class);\n\n    protected ObjectMapper objectMapper;\n    protected ObjectReader objectReader;\n\n    public ObjectMapper getObjectMapper() {\n        return objectMapper;\n    }\n\n    /**\n     * Initialize the JacksonProvider with the default ObjectMapper and ObjectReader\n     */\n    public JacksonJsonProvider() {\n      this(defaultObjectMapper, defaultObjectReader);\n    }\n\n    /**\n     * Initialize the JacksonProvider with a custom ObjectMapper.\n     * @param objectMapper the ObjectMapper to use\n     */\n    public JacksonJsonProvider(ObjectMapper objectMapper) {\n      this(objectMapper, objectMapper.reader().forType(Object.class));\n    }\n\n    /**\n     * Initialize the JacksonProvider with a custom ObjectMapper and ObjectReader.\n     * @param objectMapper the ObjectMapper to use\n     * @param objectReader the ObjectReader to use\n     */\n    public JacksonJsonProvider(ObjectMapper objectMapper, ObjectReader objectReader) {\n      this.objectMapper = objectMapper;\n      this.objectReader = objectReader;\n    }\n\n    @Override\n    public Object parse(String json) throws InvalidJsonException {\n        try {\n            return objectReader.readValue(json);\n        } catch (IOException e) {\n            throw new InvalidJsonException(e, json);\n        }\n    }\n\n    @Override\n    public Object parse(byte[] json)\n        throws InvalidJsonException {\n        try {\n            return objectReader.readValue(json);\n        } catch (IOException e) {\n            throw new InvalidJsonException(e, new String(json, StandardCharsets.UTF_8));\n        }\n    }\n\n    @Override\n    public Object parse(InputStream jsonStream, String charset) throws InvalidJsonException {\n        try {\n            return objectReader.readValue(new InputStreamReader(jsonStream, charset));\n        } catch (IOException e) {\n            throw new InvalidJsonException(e);\n        }\n    }\n\n    @Override\n    public String toJson(Object obj) {\n        StringWriter writer = new StringWriter();\n        try {\n            JsonGenerator generator = objectMapper.getFactory().createGenerator(writer);\n            objectMapper.writeValue(generator, obj);\n            writer.flush();\n            writer.close();\n            generator.close();\n            return writer.getBuffer().toString();\n        } catch (IOException e) {\n            throw new InvalidJsonException(e);\n        }\n    }\n\n    @Override\n    public List<Object> createArray() {\n        return new LinkedList<Object>();\n    }\n\n    @Override\n    public Object createMap() {\n        return new LinkedHashMap<String, Object>();\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/json/JakartaJsonProvider.java",
    "content": "package com.jayway.jsonpath.spi.json;\r\n\r\nimport com.jayway.jsonpath.InvalidJsonException;\r\nimport com.jayway.jsonpath.JsonPathException;\r\nimport jakarta.json.JsonArray;\r\nimport jakarta.json.JsonArrayBuilder;\r\nimport jakarta.json.JsonBuilderFactory;\r\nimport jakarta.json.JsonNumber;\r\nimport jakarta.json.JsonObject;\r\nimport jakarta.json.JsonObjectBuilder;\r\nimport jakarta.json.JsonReader;\r\nimport jakarta.json.JsonString;\r\nimport jakarta.json.JsonStructure;\r\nimport jakarta.json.JsonValue;\r\nimport jakarta.json.spi.JsonProvider;\r\nimport jakarta.json.stream.JsonParsingException;\r\nimport java.io.ByteArrayInputStream;\r\nimport java.io.InputStream;\r\nimport java.io.InputStreamReader;\r\nimport java.io.Reader;\r\nimport java.io.StringReader;\r\nimport java.io.UnsupportedEncodingException;\r\nimport java.math.BigDecimal;\r\nimport java.math.BigInteger;\r\nimport java.nio.charset.StandardCharsets;\r\nimport java.util.AbstractSet;\r\nimport java.util.ArrayList;\r\nimport java.util.Collection;\r\nimport java.util.ConcurrentModificationException;\r\nimport java.util.Iterator;\r\nimport java.util.LinkedHashMap;\r\nimport java.util.LinkedList;\r\nimport java.util.List;\r\nimport java.util.ListIterator;\r\nimport java.util.Map;\r\nimport java.util.Set;\r\n\r\n\r\npublic class JakartaJsonProvider extends AbstractJsonProvider {\r\n\r\n    private static final JsonProvider defaultJsonProvider = JsonProvider.provider();\r\n    private static final JsonBuilderFactory jsonBuilderFactory = defaultJsonProvider.createBuilderFactory(null);\r\n\r\n    private final boolean mutableJson;\r\n\r\n    /**\r\n     * Constructs new instance of parsing and serialization adapter for Jakarta EE 9\r\n     * JSON-P default provider. JSON files, strings, and streams can be loaded, parsed,\r\n     * and navigated with JsonPath expressions, and values retrieved - but no changes\r\n     * to the loaded JSON document are permitted, and will yield exceptions.\r\n     */\r\n    public JakartaJsonProvider() {\r\n    \tthis.mutableJson = false;\r\n    }\r\n\r\n    /**\r\n     * Constructs new instance of parsing and serialization adapter for Jakarta EE 9\r\n     * JSON-P default provider, and optionally enables proxying of {@code JsonObject}\r\n     * and {@code JsonArray} entities to implement mutable JSON structures. By default,\r\n     * all structures and values produced and consumed by JSON-P are immutable. This\r\n     * comes at an extra cost to perfomance and memory consumption, so enable only if\r\n     * expected use cases include add/put/replace/delete operations on JSON document. \r\n     * \r\n     * @param mutableJson enable dynamic proxies for JSON structures\r\n     */\r\n    public JakartaJsonProvider(boolean mutableJson) {\r\n    \tthis.mutableJson = mutableJson;\r\n    }\r\n\r\n    @Override\r\n    public Object parse(String json) throws InvalidJsonException {\r\n        return parse(new StringReader(json));\r\n    }\r\n\r\n    @Override\r\n    public Object parse(byte[] json)\r\n        throws InvalidJsonException {\r\n        return parse(new InputStreamReader(new ByteArrayInputStream(json), StandardCharsets.UTF_8));\r\n    }\r\n\r\n    @Override\r\n    public Object parse(InputStream jsonStream, String charset) throws InvalidJsonException {\r\n        try {\r\n            return parse(new InputStreamReader(jsonStream, charset));\r\n        } catch (UnsupportedEncodingException e) {\r\n            throw new JsonPathException(e);\r\n        }\r\n    }\r\n\r\n  private Object parse(Reader jsonInput) {\r\n    try (JsonReader jsonReader = defaultJsonProvider.createReader(jsonInput)) {\r\n        JsonStructure jsonStruct = jsonReader.read();\r\n        return mutableJson ? proxyAll(jsonStruct) : jsonStruct;\r\n    } catch (JsonParsingException e) {\r\n        throw new InvalidJsonException(e);\r\n    }\r\n    // not catching a JsonException as it never happens here\r\n  }\r\n\r\n    @Override\r\n    public String toJson(Object obj) {\r\n        if (obj instanceof JsonObjectBuilder) {\r\n            obj = ((JsonObjectBuilder) obj).build();\r\n        } else if (obj instanceof JsonArrayBuilder) {\r\n            obj = ((JsonArrayBuilder) obj).build();\r\n        } else if (obj instanceof List) {\r\n            obj = jsonBuilderFactory.createArrayBuilder((Collection<?>) obj).build();\r\n        }\r\n        return obj.toString();\r\n    }\r\n\r\n    @Override\r\n    public Object createArray() {\r\n    \tif (mutableJson) {\r\n    \t\treturn new JsonArrayProxy(jsonBuilderFactory.createArrayBuilder().build());\r\n    \t} else {\r\n    \t\treturn new LinkedList<Object>();\r\n    \t}\r\n    }\r\n\r\n    @Override\r\n    public Object createMap() {\r\n    \tif (mutableJson) {\r\n    \t\treturn new JsonObjectProxy(jsonBuilderFactory.createObjectBuilder().build());\r\n    \t} else {\r\n    \t\treturn jsonBuilderFactory.createObjectBuilder();\r\n    \t}\r\n    }\r\n\r\n    @Override\r\n    public boolean isArray(Object obj) {\r\n        return (obj instanceof JsonArray || obj instanceof JsonArrayBuilder || obj instanceof List);\r\n    }\r\n\r\n    @Override\r\n    public Object getArrayIndex(Object obj, int idx) {\r\n        if (obj instanceof JsonArrayBuilder) {\r\n            obj = ((JsonArrayBuilder) obj).build();\r\n        }\r\n        if (obj instanceof JsonArray) {\r\n            return ((JsonArray) obj).get(idx);\r\n        } else if (obj instanceof List<?>) {\r\n        \treturn super.getArrayIndex(obj, idx);\r\n        } else {\r\n            throw new UnsupportedOperationException();\r\n        }\r\n    }\r\n\r\n    @Override\r\n    public void setArrayIndex(Object array, int index, Object newValue) {\r\n        if (array instanceof JsonArrayBuilder) {\r\n            // next line is not optimal, but ArrayBuilder has no size() method\r\n            if (index == ((JsonArrayBuilder) array).build().size()) {\r\n                array = ((JsonArrayBuilder) array).add(wrap(newValue));\r\n            } else {\r\n                array = ((JsonArrayBuilder) array).set(index, wrap(newValue));\r\n            }\r\n        } else if (array instanceof JsonArray) {\r\n        \tif (mutableJson && array instanceof JsonArrayProxy) {\r\n        \t\t((JsonArrayProxy) array).set(index, wrap(newValue));\r\n        \t} else {\r\n        \t\tthrow new UnsupportedOperationException(\"JsonArray is immutable in JSON-P\");\r\n        \t}\r\n        } else {\r\n            super.setArrayIndex(array, index, wrap(newValue));\r\n        }\r\n    }\r\n\r\n    @Override\r\n    public Object getMapValue(Object obj, String key) {\r\n        if (obj instanceof JsonObjectBuilder) {\r\n            obj = ((JsonObjectBuilder) obj).build();\r\n        }\r\n        if (obj instanceof JsonObject) {\r\n            JsonValue o = ((JsonObject) obj).get(key);\r\n            if (o == null) {\r\n                return UNDEFINED;\r\n            } else {\r\n                return unwrap(o);\r\n            }\r\n        } else {\r\n            throw new UnsupportedOperationException();\r\n        }\r\n    }\r\n\r\n    @Override\r\n    public void setProperty(Object obj, Object key, Object value) {\r\n        if (obj instanceof JsonObjectBuilder) {\r\n            ((JsonObjectBuilder) obj).add(key.toString(), wrap(value));\r\n        } else if (mutableJson && obj instanceof JsonObjectProxy) {\r\n    \t\t((JsonObjectProxy) obj).put(key.toString(), wrap(value));\r\n    \t} else if (obj instanceof JsonObject) {\r\n    \t\tthrow new UnsupportedOperationException(\"JsonObject is immutable in JSON-P\");\r\n    \t} else if (obj instanceof JsonArrayBuilder) {\r\n    \t\tif (key == null) {\r\n    \t\t\t((JsonArrayBuilder) obj).add(wrap(value));\r\n    \t\t} else {\r\n\t\t\t\t((JsonArrayBuilder) obj).set(toArrayIndex(key), wrap(value));\r\n    \t\t}\r\n        } else if (mutableJson && obj instanceof JsonArrayProxy) {\r\n        \tif (key == null) {\r\n    \t\t\t((JsonArrayProxy) obj).add(wrap(value));\r\n        \t} else {\r\n        \t\t((JsonArrayProxy) obj).set(toArrayIndex(key), wrap(value));\r\n    \t\t}\r\n    \t} else if (obj instanceof JsonArray) {\r\n    \t\tthrow new UnsupportedOperationException(\"JsonArray is immutable in JSON-P\");\r\n        } else if (obj instanceof List) {\r\n        \t@SuppressWarnings(\"unchecked\")\r\n        \tList<JsonValue> array = (List<JsonValue>) obj;\r\n        \tif (key == null) {\r\n        \t\tarray.add(wrap(value));\r\n        \t} else {\r\n        \t\tarray.add(toArrayIndex(key), wrap(value));\r\n        \t}\r\n        } else {\r\n            throw new UnsupportedOperationException();\r\n        }\r\n    }\r\n\r\n    @SuppressWarnings(\"rawtypes\")\r\n    public void removeProperty(Object obj, Object key) {\r\n        if (obj instanceof JsonObjectBuilder) {\r\n            ((JsonObjectBuilder) obj).remove(key.toString());\r\n        } else if (obj instanceof JsonObject) {\r\n        \tif (mutableJson && obj instanceof JsonObjectProxy) {\r\n        \t\t((JsonObjectProxy) obj).remove(key);\r\n        \t} else {\r\n        \t\tthrow new UnsupportedOperationException(\"JsonObject is immutable in JSON-P\");\r\n        \t}\r\n        } else if (isArray(obj)) {\r\n            int index = toArrayIndex(key).intValue();\r\n            if (obj instanceof JsonArrayBuilder) {\r\n                ((JsonArrayBuilder) obj).remove(index);\r\n            } else if (obj instanceof List) {\r\n            \t// this also covers JsonArray as it implements List<>\r\n                ((List) obj).remove(index);\r\n            }\r\n        } else {\r\n            throw new UnsupportedOperationException();\r\n        }\r\n    }\r\n\r\n    @Override\r\n    public boolean isMap(Object obj) {\r\n        return (obj instanceof JsonObject || obj instanceof JsonObjectBuilder);\r\n    }\r\n\r\n    @Override\r\n    public Collection<String> getPropertyKeys(Object obj) {\r\n        Set<String> keys;\r\n        if (obj instanceof JsonObjectBuilder) {\r\n            keys = ((JsonObjectBuilder) obj).build().keySet();\r\n        } else if (obj instanceof JsonObject) {\r\n            keys = ((JsonObject) obj).keySet();\r\n        } else {\r\n            throw new UnsupportedOperationException(\"Json object is expected\");\r\n        }\r\n        return new ArrayList<String>(keys);\r\n    }\r\n\r\n    @Override\r\n    public int length(Object obj) {\r\n        if (isArray(obj)) {\r\n            if (obj instanceof JsonArrayBuilder) {\r\n                return ((JsonArrayBuilder) obj).build().size();\r\n            } else {\r\n                return ((List<?>) obj).size();\r\n            }\r\n        } else if (isMap(obj)) {\r\n            if (obj instanceof JsonObjectBuilder) {\r\n                obj = ((JsonObjectBuilder) obj).build();\r\n            }\r\n            return ((JsonObject) obj).size();\r\n        } else {\r\n            if (obj instanceof CharSequence) {\r\n                return ((CharSequence) obj).length();\r\n            }\r\n        }\r\n        String className = obj != null ? obj.getClass().getName() : null;\r\n        throw new JsonPathException(\"length operation can not applied to \" + className);\r\n    }\r\n\r\n    @Override\r\n    public Iterable<?> toIterable(Object obj) {\r\n        List<Object> values;\r\n        if (isArray(obj)) {\r\n            if (obj instanceof JsonArrayBuilder) {\r\n                obj = ((JsonArrayBuilder) obj).build();\r\n            }\r\n            values = new ArrayList<Object>(((List<?>) obj).size());\r\n            for (Object val : ((List<?>) obj)) {\r\n                values.add(unwrap(val));\r\n            }\r\n        } else if (isMap(obj)) {\r\n            if (obj instanceof JsonObjectBuilder) {\r\n                obj = ((JsonObjectBuilder) obj).build();\r\n            }\r\n            values = new ArrayList<Object>(((JsonObject) obj).size());\r\n            for (JsonValue val : ((JsonObject) obj).values()) {\r\n                values.add(unwrap(val));\r\n            }\r\n        } else {\r\n            throw new UnsupportedOperationException(\"an array or object instance is expected\");\r\n        }\r\n        return values;\r\n    }\r\n\r\n    @Override\r\n    public Object unwrap(Object obj) {\r\n        if (obj == null) {\r\n            return null;\r\n        }\r\n        if (!(obj instanceof JsonValue)) {\r\n            return obj;\r\n        }\r\n        switch (((JsonValue) obj).getValueType()) {\r\n        case ARRAY:\r\n        \tif (mutableJson && obj instanceof JsonArrayProxy) {\r\n        \t\treturn (JsonArray) obj;\r\n        \t} else {\r\n        \t\treturn ((JsonArray) obj).getValuesAs((JsonValue v) -> unwrap(v));\r\n        \t}\r\n        case STRING:\r\n            return ((JsonString) obj).getString();\r\n        case NUMBER:\r\n            if (((JsonNumber) obj).isIntegral()) {\r\n                //return ((JsonNumber) obj).bigIntegerValueExact();\r\n                try {\r\n                    return ((JsonNumber) obj).intValueExact();\r\n                } catch (ArithmeticException e) {\r\n                    return ((JsonNumber) obj).longValueExact();\r\n                }\r\n            } else {\r\n                //return ((JsonNumber) obj).bigDecimalValue();\r\n                return ((JsonNumber) obj).doubleValue();\r\n            }\r\n        case TRUE:\r\n            return Boolean.TRUE;\r\n        case FALSE:\r\n            return Boolean.FALSE;\r\n        case NULL:\r\n            return null;\r\n        default:\r\n            return obj;\r\n        }\r\n    }\r\n\r\n    private Integer toArrayIndex(Object index) {\r\n        try {\r\n        \tif (index instanceof Integer) {\r\n        \t\treturn (Integer) index;\r\n        \t} else if (index instanceof Long) {\r\n        \t\treturn Integer.valueOf(((Long) index).intValue());\r\n        \t} else if (index != null) {\r\n        \t\treturn Integer.valueOf(index.toString());\r\n        \t} else {\r\n        \t\t//return null;\r\n\t\t\t\tthrow new IllegalArgumentException(\"Invalid array index\");\r\n            }\r\n        } catch (NumberFormatException e) {\r\n            throw new JsonPathException(e);\r\n        }\r\n    }\r\n\r\n    private JsonValue wrap(Object obj) {\r\n        if (obj == null) {\r\n            return JsonValue.NULL;\r\n        } else if (obj instanceof JsonArray) {\r\n        \tif (!mutableJson || obj instanceof JsonArrayProxy) {\r\n        \t\treturn (JsonArray) obj;\r\n        \t} else {\r\n        \t\treturn proxyAll((JsonArray) obj);\r\n        \t}\r\n        } else if (obj instanceof JsonObject) {\r\n        \tif (!mutableJson || obj instanceof JsonObjectProxy) {\r\n        \t\treturn (JsonObject) obj;\r\n        \t} else {\r\n        \t\treturn proxyAll((JsonObject) obj);\r\n        \t}\r\n        } else if (obj instanceof JsonValue) {\r\n            return (JsonValue) obj;\r\n        } else if (Boolean.TRUE.equals(obj)) {\r\n            return JsonValue.TRUE;\r\n        } else if (Boolean.FALSE.equals(obj)) {\r\n            return JsonValue.FALSE;\r\n        } else if (obj instanceof CharSequence) {\r\n            return defaultJsonProvider.createValue(obj.toString());\r\n        } else if (obj instanceof Number) {\r\n            if (obj instanceof Integer) {\r\n                int v = ((Number) obj).intValue();\r\n                return defaultJsonProvider.createValue(v);\r\n            } else if (obj instanceof Long) {\r\n            \tlong v = ((Number) obj).longValue();\r\n            \treturn defaultJsonProvider.createValue(v);\r\n            } else if ((obj instanceof Float) || (obj instanceof Double)) {\r\n                double v = ((Number) obj).doubleValue();\r\n                return defaultJsonProvider.createValue(v);\r\n            } else if (obj instanceof BigInteger) {\r\n                return defaultJsonProvider.createValue((BigInteger) obj);\r\n            } else if (obj instanceof BigDecimal) {\r\n                return defaultJsonProvider.createValue((BigDecimal) obj);\r\n            } else {\r\n                // default to BigDecimal conversion for other numeric types\r\n                BigDecimal v = BigDecimal.valueOf(((Number) obj).doubleValue());\r\n                return defaultJsonProvider.createValue(v);\r\n            }\r\n        } else if (obj instanceof Collection) {\r\n    \t\tJsonArray result = jsonBuilderFactory.createArrayBuilder((Collection<?>) obj).build();\r\n    \t\treturn mutableJson ? proxyAll(result) : result;\r\n        } else if (obj instanceof Map) {\r\n    \t\t@SuppressWarnings(\"unchecked\")\r\n    \t\tMap<String, Object> map = (Map<String, Object>) obj;\r\n    \t\tJsonObject result = jsonBuilderFactory.createObjectBuilder(map).build();\r\n    \t\treturn mutableJson ? proxyAll(result) : result;\r\n        } else if (obj instanceof JsonArrayBuilder) {\r\n        \tJsonArray result = ((JsonArrayBuilder) obj).build();\r\n    \t\treturn mutableJson ? proxyAll(result) : result;\r\n        } else if (obj instanceof JsonObjectBuilder) {\r\n        \tJsonObject result = ((JsonObjectBuilder) obj).build();\r\n    \t\treturn mutableJson ? proxyAll(result) : result;\r\n        } else {\r\n            String className = obj.getClass().getSimpleName();\r\n            throw new UnsupportedOperationException(\"Cannot create JSON element from \" + className);\r\n        }\r\n    }\r\n\r\n    private JsonStructure proxyAll(JsonStructure jsonStruct) {\r\n    \tif (jsonStruct == null) {\r\n    \t\treturn null;\r\n    \t} else if (jsonStruct instanceof JsonArrayProxy) {\r\n    \t\treturn (JsonArray) jsonStruct;\r\n    \t} else if (jsonStruct instanceof JsonArray) {\r\n    \t\tList<Object> array = new ArrayList<>();\r\n    \t\tfor (JsonValue v : (JsonArray) jsonStruct) {\r\n    \t\t\tif (v instanceof JsonStructure) {\r\n    \t\t\t\tv = proxyAll((JsonStructure) v);\r\n    \t\t\t}\r\n    \t\t\tarray.add(v);\r\n    \t\t}\r\n    \t\treturn new JsonArrayProxy(jsonBuilderFactory.createArrayBuilder(array).build());\r\n    \t} else if (jsonStruct instanceof JsonObjectProxy) {\r\n    \t\treturn (JsonObject) jsonStruct;\r\n    \t} else if (jsonStruct instanceof JsonObject) {\r\n    \t\tMap<String, Object> map = new LinkedHashMap<>();\r\n    \t\tfor (Map.Entry<String, JsonValue> e : ((JsonObject) jsonStruct).entrySet()) {\r\n    \t\t\tJsonValue v = e.getValue();\r\n    \t\t\tif (v instanceof JsonStructure) {\r\n    \t\t\t\tv = proxyAll((JsonStructure) v);\r\n    \t\t\t}\r\n    \t\t\tmap.put(e.getKey(), v);\r\n    \t\t}\r\n    \t\treturn new JsonObjectProxy(jsonBuilderFactory.createObjectBuilder(map).build());\r\n    \t} else {\r\n    \t\tthrow new IllegalArgumentException();\r\n    \t}\r\n    }\r\n\r\n    private static class JsonArrayProxy implements JsonArray {\r\n\r\n    \tprivate JsonArray arr;\r\n\r\n    \tJsonArrayProxy(JsonArray arr) {\r\n    \t\tthis.arr = arr;\r\n    \t}\r\n\r\n        @Override\r\n        public JsonObject getJsonObject(int index) {\r\n        \treturn arr.getJsonObject(index);\r\n        }\r\n\r\n        @Override\r\n        public JsonArray getJsonArray(int index) {\r\n        \treturn arr.getJsonArray(index);\r\n        }\r\n\r\n        @Override\r\n        public JsonNumber getJsonNumber(int index) {\r\n        \treturn arr.getJsonNumber(index);\r\n        }\r\n\r\n        @Override\r\n        public JsonString getJsonString(int index) {\r\n        \treturn arr.getJsonString(index);\r\n        }\r\n\r\n\t\t@Override\r\n\t\tpublic <T extends JsonValue> List<T> getValuesAs(Class<T> clazz) {\r\n        \treturn arr.getValuesAs(clazz);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic String getString(int index) {\r\n        \treturn arr.getString(index);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic String getString(int index, String defaultValue) {\r\n        \treturn arr.getString(index, defaultValue);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic int getInt(int index) {\r\n        \treturn arr.getInt(index);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic int getInt(int index, int defaultValue) {\r\n        \treturn arr.getInt(index, defaultValue);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean getBoolean(int index) {\r\n        \treturn arr.getBoolean(index);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean getBoolean(int index, boolean defaultValue) {\r\n        \treturn arr.getBoolean(index, defaultValue);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean isNull(int index) {\r\n        \treturn arr.isNull(index);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic ValueType getValueType() {\r\n\t\t\treturn arr.getValueType();\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic int size() {\r\n\t\t\treturn arr.size();\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean isEmpty() {\r\n\t\t\treturn arr.isEmpty();\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean contains(Object o) {\r\n\t\t\treturn arr.contains(o);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic Iterator<JsonValue> iterator() {\r\n\t\t\treturn new Iterator<JsonValue>() {\r\n\r\n\t\t\t\tfinal JsonArray refArr = arr;\r\n\t\t\t\tfinal Iterator<JsonValue> it = arr.iterator();\r\n\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic boolean hasNext() {\r\n\t\t\t\t\tif (refArr == arr) {\r\n\t\t\t\t\t\treturn it.hasNext();\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthrow new ConcurrentModificationException();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic JsonValue next() {\r\n\t\t\t\t\tif (refArr == arr) {\r\n\t\t\t\t\t\treturn it.next();\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthrow new ConcurrentModificationException();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic Object[] toArray() {\r\n\t\t\treturn arr.toArray();\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic <T> T[] toArray(T[] a) {\r\n\t\t\treturn arr.toArray(a);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean add(JsonValue e) {\r\n\t\t\tarr = jsonBuilderFactory.createArrayBuilder(arr).add(e).build();\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean remove(Object o) {\r\n\t\t\tint i = arr.indexOf(o);\r\n\t\t\tif (i != -1) {\r\n\t\t\t\tarr = jsonBuilderFactory.createArrayBuilder(arr).remove(i).build();\r\n\t\t\t\treturn true;\r\n\t\t\t} else {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean containsAll(Collection<?> c) {\r\n\t\t\treturn arr.containsAll(c);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean addAll(Collection<? extends JsonValue> c) {\r\n\t\t\tif (!c.isEmpty()) {\r\n\t\t\t\tJsonArrayBuilder builder = jsonBuilderFactory.createArrayBuilder(arr);\r\n\t\t\t\tfor (JsonValue v : c) {\r\n\t\t\t\t\tbuilder.add(v);\r\n\t\t\t\t}\r\n\t\t\t\tarr = builder.build();\r\n\t\t\t\treturn true;\r\n\t\t\t} else { \r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean addAll(int index, Collection<? extends JsonValue> c) {\r\n\t\t\tif (c.isEmpty()) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tif (index < 0 || index >= arr.size()) {\r\n\t\t\t\tthrow new IndexOutOfBoundsException();\r\n\t\t\t}\r\n\t\t\tJsonArrayBuilder builder = jsonBuilderFactory.createArrayBuilder(arr);\r\n\t\t\tfor (int i = 0; i < arr.size(); i++) {\r\n\t\t\t\tif (index == i) {\r\n\t\t\t\t\tfor (JsonValue v : c) {\r\n\t\t\t\t\t\tbuilder.add(v);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbuilder.add(arr.get(i));\r\n\t\t\t}\r\n\t\t\tarr = builder.build();\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean removeAll(Collection<?> c) {\r\n\t\t\tif (c.isEmpty()) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\tJsonArrayBuilder builder = null;\r\n\t\t\tfor (int i = 0, j = 0; i < arr.size(); i++, j++) {\r\n\t\t\t\tif (c.contains(arr.get(i))) {\r\n\t\t\t\t\tif (builder == null) {\r\n\t\t\t\t\t\tbuilder = jsonBuilderFactory.createArrayBuilder(arr);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbuilder.remove(j--);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (builder != null) {\r\n\t\t\t\tarr = builder.build();\r\n\t\t\t\treturn true;\r\n\t\t\t} else {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean retainAll(Collection<?> c) {\r\n\t\t\tif (c.isEmpty()) {\r\n\t\t\t\tarr = jsonBuilderFactory.createArrayBuilder().build();\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tJsonArrayBuilder builder = null;\r\n\t\t\tfor (int i = 0, j = 0; i < arr.size(); i++, j++) {\r\n\t\t\t\tif (!c.contains(arr.get(i))) {\r\n\t\t\t\t\tif (builder == null) {\r\n\t\t\t\t\t\tbuilder = jsonBuilderFactory.createArrayBuilder(arr);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbuilder.remove(j--);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (builder != null) {\r\n\t\t\t\tarr = builder.build();\r\n\t\t\t\treturn true;\r\n\t\t\t} else {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic void clear() {\r\n\t\t\tarr = jsonBuilderFactory.createArrayBuilder().build();\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic JsonValue get(int index) {\r\n\t\t\treturn arr.get(index);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic JsonValue set(int index, JsonValue element) {\r\n\t\t\tif (index == arr.size()) {\r\n\t\t\t\tarr = jsonBuilderFactory.createArrayBuilder(arr).add(index, element).build();\r\n\t\t\t\treturn null;\r\n\t\t\t} else {\r\n\t\t\t\tJsonValue oldValue = arr.get(index);\r\n\t\t\t\tarr = jsonBuilderFactory.createArrayBuilder(arr).set(index, element).build();\r\n\t\t\t\treturn oldValue;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic void add(int index, JsonValue element) {\r\n\t\t\tarr = jsonBuilderFactory.createArrayBuilder(arr).add(index, element).build();\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic JsonValue remove(int index) {\r\n\t\t\tJsonValue oldValue = arr.get(index);\r\n\t\t\tarr = jsonBuilderFactory.createArrayBuilder(arr).remove(index).build();\r\n\t\t\treturn oldValue;\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic int indexOf(Object o) {\r\n\t\t\treturn arr.indexOf(o);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic int lastIndexOf(Object o) {\r\n\t\t\treturn arr.lastIndexOf(o);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic ListIterator<JsonValue> listIterator() {\r\n\t\t\treturn listIterator(0);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic ListIterator<JsonValue> listIterator(int index) {\r\n\t\t\treturn new ListIterator<JsonValue>() {\r\n\r\n\t\t\t\tfinal JsonArray refArr = arr;\r\n\t\t\t\tfinal ListIterator<JsonValue> it = arr.listIterator(index);\r\n\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic boolean hasNext() {\r\n\t\t\t\t\tif (refArr == arr) {\r\n\t\t\t\t\t\treturn it.hasNext();\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthrow new ConcurrentModificationException();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic JsonValue next() {\r\n\t\t\t\t\tif (refArr == arr) {\r\n\t\t\t\t\t\treturn it.next();\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthrow new ConcurrentModificationException();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic boolean hasPrevious() {\r\n\t\t\t\t\tif (refArr == arr) {\r\n\t\t\t\t\t\treturn it.hasPrevious();\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthrow new ConcurrentModificationException();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic JsonValue previous() {\r\n\t\t\t\t\tif (refArr == arr) {\r\n\t\t\t\t\t\treturn it.previous();\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthrow new ConcurrentModificationException();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic int nextIndex() {\r\n\t\t\t\t\tif (refArr == arr) {\r\n\t\t\t\t\t\treturn it.nextIndex();\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthrow new ConcurrentModificationException();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic int previousIndex() {\r\n\t\t\t\t\tif (refArr == arr) {\r\n\t\t\t\t\t\treturn it.previousIndex();\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthrow new ConcurrentModificationException();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic void remove() {\r\n\t\t\t\t\tit.remove(); // will throw exception\r\n\t\t\t\t}\r\n\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic void set(JsonValue e) {\r\n\t\t\t\t\tit.set(e); // will throw exception\r\n\t\t\t\t}\r\n\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic void add(JsonValue e) {\r\n\t\t\t\t\tit.add(e); // will throw exception\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic List<JsonValue> subList(int fromIndex, int toIndex) {\r\n\t\t\treturn arr.subList(fromIndex, toIndex);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic int hashCode() {\r\n\t\t\treturn arr != null ? arr.hashCode() : 0;\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t    public boolean equals(Object obj) {\r\n\t\t\tif (obj == null) {\r\n\t\t\t\treturn this.arr == null;\r\n\t\t\t} else if (obj instanceof JsonArrayProxy) {\r\n\t\t\t\treturn this.arr.equals(((JsonArrayProxy) obj).arr);\r\n\t\t\t}\r\n\t\t\treturn arr.equals(obj);\r\n\t    }\r\n\r\n\t\t@Override\r\n\t    public String toString() {\r\n\t\t\treturn arr != null ? arr.toString() : null;\r\n\t    }\r\n    }\r\n\r\n    private static class JsonObjectProxy implements JsonObject {\r\n\r\n    \tprivate JsonObject obj;\r\n\r\n    \tJsonObjectProxy(JsonObject obj) {\r\n    \t\tthis.obj = obj;\r\n    \t}\r\n\r\n\t\t@Override\r\n\t\tpublic JsonArray getJsonArray(String name) {\r\n\t\t\treturn obj.getJsonArray(name);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic JsonObject getJsonObject(String name) {\r\n\t\t\treturn obj.getJsonObject(name);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic JsonNumber getJsonNumber(String name) {\r\n\t\t\treturn obj.getJsonNumber(name);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic JsonString getJsonString(String name) {\r\n\t\t\treturn obj.getJsonString(name);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic String getString(String name) {\r\n\t\t\treturn obj.getString(name);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic String getString(String name, String defaultValue) {\r\n\t\t\treturn obj.getString(name, defaultValue);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic int getInt(String name) {\r\n\t\t\treturn obj.getInt(name);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic int getInt(String name, int defaultValue) {\r\n\t\t\treturn obj.getInt(name, defaultValue);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean getBoolean(String name) {\r\n\t\t\treturn obj.getBoolean(name);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean getBoolean(String name, boolean defaultValue) {\r\n\t\t\treturn obj.getBoolean(name, defaultValue);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean isNull(String name) {\r\n\t\t\treturn obj.isNull(name);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic ValueType getValueType() {\r\n\t\t\treturn obj.getValueType();\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic int size() {\r\n\t\t\treturn obj.size();\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean isEmpty() {\r\n\t\t\treturn obj.isEmpty();\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean containsKey(Object key) {\r\n\t\t\treturn obj.containsKey(key);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic boolean containsValue(Object value) {\r\n\t\t\treturn obj.containsValue(value);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic JsonValue get(Object key) {\r\n\t\t\treturn obj.get(key);\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic JsonValue put(String key, JsonValue value) {\r\n\t\t\tJsonValue oldValue = obj.get(key);\r\n\t\t\tobj = jsonBuilderFactory.createObjectBuilder(obj).add(key, value).build();\r\n\t\t\treturn oldValue;\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic JsonValue remove(Object key) {\r\n\t\t\tJsonValue oldValue = obj.get(key);\r\n\t\t\tif (oldValue != null) {\r\n\t\t\t\tobj = jsonBuilderFactory.createObjectBuilder(obj).remove(key.toString()).build();\r\n\t\t\t\treturn oldValue;\r\n\t\t\t} else {\r\n\t\t\t\treturn null;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic void putAll(Map<? extends String, ? extends JsonValue> m) {\r\n\t\t\tif (m.isEmpty()) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tJsonObjectBuilder builder = jsonBuilderFactory.createObjectBuilder(obj);\r\n\t\t\tfor (Map.Entry<? extends String, ? extends JsonValue> e : m.entrySet()) {\r\n\t\t\t\tbuilder.add(e.getKey(), e.getValue());\r\n\t\t\t}\r\n\t\t\tobj = builder.build();\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic void clear() {\r\n\t\t\tobj = jsonBuilderFactory.createObjectBuilder().build();\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic Set<String> keySet() {\r\n\t\t\treturn obj.keySet();\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic Collection<JsonValue> values() {\r\n\t\t\treturn obj.values();\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic Set<Map.Entry<String, JsonValue>> entrySet() {\r\n\t\t\treturn new AbstractSet<Map.Entry<String,JsonValue>>() {\r\n\r\n\t\t\t\tfinal JsonObject refObj = obj;\r\n\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic Iterator<Map.Entry<String, JsonValue>> iterator() {\r\n\t\t\t\t\tif (refObj != obj) {\r\n\t\t\t\t\t\tthrow new ConcurrentModificationException();\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn new Iterator<Map.Entry<String, JsonValue>>() {\r\n\r\n\t\t\t\t\t\tfinal Iterator<Map.Entry<String, JsonValue>> it = obj.entrySet().iterator();\r\n\r\n\t\t\t\t\t\t@Override\r\n\t\t\t\t\t\tpublic boolean hasNext() {\r\n\t\t\t\t\t\t\tif (refObj == obj) {\r\n\t\t\t\t\t\t\t\treturn it.hasNext();\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tthrow new ConcurrentModificationException();\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t@Override\r\n\t\t\t\t\t\tpublic Map.Entry<String, JsonValue> next() {\r\n\t\t\t\t\t\t\tif (refObj == obj) {\r\n\t\t\t\t\t\t\t\treturn it.next();\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tthrow new ConcurrentModificationException();\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t};\r\n\t\t\t\t}\r\n\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic int size() {\r\n\t\t\t\t\tif (refObj == obj) {\r\n\t\t\t\t\t\treturn obj.size();\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthrow new ConcurrentModificationException();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t\tpublic int hashCode() {\r\n\t\t\treturn obj != null ? obj.hashCode() : 0;\r\n\t\t}\r\n\r\n\t\t@Override\r\n\t    public boolean equals(Object obj) {\r\n\t\t\tif (obj == null) {\r\n\t\t\t\treturn this.obj == null;\r\n\t\t\t} else if (obj instanceof JsonObjectProxy) {\r\n\t\t\t\treturn this.obj.equals(((JsonObjectProxy) obj).obj);\r\n\t\t\t}\r\n\t\t\treturn this.obj.equals(obj);\r\n\t    }\r\n\r\n\t\t@Override\r\n\t    public String toString() {\r\n\t\t\treturn obj != null ? obj.toString() : null;\r\n\t    }\r\n    }\r\n}\r\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/json/JettisonProvider.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.json;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.NoSuchElementException;\n\nimport org.codehaus.jettison.json.JSONException;\nimport com.jayway.jsonpath.InvalidJsonException;\n\npublic class JettisonProvider extends AbstractJsonProvider\n{\n\tprivate static Object jettisonUnwrap(Object obj)\n\t{\n\t\tif( obj!=null && obj.equals(org.codehaus.jettison.json.JSONObject.NULL) )\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t\treturn obj;\n\t}\n\t\n\tprivate static Object jettisonWrap(Object obj)\n\t{\n\t\tif( obj==null )\n\t\t{\n\t\t\treturn org.codehaus.jettison.json.JSONObject.NULL;\n\t\t}\n\t\treturn obj;\n\t}\n\t\n\t/** JSON Object implementation */\n\tprivate static class JettisonTokener extends org.codehaus.jettison.json.JSONTokener\n\t{\n\t\tpublic JettisonTokener(String s)\n\t\t{\n\t\t\tsuper(s);\n\t\t}\n\t\t@Override\n\t\tprotected JettisonObject newJSONObject() throws JSONException \n\t\t{\n\t\t\treturn new JettisonObject(this);\n\t\t}\n\t\t@Override\n\t\tprotected JettisonArray newJSONArray() throws JSONException \n\t\t{\n\t\t\treturn new JettisonArray(this);\n\t\t}\n\t}\n\t\n\t/** JSON Object implementation */\n\tprivate static class JettisonObject extends org.codehaus.jettison.json.JSONObject implements Iterable<Object>\n\t{\n\t\tprivate static final long serialVersionUID = 1L;\n\t\t\n\t\tprivate JettisonObject(JettisonTokener tokener) throws JSONException\n\t\t{\n\t\t\tsuper(tokener);\n\t\t}\n\t\t\n\t\tprivate JettisonObject()\n\t\t{\n\t\t\tsuper();\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic Iterator<Object> iterator() \n\t\t{\n\t\t\treturn new JettisonObjectIterator(this);\n\t\t}\n\t}\n\t/** JSON Array implementation */\n\tprivate static class JettisonArray extends org.codehaus.jettison.json.JSONArray implements Iterable<Object>\n\t{\n\t\tprivate static final long serialVersionUID = 2L;\n\n\t\tprivate JettisonArray(JettisonTokener tokener) throws JSONException\n\t\t{\n\t\t\tsuper(tokener);\n\t\t}\n\t\t\n\t\tprivate JettisonArray() \n\t\t{\n\t\t\tsuper();\n\t\t}\n\n\t\t@Override\n\t\tpublic Iterator<Object> iterator() \n\t\t{\n\t\t\treturn new JettisonArrayIterator(this);\n\t\t}\n\t}\n\t\n\tprivate static class JettisonArrayIterator implements Iterator<Object>\n\t{\n\t\tprivate final org.codehaus.jettison.json.JSONArray jsonArray;\n\t\tprivate int index = 0;\n\t\t\n\t\tprivate JettisonArrayIterator(org.codehaus.jettison.json.JSONArray jsonArray)\n\t\t{\n\t\t\tthis.jsonArray = jsonArray;\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic boolean hasNext() \n\t\t{\n\t\t\treturn index < jsonArray.length();\n\t\t}\n\n\t\t@Override\n\t\tpublic Object next() \n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\treturn jettisonUnwrap(jsonArray.get(index++));\n\t\t\t}\n\t\t\tcatch( org.codehaus.jettison.json.JSONException jsonException )\n\t\t\t{\n\t\t\t\tthrow new NoSuchElementException(jsonException.toString());\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void remove() \n\t\t{\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\t\t\n\t}\n\t\n\tprivate static class JettisonObjectIterator implements Iterator<Object>\n\t{\n\t\tprivate final org.codehaus.jettison.json.JSONObject jsonObject;\n\t\tprivate final Iterator<?> jsonKeysIt;\n\t\t\n\t\t\n\t\tprivate JettisonObjectIterator(org.codehaus.jettison.json.JSONObject jsonObject)\n\t\t{\n\t\t\tthis.jsonObject = jsonObject;\n\t\t\tthis.jsonKeysIt = jsonObject.keys();\n\t\t}\n\t\t\n\t\t@Override\n\t\tpublic boolean hasNext() \n\t\t{\n\t\t\treturn jsonKeysIt.hasNext();\n\t\t}\n\n\t\t@Override\n\t\tpublic Object next() \n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\treturn jettisonUnwrap(jsonObject.get(String.valueOf(jsonKeysIt.next())));\n\t\t\t}\n\t\t\tcatch( org.codehaus.jettison.json.JSONException jsonException )\n\t\t\t{\n\t\t\t\tthrow new NoSuchElementException(jsonException.toString());\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void remove() \n\t\t{\n\t\t\tjsonKeysIt.remove();\n\t\t}\n\t\t\n\t}\n\t\n\tprivate Object parse(JettisonTokener JsonTokener)\n\t{\n\t\ttry\n\t\t{\n\t\t\tchar nextChar = JsonTokener.nextClean();\n\t\t\tJsonTokener.back();\n\t\t\tif (nextChar == '{') \n\t\t\t{\n\t\t\t\treturn new JettisonObject(JsonTokener);\n\t\t\t}\n\t\t\tif (nextChar == '[') \n\t\t\t{\n\t\t\t\treturn new JettisonArray(JsonTokener);\n\t\t\t}\n\t\t\tthrow new JSONException(\"Invalid JSON\");\n\t\t}\n\t\tcatch( org.codehaus.jettison.json.JSONException jsonException )\n\t\t{\n\t\t\tthrow new IllegalStateException(jsonException);\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic Object parse(String json) throws InvalidJsonException \n\t{\n\t\treturn parse(new JettisonTokener(json));\n\t}\n\t\n\t@Override\n\tpublic Object parse(InputStream jsonStream, String charset) throws InvalidJsonException\n\t{\n\t\ttry\n\t\t{\n\t\t\tByteArrayOutputStream stream = new ByteArrayOutputStream();\n\t\t\tbyte[] buffer = new byte[1024];\n\t\t\tint size;\n\t\t\twhile( (size=jsonStream.read(buffer))>0 )\n\t\t\t{\n\t\t\t\tstream.write(buffer, 0, size);\n\t\t\t}\n\t\t\treturn parse(new JettisonTokener(new String(stream.toByteArray(), charset)));\n\t\t}\n\t\tcatch( IOException ioe )\n\t\t{\n\t\t\tthrow new InvalidJsonException(ioe);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String toJson(Object obj) \n\t{\n\t\ttry\n\t\t{\n\t\t\tif( obj instanceof org.codehaus.jettison.json.JSONArray )\n\t\t\t{\n\t\t\t\treturn ((org.codehaus.jettison.json.JSONArray)obj).toString(2);\n\t\t\t}\n\t\t\tif( obj instanceof org.codehaus.jettison.json.JSONObject )\n\t\t\t{\n\t\t\t\treturn ((org.codehaus.jettison.json.JSONObject)obj).toString(2);\n\t\t\t}\n\t\t\treturn String.valueOf(obj);\n\t\t\t//return \"\\\"\" + String.valueOf(obj).replaceAll(\"\\\"\", \"\\\\\\\"\") + \"\\\"\";\n\t\t}\n\t\tcatch( org.codehaus.jettison.json.JSONException jsonException )\n\t\t{\n\t\t\tthrow new IllegalStateException(jsonException);\n\t\t}\n\t}\n\n\t@Override\n\tpublic Object createMap() \n\t{\n\t\treturn new JettisonObject();\n\t}\n\n\t@Override\n\tpublic Iterable<?> createArray() \n\t{\n\t\treturn new JettisonArray();\n\t}\n\t\n\t@Override \n\tpublic Object unwrap(Object obj)\n\t{\n\t\treturn jettisonUnwrap(obj);\n\t}\n\t\n\t@Override\n\tpublic boolean isArray(Object obj) \n\t{\n\t\treturn obj instanceof org.codehaus.jettison.json.JSONArray;\n\t}\n\t\n\t@Override\n\tpublic boolean isMap(Object obj) \n\t{\n\t\treturn obj instanceof org.codehaus.jettison.json.JSONObject;\n\t}\n\n\t@Override\n\tpublic int length(Object obj) \n\t{\n\t\tif( obj instanceof org.codehaus.jettison.json.JSONArray )\n\t\t{\n\t\t\treturn ((org.codehaus.jettison.json.JSONArray) obj).length();\n\t\t}\n\t\tif( obj instanceof org.codehaus.jettison.json.JSONObject )\n\t\t{\n\t\t\treturn ((org.codehaus.jettison.json.JSONObject)obj).length();\n\t\t}\n\t\tif( obj instanceof String )\n\t\t{\n\t\t\treturn ((String)obj).length();\n\t\t}\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic Iterable<?> toIterable(final Object obj) \n\t{\n\t\treturn new Iterable<Object>()\n\t\t{\n\t\t\t@Override\n\t\t\tpublic Iterator<Object> iterator() \n\t\t\t{\n\t\t\t\tif( obj instanceof org.codehaus.jettison.json.JSONArray )\n\t\t\t\t{\n\t\t\t\t\treturn new JettisonArrayIterator((org.codehaus.jettison.json.JSONArray)obj);\n\t\t\t\t}\n\t\t\t\tif( obj instanceof org.codehaus.jettison.json.JSONObject )\n\t\t\t\t{\n\t\t\t\t\treturn new JettisonObjectIterator((org.codehaus.jettison.json.JSONObject)obj);\n\t\t\t\t}\n\t\t\t\treturn Collections.emptyList().iterator();\n\t\t\t}\n\t\t};\n\n\t}\n\n\tpublic Collection<String> getPropertyKeys(Object obj) \n\t{\n\t\tList<String> keys = new ArrayList<String>(length(obj));\n\t\t\n\t\tif( obj instanceof org.codehaus.jettison.json.JSONArray )\n\t\t{\n\t\t\tfor (int i = 0; i < length(obj); i++)\n\t\t\t{\n\t\t\t\tkeys.add(String.valueOf(i));\n\t\t\t}\n\t\t}\n\t\tif( obj instanceof org.codehaus.jettison.json.JSONObject )\n\t\t{\n\t\t\tIterator<?> keysIt = ((org.codehaus.jettison.json.JSONObject)obj).keys();\n\t\t\twhile (keysIt.hasNext())\n\t\t\t{\n\t\t\t\tkeys.add(String.valueOf(keysIt.next()));\n\t\t\t}\n\t\t}\n\t\treturn keys;\n\t}\n\t\n\t\n\t@Override\n\tpublic Object getArrayIndex(Object obj, int index)\n\t{\n\t\treturn jettisonUnwrap(((org.codehaus.jettison.json.JSONArray)obj).opt(index));\n\t}\n\t\n\t@Override public void setArrayIndex(Object array, int index, Object value)\n\t{\n\t\tif( !isArray(array) )\n\t\t{\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\t\t\n\t\ttry\n\t\t{\n\t\t\t((org.codehaus.jettison.json.JSONArray)array).put(index, jettisonWrap(value));\n\t\t}\n\t\tcatch( org.codehaus.jettison.json.JSONException jsonException )\n\t\t{\n\t\t\tthrow new IllegalArgumentException(jsonException);\n\t\t}\n\t}\n\t\n\t@Override \n\tpublic Object getMapValue(Object obj, String key)\n\t{\n\t\tObject value = ((org.codehaus.jettison.json.JSONObject)obj).opt(key);\n\t\tif( value==null )\n\t\t{\n\t\t\treturn com.jayway.jsonpath.spi.json.JsonProvider.UNDEFINED;\n\t\t}\n\t\treturn jettisonUnwrap(value);\n\t}\n\t\n\t@Override\n\tpublic void setProperty(Object obj, Object key, Object value) \n\t{\n\t\ttry\n\t\t{\n\t\t\tif( obj instanceof org.codehaus.jettison.json.JSONArray )\n\t\t\t{\n\t\t\t\tint index = key instanceof Integer? (Integer) key : Integer.parseInt(key.toString());\n\t\t\t\t((org.codehaus.jettison.json.JSONArray)obj).put(index, jettisonWrap(value));\n\t\t\t}\n\t\t\tif( obj instanceof org.codehaus.jettison.json.JSONObject )\n\t\t\t{\n\t\t\t\t((org.codehaus.jettison.json.JSONObject)obj).put(String.valueOf(key), jettisonWrap(value));\n\t\t\t}\n\t\t}\n\t\tcatch( org.codehaus.jettison.json.JSONException jsonException )\n\t\t{\n\t\t\tthrow new IllegalStateException(jsonException);\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic void removeProperty(Object obj, Object key)\n\t{\n\t\ttry\n\t\t{\n\t\t\tif( obj instanceof org.codehaus.jettison.json.JSONArray )\n\t\t\t{\n\t\t\t\tint index = key instanceof Integer? (Integer) key : Integer.parseInt(key.toString());\n\t\t\t\tif( index<length(obj) )\n\t\t\t\t{\n\t\t\t\t\tObject temp = new Object(); // Need FIX: JSONArray.remove(int)\n\t\t\t\t\t((org.codehaus.jettison.json.JSONArray)obj).put(index, temp);\n\t\t\t\t\t((org.codehaus.jettison.json.JSONArray)obj).remove(temp);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif( obj instanceof org.codehaus.jettison.json.JSONObject )\n\t\t\t{\n\t\t\t\t((org.codehaus.jettison.json.JSONObject)obj).remove(String.valueOf(key));\n\t\t\t}\n\t\t}\n\t\tcatch( org.codehaus.jettison.json.JSONException jsonException )\n\t\t{\n\t\t\tthrow new IllegalStateException(jsonException);\n\t\t}\n\t}\n\t\n}"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonOrgJsonProvider.java",
    "content": "package com.jayway.jsonpath.spi.json;\n\nimport org.json.JSONObject;\nimport com.jayway.jsonpath.InvalidJsonException;\nimport com.jayway.jsonpath.JsonPathException;\nimport org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\nimport org.json.JSONTokener;\n\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.UnsupportedEncodingException;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Objects;\n\npublic class JsonOrgJsonProvider extends AbstractJsonProvider {\n\n    @Override\n    public Object parse(String json) throws InvalidJsonException {\n        try {\n            return new JSONTokener(json).nextValue();\n        } catch (JSONException e) {\n            throw new InvalidJsonException(e);\n        }\n    }\n\n    @Override\n    public Object parse(InputStream jsonStream, String charset) throws InvalidJsonException {\n\n        try {\n            return new JSONTokener(new InputStreamReader(jsonStream, charset)).nextValue();\n        } catch (UnsupportedEncodingException e) {\n            throw new JsonPathException(e);\n        } catch (JSONException e) {\n            throw new InvalidJsonException(e);\n        }\n    }\n\n    @Override\n    public Object unwrap(Object obj) {\n        if(obj == JSONObject.NULL){\n            return null;\n        }\n        return obj;\n    }\n\n    @Override\n    public String toJson(Object obj) {\n        return obj.toString();\n    }\n\n    @Override\n    public Object createArray() {\n        return new JSONArray();\n    }\n\n    @Override\n    public Object createMap() {\n        return new JSONObject();\n    }\n\n    @Override\n    public boolean isArray(Object obj) {\n        return (obj instanceof JSONArray || obj instanceof List);\n    }\n\n    @Override\n    public Object getArrayIndex(Object obj, int idx) {\n        try {\n            return toJsonArray(obj).get(idx);\n        } catch (JSONException e) {\n            throw new JsonPathException(e);\n        }\n    }\n\n    @Override\n    public void setArrayIndex(Object array, int index, Object newValue) {\n        try {\n            if (!isArray(array)) {\n                throw new UnsupportedOperationException();\n            } else {\n                toJsonArray(array).put(index, createJsonElement(newValue));\n            }\n        } catch (JSONException e) {\n            throw new JsonPathException(e);\n        }\n    }\n\n    @Override\n    public Object getMapValue(Object obj, String key) {\n        try {\n            JSONObject jsonObject = toJsonObject(obj);\n            Object o = jsonObject.opt(key);\n            if (o == null) {\n                return UNDEFINED;\n            } else {\n                return unwrap(o);\n            }\n        } catch (JSONException e) {\n            throw new JsonPathException(e);\n        }\n    }\n\n    @Override\n    public void setProperty(Object obj, Object key, Object value) {\n        try {\n            if (isMap(obj))\n                toJsonObject(obj).put(key.toString(), createJsonElement(value));\n            else {\n                JSONArray array = toJsonArray(obj);\n                int index;\n                if (key != null) {\n                    index = key instanceof Integer ? (Integer) key : Integer.parseInt(key.toString());\n                } else {\n                    index = array.length();\n                }\n                if (index == array.length()) {\n                    array.put(createJsonElement(value));\n                } else {\n                    array.put(index, createJsonElement(value));\n                }\n            }\n        } catch (JSONException e) {\n            throw new JsonPathException(e);\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public void removeProperty(Object obj, Object key) {\n        if (isMap(obj))\n            toJsonObject(obj).remove(key.toString());\n        else {\n            JSONArray array = toJsonArray(obj);\n            int index = key instanceof Integer ? (Integer) key : Integer.parseInt(key.toString());\n            array.remove(index);\n        }\n    }\n\n    @Override\n    public boolean isMap(Object obj) {\n        return (obj instanceof JSONObject);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public Collection<String> getPropertyKeys(Object obj) {\n        JSONObject jsonObject = toJsonObject(obj);\n        try {\n            if(Objects.isNull(jsonObject.names()))\n                return new ArrayList<>();\n            return jsonObject.keySet();\n        } catch (JSONException e) {\n            throw new JsonPathException(e);\n        }\n    }\n\n    @Override\n    public int length(Object obj) {\n        if (isArray(obj)) {\n            return toJsonArray(obj).length();\n        } else if (isMap(obj)) {\n            return toJsonObject(obj).length();\n        } else {\n            if (obj instanceof String) {\n                return ((String) obj).length();\n            }\n        }\n        throw new JsonPathException(\"length operation can not applied to \" + (obj != null ? obj.getClass().getName()\n                : \"null\"));\n    }\n\n    @Override\n    public Iterable<?> toIterable(Object obj) {\n        try {\n            if (isArray(obj)) {\n                JSONArray arr = toJsonArray(obj);\n                List<Object> values = new ArrayList<Object>(arr.length());\n                for (int i = 0; i < arr.length(); i++) {\n                    values.add(unwrap(arr.get(i)));\n                }\n                return values;\n            } else {\n                JSONObject jsonObject = toJsonObject(obj);\n                List<Object> values = new ArrayList<Object>();\n\n                for (int i = 0; i < jsonObject.names().length(); i++) {\n                    String key = (String) jsonObject.names().get(i);\n                    Object val = jsonObject.get(key);\n                    values.add(unwrap(val));\n\n                }\n\n                return values;\n            }\n        } catch (JSONException e) {\n            throw new JsonPathException(e);\n        }\n    }\n\n    private Object createJsonElement(Object o) {\n        return o;\n    }\n\n    private JSONArray toJsonArray(Object o) {\n        return (JSONArray) o;\n    }\n\n    private JSONObject toJsonObject(Object o) {\n        return (JSONObject) o;\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.json;\n\nimport com.jayway.jsonpath.InvalidJsonException;\nimport java.io.InputStream;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Collection;\n\n\npublic interface JsonProvider {\n\n    static final Object UNDEFINED = new Object();\n\n    /**\n     * Parse the given json string\n     * @param json json string to parse\n     * @return Object representation of json\n     * @throws InvalidJsonException\n     */\n    Object parse(String json) throws InvalidJsonException;\n\n    /**\n     * Parse the given json bytes in UTF-8 encoding\n     * @param json json bytes to parse\n     * @return Object representation of json\n     * @throws InvalidJsonException\n     */\n    default Object parse(byte[] json) throws InvalidJsonException {\n        return parse(new String(json, StandardCharsets.UTF_8));\n    }\n    /**\n     * Parse the given json string\n     * @param jsonStream input stream to parse\n     * @param charset charset to use\n     * @return Object representation of json\n     * @throws InvalidJsonException\n     */\n    Object parse(InputStream jsonStream, String charset) throws InvalidJsonException;\n\n    /**\n     * Convert given json object to a json string\n     * @param obj object to transform\n     * @return json representation of object\n     */\n    String toJson(Object obj);\n\n    /**\n     * Creates a provider specific json array\n     * @return new array\n     */\n    Object createArray();\n\n    /**\n     * Creates a provider specific json object\n     * @return new object\n     */\n    Object createMap();\n\n    /**\n     * checks if object is an array\n     *\n     * @param obj object to check\n     * @return true if obj is an array\n     */\n    boolean isArray(Object obj);\n\n    /**\n     * Get the length of an json array, json object or a json string\n     *\n     * @param obj an array or object or a string\n     * @return the number of entries in the array or object\n     */\n    int length(Object obj);\n\n    /**\n     * Converts given array to an {@link Iterable}\n     *\n     * @param obj an array\n     * @return an Iterable that iterates over the entries of an array\n     */\n    Iterable<?> toIterable(Object obj);\n\n\n    /**\n     * Returns the keys from the given object\n     *\n     * @param obj an object\n     * @return the keys for an object\n     */\n    Collection<String> getPropertyKeys(Object obj);\n\n    /**\n     * Extracts a value from an array anw unwraps provider specific data type\n     *\n     * @param obj an array\n     * @param idx index\n     * @return the entry at the given index\n     */\n    Object getArrayIndex(Object obj, int idx);\n\n    /**\n     * Extracts a value from an array\n     *\n     * @param obj an array\n     * @param idx index\n     * @param unwrap should provider specific data type be unwrapped\n     * @return the entry at the given index\n     */\n    @Deprecated\n    Object getArrayIndex(Object obj, int idx, boolean unwrap);\n\n    /**\n     * Sets a value in an array. If the array is too small, the provider is supposed to enlarge it.\n     *\n     * @param array an array\n     * @param idx index\n     * @param newValue the new value\n     */\n    void setArrayIndex(Object array, int idx, Object newValue);\n\n    /**\n     * Extracts a value from an map\n     *\n     * @param obj a map\n     * @param key property key\n     * @return the map entry or {@link com.jayway.jsonpath.spi.json.JsonProvider#UNDEFINED} for missing properties\n     */\n    Object getMapValue(Object obj, String key);\n\n    /**\n     * Sets a value in an object\n     *\n     * @param obj   an object\n     * @param key   a String key\n     * @param value the value to set\n     */\n    void setProperty(Object obj, Object key, Object value);\n\n    /**\n     * Removes a value in an object or array\n     *\n     * @param obj   an array or an object\n     * @param key   a String key or a numerical index to remove\n     */\n    void removeProperty(Object obj, Object key);\n\n    /**\n     * checks if object is a map (i.e. no array)\n     *\n     * @param obj object to check\n     * @return true if the object is a map\n     */\n    boolean isMap(Object obj);\n\n    /**\n     * Extracts a value from a wrapper object. For JSON providers that to not wrap\n     * values, this will usually be the object itself.\n     *\n     * @param obj a value holder object\n     * @return the unwrapped value.\n     */\n    Object unwrap(Object obj);\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonSmartJsonProvider.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.json;\n\nimport com.jayway.jsonpath.InvalidJsonException;\nimport com.jayway.jsonpath.JsonPathException;\nimport net.minidev.json.JSONArray;\nimport net.minidev.json.JSONObject;\nimport net.minidev.json.JSONStyle;\nimport net.minidev.json.JSONValue;\nimport net.minidev.json.parser.JSONParser;\nimport net.minidev.json.parser.ParseException;\nimport net.minidev.json.writer.JsonReaderI;\n\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.UnsupportedEncodingException;\nimport java.util.List;\nimport java.util.Map;\n\npublic class JsonSmartJsonProvider extends AbstractJsonProvider {\n\n    private final int parseMode;\n    private final JsonReaderI<?> mapper;\n\n    public JsonSmartJsonProvider() {\n        this(JSONParser.MODE_PERMISSIVE, JSONValue.defaultReader.DEFAULT_ORDERED);\n    }\n\n    public JsonSmartJsonProvider(int parseMode){\n        this(parseMode, JSONValue.defaultReader.DEFAULT_ORDERED);\n\n    }\n\n    public JsonSmartJsonProvider(int parseMode, JsonReaderI<?> mapper){\n        this.parseMode = parseMode;\n        this.mapper = mapper;\n    }\n\n    public Object createArray() {\n        return mapper.createArray();\n    }\n\n    public Object createMap() {\n        return mapper.createObject();\n    }\n\n    public Object parse(String json) {\n        try {\n            return createParser().parse(json, mapper);\n        } catch (ParseException e) {\n            throw new InvalidJsonException(e);\n        }\n    }\n\n    @Override\n    public Object parse(InputStream jsonStream, String charset) throws InvalidJsonException {\n        try {\n            return createParser().parse(new InputStreamReader(jsonStream, charset), mapper);\n        } catch (ParseException e) {\n            throw new InvalidJsonException(e);\n        } catch (UnsupportedEncodingException e) {\n            throw new JsonPathException(e);\n        }\n    }\n\n    @Override\n    public String toJson(Object obj) {\n\n        if (obj instanceof Map) {\n            return JSONObject.toJSONString((Map<String, ?>) obj, JSONStyle.LT_COMPRESS);\n        } else if (obj instanceof List) {\n            return JSONArray.toJSONString((List<?>) obj, JSONStyle.LT_COMPRESS);\n        } else if (obj instanceof Number ||  obj instanceof Boolean){\n            return JSONValue.toJSONString(obj);\n        } else {\n            throw new UnsupportedOperationException(obj.getClass().getName() + \" can not be converted to JSON\");\n        }\n    }\n\n    private JSONParser createParser() {\n        return new JSONParser(parseMode);\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/json/TapestryJsonProvider.java",
    "content": "package com.jayway.jsonpath.spi.json;\n\nimport com.jayway.jsonpath.InvalidJsonException;\nimport org.apache.tapestry5.json.JSONArray;\nimport org.apache.tapestry5.json.JSONCollection;\nimport org.apache.tapestry5.json.JSONObject;\n\nimport java.io.InputStream;\nimport java.util.Collection;\nimport java.util.Scanner;\n\npublic class TapestryJsonProvider extends AbstractJsonProvider {\n\n  public static final TapestryJsonProvider INSTANCE = new TapestryJsonProvider();\n\n  @Override\n  public Object parse(final String json) throws InvalidJsonException {\n    return new JSONObject(json);\n  }\n\n  @Override\n  public Object parse(final InputStream jsonStream, final String charset) throws InvalidJsonException {\n    Scanner sc = null;\n    try {\n      sc = new Scanner(jsonStream, charset);\n      return parse(sc.useDelimiter(\"\\\\A\").next());\n    } finally {\n      if (sc != null) {\n        sc.close();\n      }\n    }\n  }\n\n  @Override\n  public String toJson(final Object obj) {\n    return ((JSONCollection) obj).toCompactString();\n  }\n\n  @Override\n  public Object createArray() {\n    return new JSONArray();\n  }\n\n  @Override\n  public Object createMap() {\n    return new JSONObject();\n  }\n\n  @Override\n  public void setProperty(final Object obj, final Object key, final Object value) {\n    Object v = value == null ? JSONObject.NULL : value;\n    if (isMap(obj)) {\n      ((JSONObject) obj).put(key.toString(), v);\n    }\n  }\n\n  @Override\n  public boolean isMap(final Object obj) {\n    return obj instanceof JSONObject;\n  }\n\n  @Override\n  public Object getArrayIndex(final Object obj, final int idx) {\n    return ((JSONArray) obj).get(idx);\n  }\n\n  @Override\n  public Collection<String> getPropertyKeys(final Object obj) {\n    return ((JSONObject) obj).keys();\n  }\n\n  @Override\n  public Object getMapValue(final Object obj, final String key) {\n    JSONObject json = (JSONObject) obj;\n    if (!json.has(key)) {\n      return UNDEFINED;\n    }\n    return json.get(key);\n  }\n\n  @Override\n  public int length(final Object obj) {\n    if (obj instanceof JSONArray) {\n      return ((JSONArray) obj).length();\n    } else if (obj instanceof JSONObject) {\n      return ((JSONObject) obj).length();\n    } else {\n      throw new IllegalArgumentException(\"Cannot determine length of \" + obj + \", unsupported type.\");\n    }\n  }\n\n  @Override\n  public boolean isArray(final Object obj) {\n    return (obj instanceof JSONArray);\n  }\n\n  @Override\n  public void setArrayIndex(final Object array, final int index, final Object newValue) {\n    Object v = newValue == null ? JSONObject.NULL : newValue;\n    JSONArray list = (JSONArray) array;\n    list.put(index, v);\n  }\n\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/mapper/GsonMappingProvider.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.mapper;\n\nimport com.google.gson.Gson;\nimport com.google.gson.JsonElement;\nimport com.google.gson.reflect.TypeToken;\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.JsonPathException;\nimport com.jayway.jsonpath.TypeRef;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.concurrent.Callable;\n\npublic class GsonMappingProvider implements MappingProvider {\n\n    private static final Logger logger = LoggerFactory.getLogger(GsonMappingProvider.class);\n\n    private final Callable<Gson> factory;\n\n    public GsonMappingProvider(final Gson gson) {\n        this(new Callable<Gson>() {\n            @Override\n            public Gson call() {\n                return gson;\n            }\n        });\n    }\n\n    public GsonMappingProvider(Callable<Gson> factory) {\n        this.factory = factory;\n    }\n\n    public GsonMappingProvider() {\n        super();\n        try {\n            Class.forName(\"com.google.gson.Gson\");\n            this.factory = new Callable<Gson>() {\n                @Override\n                public Gson call() {\n                    return new Gson();\n                }\n            };\n        } catch (ClassNotFoundException e) {\n            logger.error(\"Gson not found on class path. No converters configured.\");\n            throw new JsonPathException(\"Gson not found on path\", e);\n        }\n    }\n\n    @Override\n    public <T> T map(Object source, Class<T> targetType, Configuration configuration) {\n        if(source == null){\n            return null;\n        }\n        try {\n            return factory.call().getAdapter(targetType).fromJsonTree((JsonElement) source);\n        } catch (Exception e){\n            throw new MappingException(e);\n        }\n    }\n\n    @Override\n    public <T> T map(Object source, TypeRef<T> targetType, Configuration configuration) {\n        if(source == null){\n            return null;\n        }\n        try {\n            return (T) factory.call().getAdapter(TypeToken.get(targetType.getType())).fromJsonTree((JsonElement) source);\n        } catch (Exception e){\n            throw new MappingException(e);\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/mapper/Jackson3MappingProvider.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.mapper;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.TypeRef;\nimport tools.jackson.databind.JavaType;\nimport tools.jackson.databind.ObjectMapper;\n\npublic class Jackson3MappingProvider implements MappingProvider {\n\n    private final ObjectMapper objectMapper;\n\n    public Jackson3MappingProvider() {\n        this(new ObjectMapper());\n    }\n\n    public Jackson3MappingProvider(ObjectMapper objectMapper) {\n        this.objectMapper = objectMapper;\n    }\n\n    @Override\n    public <T> T map(Object source, Class<T> targetType, Configuration configuration) {\n        if (source == null) {\n            return null;\n        }\n        try {\n            return objectMapper.convertValue(source, targetType);\n        } catch (Exception e) {\n            throw new MappingException(e);\n        }\n\n    }\n\n    @Override\n    public <T> T map(Object source, final TypeRef<T> targetType, Configuration configuration) {\n        if (source == null) {\n            return null;\n        }\n        JavaType type = objectMapper.getTypeFactory().constructType(targetType.getType());\n\n        try {\n            return (T) objectMapper.convertValue(source, type);\n        } catch (Exception e) {\n            throw new MappingException(e);\n        }\n\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/mapper/JacksonMappingProvider.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.mapper;\n\nimport com.fasterxml.jackson.databind.JavaType;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.TypeRef;\n\npublic class JacksonMappingProvider implements MappingProvider {\n\n    private final ObjectMapper objectMapper;\n\n    public JacksonMappingProvider() {\n        this(new ObjectMapper());\n    }\n\n    public JacksonMappingProvider(ObjectMapper objectMapper) {\n        this.objectMapper = objectMapper;\n    }\n\n\n    @Override\n    public <T> T map(Object source, Class<T> targetType, Configuration configuration) {\n        if(source == null){\n            return null;\n        }\n        try {\n            return objectMapper.convertValue(source, targetType);\n        } catch (Exception e) {\n            throw new MappingException(e);\n        }\n\n    }\n\n    @Override\n    public <T> T map(Object source, final TypeRef<T> targetType, Configuration configuration) {\n        if(source == null){\n            return null;\n        }\n        JavaType type = objectMapper.getTypeFactory().constructType(targetType.getType());\n\n        try {\n            return (T)objectMapper.convertValue(source, type);\n        } catch (Exception e) {\n            throw new MappingException(e);\n        }\n\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/mapper/JakartaMappingProvider.java",
    "content": "/*\r\n * Copyright 2011 the original author or authors.\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n *       http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\npackage com.jayway.jsonpath.spi.mapper;\r\n\r\nimport java.lang.reflect.Constructor;\r\nimport java.lang.reflect.GenericArrayType;\r\nimport java.lang.reflect.Method;\r\nimport java.lang.reflect.Modifier;\r\nimport java.lang.reflect.ParameterizedType;\r\nimport java.lang.reflect.Type;\r\nimport java.math.BigDecimal;\r\nimport java.math.BigInteger;\r\nimport java.util.ArrayDeque;\r\nimport java.util.Arrays;\r\nimport java.util.Collection;\r\nimport java.util.Deque;\r\nimport java.util.Iterator;\r\nimport java.util.List;\r\nimport java.util.Map;\r\nimport java.util.NoSuchElementException;\r\nimport java.util.Queue;\r\nimport java.util.Set;\r\n\r\nimport com.jayway.jsonpath.Configuration;\r\nimport com.jayway.jsonpath.TypeRef;\r\n\r\nimport jakarta.json.JsonArray;\r\nimport jakarta.json.JsonArrayBuilder;\r\nimport jakarta.json.JsonException;\r\nimport jakarta.json.JsonNumber;\r\nimport jakarta.json.JsonObject;\r\nimport jakarta.json.JsonObjectBuilder;\r\nimport jakarta.json.JsonString;\r\nimport jakarta.json.JsonStructure;\r\nimport jakarta.json.JsonValue;\r\nimport jakarta.json.bind.Jsonb;\r\nimport jakarta.json.bind.JsonbBuilder;\r\nimport jakarta.json.bind.JsonbConfig;\r\nimport jakarta.json.bind.JsonbException;\r\nimport jakarta.json.stream.JsonLocation;\r\nimport jakarta.json.stream.JsonParser;\r\n\r\npublic class JakartaMappingProvider implements MappingProvider {\r\n\r\n    private final Jsonb jsonb;\r\n    private Method jsonToClassMethod, jsonToTypeMethod;\r\n\r\n    public JakartaMappingProvider() {\r\n        this.jsonb = JsonbBuilder.create();\r\n        this.jsonToClassMethod = findMethod(jsonb.getClass(), \"fromJson\", JsonParser.class, Class.class);\r\n        this.jsonToTypeMethod = findMethod(jsonb.getClass(), \"fromJson\", JsonParser.class, Type.class);\r\n    }\r\n\r\n    public JakartaMappingProvider(JsonbConfig jsonbConfiguration) {\r\n        this.jsonb = JsonbBuilder.create(jsonbConfiguration);\r\n        this.jsonToClassMethod = findMethod(jsonb.getClass(), \"fromJson\", JsonParser.class, Class.class);\r\n        this.jsonToTypeMethod = findMethod(jsonb.getClass(), \"fromJson\", JsonParser.class, Type.class);\r\n    }\r\n\r\n    /**\r\n     * Maps supplied JSON source {@code Object} to a given target class or collection.\r\n     * This implementation ignores the JsonPath's {@link Configuration} argument.\r\n     */\r\n    @Override\r\n    public <T> T map(Object source, Class<T> targetType, Configuration configuration) {\r\n        @SuppressWarnings(\"unchecked\")\r\n        T result = (T) mapImpl(source, targetType);\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * Maps supplied JSON source {@code Object} to a given target type or collection.\r\n     * This implementation ignores the JsonPath's {@link Configuration} argument.\r\n     * <p>\r\n     * Method <em>may</em> produce a {@code ClassCastException} on an attempt to cast\r\n     * the result of JSON mapping operation to a requested target type, especially if\r\n     * a parameterized generic type is used.\r\n     */\r\n    @Override\r\n    public <T> T map(Object source, final TypeRef<T> targetType, Configuration configuration) {\r\n        @SuppressWarnings(\"unchecked\")\r\n        T result = (T) mapImpl(source, targetType.getType());\r\n        return result;\r\n    }\r\n\r\n    private Object mapImpl(Object source, final Type targetType) {\r\n        if (source == null || source == JsonValue.NULL) {\r\n            return null;\r\n        }\r\n        if (source == JsonValue.TRUE) {\r\n            if (Boolean.class.equals(targetType)) {\r\n                return Boolean.TRUE;\r\n            } else {\r\n                String className = targetType.toString();\r\n                throw new MappingException(\"JSON boolean (true) cannot be mapped to \" + className);\r\n            }\r\n        }\r\n        if (source == JsonValue.FALSE) {\r\n            if (Boolean.class.equals(targetType)) {\r\n                return Boolean.FALSE;\r\n            } else {\r\n                String className = targetType.toString();\r\n                throw new MappingException(\"JSON boolean (false) cannot be mapped to \" + className);\r\n            }\r\n        } else if (source instanceof JsonString) {\r\n            if (String.class.equals(targetType)) {\r\n                return ((JsonString) source).getChars();\r\n            } else {\r\n                String className = targetType.toString();\r\n                throw new MappingException(\"JSON string cannot be mapped to \" + className);\r\n            }\r\n        } else if (source instanceof JsonNumber) {\r\n            JsonNumber jsonNumber = (JsonNumber) source;\r\n            if (jsonNumber.isIntegral()) {\r\n                return mapIntegralJsonNumber(jsonNumber, getRawClass(targetType));\r\n            } else {\r\n                return mapDecimalJsonNumber(jsonNumber, getRawClass(targetType));\r\n            }\r\n        }\r\n        if (source instanceof JsonArrayBuilder) {\r\n            source = ((JsonArrayBuilder) source).build();\r\n        } else if (source instanceof JsonObjectBuilder) {\r\n            source = ((JsonObjectBuilder) source).build();\r\n        }\r\n        if (source instanceof Collection) {\r\n            // this covers both List<JsonValue> and JsonArray from JSON-P spec\r\n            Class<?> rawTargetType = getRawClass(targetType);\r\n            Type targetTypeArg = getFirstTypeArgument(targetType);\r\n            Collection<Object> result = newCollectionOfType(rawTargetType);\r\n            for (Object srcValue : (Collection<?>) source) {\r\n                if (srcValue instanceof JsonObject) {\r\n                    if (targetTypeArg != null) {\r\n                        result.add(mapImpl(srcValue, targetTypeArg));\r\n                    } else {\r\n                        result.add(srcValue);\r\n                    }\r\n                } else {\r\n                    result.add(unwrapJsonValue(srcValue));\r\n                }\r\n            }\r\n            return result;\r\n        } else if (source instanceof JsonObject) {\r\n            if (targetType instanceof Class) {\r\n                if (jsonToClassMethod != null) {\r\n                    try {\r\n                        JsonParser jsonParser = new JsonStructureToParserAdapter((JsonStructure) source);\r\n                        return jsonToClassMethod.invoke(jsonb, jsonParser, (Class<?>) targetType);\r\n                    } catch (Exception e){\r\n                        throw new MappingException(e);\r\n                    }\r\n                } else {\r\n                    try {\r\n                        // Fallback databinding approach for JSON-B API implementations without\r\n                        // explicit support for use of JsonParser in their public API. The approach\r\n                        // is essentially first to serialize given value into JSON, and then bind\r\n                        // it to data object of given class.\r\n                        String json = source.toString();\r\n                        return jsonb.fromJson(json, (Class<?>) targetType);\r\n                    } catch (JsonbException e){\r\n                        throw new MappingException(e);\r\n                    }\r\n                }\r\n            } else if (targetType instanceof ParameterizedType) {\r\n                if (jsonToTypeMethod != null) {\r\n                    try {\r\n                        JsonParser jsonParser = new JsonStructureToParserAdapter((JsonStructure) source);\r\n                        return jsonToTypeMethod.invoke(jsonb, jsonParser, (Type) targetType);\r\n                    } catch (Exception e){\r\n                        throw new MappingException(e);\r\n                    }\r\n                } else {\r\n                    try {\r\n                        // Fallback databinding approach for JSON-B API implementations without\r\n                        // explicit support for use of JsonParser in their public API. The approach\r\n                        // is essentially first to serialize given value into JSON, and then bind\r\n                        // the JSON string to data object of given type.\r\n                        String json = source.toString();\r\n                        return jsonb.fromJson(json, (Type) targetType);\r\n                    } catch (JsonbException e){\r\n                        throw new MappingException(e);\r\n                    }\r\n                }\r\n            } else {\r\n                throw new MappingException(\"JSON object cannot be databind to \" + targetType);\r\n            }\r\n        } else {\r\n            return source;\r\n        }\r\n    }\r\n\r\n    @SuppressWarnings(\"unchecked\")\r\n    private <T> T mapIntegralJsonNumber(JsonNumber jsonNumber, Class<?> targetType) {\r\n        if (targetType.isPrimitive()) {\r\n            if (int.class.equals(targetType)) {\r\n                return (T) Integer.valueOf(jsonNumber.intValueExact());\r\n            } else if (long.class.equals(targetType)) {\r\n                return (T) Long.valueOf(jsonNumber.longValueExact());\r\n            }\r\n        } else if (Integer.class.equals(targetType)) {\r\n            return (T) Integer.valueOf(jsonNumber.intValueExact());\r\n        } else if (Long.class.equals(targetType)) {\r\n            return (T) Long.valueOf(jsonNumber.longValueExact());\r\n        } else if (BigInteger.class.equals(targetType)) {\r\n            return (T) jsonNumber.bigIntegerValueExact();\r\n        } else if (BigDecimal.class.equals(targetType)) {\r\n            return (T) jsonNumber.bigDecimalValue();\r\n        }\r\n\r\n        String className = targetType.getSimpleName();\r\n        throw new MappingException(\"JSON integral number cannot be mapped to \" + className);\r\n    }\r\n\r\n    @SuppressWarnings(\"unchecked\")\r\n    private <T> T mapDecimalJsonNumber(JsonNumber jsonNumber, Class<?> targetType) {\r\n        if (targetType.isPrimitive()) {\r\n            if (float.class.equals(targetType)) {\r\n                return (T) new Float(jsonNumber.doubleValue());\r\n            } else if (double.class.equals(targetType)) {\r\n                return (T) Double.valueOf(jsonNumber.doubleValue());\r\n            }\r\n        } else if (Float.class.equals(targetType)) {\r\n            return (T) new Float(jsonNumber.doubleValue());\r\n        } else if (Double.class.equals(targetType)) {\r\n            return (T) Double.valueOf(jsonNumber.doubleValue());\r\n        } else if (BigDecimal.class.equals(targetType)) {\r\n            return (T) jsonNumber.bigDecimalValue();\r\n        }\r\n\r\n        String className = targetType.getSimpleName();\r\n        throw new MappingException(\"JSON decimal number cannot be mapped to \" + className);\r\n    }\r\n\r\n    private Object unwrapJsonValue(Object jsonValue) {\r\n        if (jsonValue == null) {\r\n            return null;\r\n        }\r\n        if (!(jsonValue instanceof JsonValue)) {\r\n            return jsonValue;\r\n        }\r\n        switch (((JsonValue) jsonValue).getValueType()) {\r\n        case ARRAY:\r\n        \t// TODO do we unwrap JsonObjectArray proxies?\r\n            //return ((JsonArray) jsonValue).getValuesAs(JsonValue.class);\r\n            return ((JsonArray) jsonValue).getValuesAs((JsonValue v) -> unwrapJsonValue(v));\r\n        case OBJECT:\r\n            throw new IllegalArgumentException(\"Use map() method to databind a JsonObject\");\r\n        case STRING:\r\n            return ((JsonString) jsonValue).getString();\r\n        case NUMBER:\r\n            if (((JsonNumber) jsonValue).isIntegral()) {\r\n                //return ((JsonNumber) jsonValue).bigIntegerValueExact();\r\n                try {\r\n                    return ((JsonNumber) jsonValue).intValueExact();\r\n                } catch (ArithmeticException e) {\r\n                    return ((JsonNumber) jsonValue).longValueExact();\r\n                }\r\n            } else {\r\n                //return ((JsonNumber) jsonValue).bigDecimalValue();\r\n                return ((JsonNumber) jsonValue).doubleValue();\r\n            }\r\n        case TRUE:\r\n            return Boolean.TRUE;\r\n        case FALSE:\r\n            return Boolean.FALSE;\r\n        case NULL:\r\n            return null;\r\n        default:\r\n            return jsonValue;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Creates new instance of {@code Collection} type specified by the\r\n     * argument. If the argument refers to an interface, then a matching\r\n     * Java standard implementation is returned; if it is a concrete class,\r\n     * then method attempts to instantiate an object of that class given\r\n     * there is a public no-arg constructor available.\r\n     *\r\n     * @param collectionType collection type; may be an interface or a class\r\n     * @return instance of collection type identified by the argument\r\n     * @throws MappingException on a type that cannot be safely instantiated\r\n     */\r\n    private Collection<Object> newCollectionOfType(Class<?> collectionType) throws MappingException {\r\n        if (Collection.class.isAssignableFrom(collectionType)) {\r\n            if (!collectionType.isInterface()) {\r\n                @SuppressWarnings(\"unchecked\")\r\n                Collection<Object> coll = (Collection<Object>) newNoArgInstance(collectionType);\r\n                return coll;\r\n            } else if (List.class.isAssignableFrom(collectionType)) {\r\n                return new java.util.LinkedList<Object>();\r\n            } else if (Set.class.isAssignableFrom(collectionType)) {\r\n                return new java.util.LinkedHashSet<Object>();\r\n            } else if (Queue.class.isAssignableFrom(collectionType)) {\r\n                return new java.util.LinkedList<Object>();\r\n            }\r\n        }\r\n        String className = collectionType.getSimpleName();\r\n        throw new MappingException(\"JSON array cannot be mapped to \" + className);\r\n    }\r\n\r\n    /**\r\n     * Lists all publicly accessible constructors for the {@code Class}\r\n     * identified by the argument, including any constructors inherited\r\n     * from superclasses, and uses a no-args constructor, if available,\r\n     * to create a new instance of the class. If argument is interface, \r\n     * this method returns {@code null}.\r\n     * \r\n     * @param targetType class type to create instance of\r\n     * @return an instance of the class represented by the argument\r\n     * @throws MappingException if no-arg public constructor is not there \r\n     */\r\n    private Object newNoArgInstance(Class<?> targetType) throws MappingException {\r\n        if (targetType.isInterface()) {\r\n            return null;\r\n        } else {\r\n            for (Constructor<?> ctr : targetType.getConstructors()) {\r\n                if (ctr.getParameterCount() == 0) {\r\n                    try {\r\n                        return ctr.newInstance();\r\n                    } catch (ReflectiveOperationException e) {\r\n                        throw new MappingException(e);\r\n                    } catch (IllegalArgumentException e) {\r\n                        // never happens\r\n                    }\r\n                }\r\n            }\r\n            String className = targetType.getSimpleName();\r\n            throw new MappingException(\"Unable to find no-arg ctr for \" + className);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Locates optional API method on the supplied JSON-B API implementation class with\r\n     * the supplied name and parameter types. Searches the superclasses up to\r\n     * {@code Object}, but ignores interfaces and default interface methods. Returns\r\n     * {@code null} if no {@code Method} can be found. \r\n     *\r\n     * @param clazz the implementation class to reflect upon\r\n     * @param name the name of the method\r\n     * @param paramTypes the parameter types of the method\r\n     * @return the {@code Method} reference, or {@code null} if none found\r\n     */\r\n    private Method findMethod(Class<?> clazz, String name, Class<?>... paramTypes) {\r\n        while (clazz != null && !clazz.isInterface()) {\r\n            for (Method method : clazz.getDeclaredMethods()) {\r\n                final int mods = method.getModifiers();\r\n                if (Modifier.isPublic(mods) && !Modifier.isAbstract(mods) &&\r\n                        name.equals(method.getName()) &&\r\n                        Arrays.equals(paramTypes, method.getParameterTypes())) {\r\n                    return method;\r\n                }\r\n            }\r\n            clazz = clazz.getSuperclass();\r\n        }\r\n        return null;\r\n    }\r\n\r\n    private Class<?> getRawClass(Type targetType) {\r\n        if (targetType instanceof Class) {\r\n            return (Class<?>) targetType;\r\n        } else if (targetType instanceof ParameterizedType) {\r\n            return (Class<?>) ((ParameterizedType) targetType).getRawType();\r\n        } else if (targetType instanceof GenericArrayType) {\r\n            String typeName = targetType.getTypeName();\r\n            throw new MappingException(\"Cannot map JSON element to \" + typeName);\r\n        } else {\r\n            String typeName = targetType.getTypeName();\r\n            throw new IllegalArgumentException(\"TypeRef not supported: \" + typeName);\r\n        }\r\n    }\r\n\r\n    private Type getFirstTypeArgument(Type targetType) {\r\n        if (targetType instanceof ParameterizedType) {\r\n            Type[] args = ((ParameterizedType) targetType).getActualTypeArguments();\r\n            if (args != null && args.length > 0) {\r\n                if (args[0] instanceof Class) {\r\n                    return (Class<?>) args[0];\r\n                } else if (args[0] instanceof ParameterizedType) {\r\n                    return (ParameterizedType) args[0];\r\n                }\r\n            }\r\n        }\r\n        return null;\r\n    }\r\n\r\n    /**\r\n     * Runtime adapter for {@link JsonParser} to pull the JSON objects and values from\r\n     * a {@link JsonStructure} content tree instead of plain JSON string.\r\n     * <p>\r\n     * JSON-B API 1.0 final specification does not include any public methods to read JSON\r\n     * content from pre-parsed {@link JsonStructure} tree, so this parser is used by the\r\n     * Jakarta EE mapping provider above to feed in JSON content to JSON-B implementation.\r\n     */\r\n    private static class JsonStructureToParserAdapter implements JsonParser {\r\n\r\n        private JsonStructureScope scope;\r\n        private Event state;\r\n        private final Deque<JsonStructureScope> ancestry = new ArrayDeque<>();\r\n\r\n        JsonStructureToParserAdapter(JsonStructure jsonStruct) {\r\n            scope = createScope(jsonStruct);\r\n        }\r\n\r\n        @Override\r\n        public boolean hasNext() {\r\n            return !((state == Event.END_ARRAY || state == Event.END_OBJECT) && ancestry.isEmpty());\r\n        }\r\n\r\n        @Override\r\n        public Event next() {\r\n            if (!hasNext()) {\r\n                throw new NoSuchElementException();\r\n            }\r\n            if (state == null) {\r\n                state = scope instanceof JsonArrayScope ? Event.START_ARRAY : Event.START_OBJECT;\r\n            } else {\r\n                if (state == Event.END_ARRAY || state == Event.END_OBJECT) {\r\n                    scope = ancestry.pop();\r\n                }\r\n                if (scope instanceof JsonArrayScope) { // array scope\r\n                    if (scope.hasNext()) {\r\n                        scope.next();\r\n                        state = getState(scope.getValue());\r\n                        if (state == Event.START_ARRAY || state == Event.START_OBJECT) {\r\n                            ancestry.push(scope);\r\n                            scope = createScope(scope.getValue());\r\n                        }\r\n                    } else {\r\n                        state = Event.END_ARRAY;\r\n                    }\r\n                } else { // object scope\r\n                    if (state == Event.KEY_NAME) {\r\n                        state = getState(scope.getValue());\r\n                        if (state == Event.START_ARRAY || state == Event.START_OBJECT) {\r\n                            ancestry.push(scope);\r\n                            scope = createScope(scope.getValue());\r\n                        }\r\n                    } else {\r\n                        if (scope.hasNext()) {\r\n                            scope.next();\r\n                            state = Event.KEY_NAME;\r\n                        } else {\r\n                            state = Event.END_OBJECT;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            return state;\r\n        }\r\n\r\n        @Override\r\n        public String getString() {\r\n            switch (state) {\r\n            case KEY_NAME:\r\n                return ((JsonObjectScope) scope).getKey();\r\n            case VALUE_STRING:\r\n                return ((JsonString) scope.getValue()).getString();\r\n            case VALUE_NUMBER:\r\n                return ((JsonNumber) scope.getValue()).toString();\r\n            default:\r\n                throw new IllegalStateException(\"Parser is not in KEY_NAME, VALUE_STRING, or VALUE_NUMBER state\");\r\n            }\r\n        }\r\n\r\n        @Override\r\n        public boolean isIntegralNumber() {\r\n            if (state == Event.VALUE_NUMBER) {\r\n                return ((JsonNumber) scope.getValue()).isIntegral();\r\n            }\r\n            throw new IllegalStateException(\"Target json value must a number, not \" + state);\r\n        }\r\n\r\n        @Override\r\n        public int getInt() {\r\n            if (state == Event.VALUE_NUMBER) {\r\n                return ((JsonNumber) scope.getValue()).intValue();\r\n            }\r\n            throw new IllegalStateException(\"Target json value must a number, not \" + state);\r\n        }\r\n\r\n        @Override\r\n        public long getLong() {\r\n            if (state == Event.VALUE_NUMBER) {\r\n                return ((JsonNumber) scope.getValue()).longValue();\r\n            }\r\n            throw new IllegalStateException(\"Target json value must a number, not \" + state);\r\n        }\r\n\r\n        @Override\r\n        public BigDecimal getBigDecimal() {\r\n            if (state == Event.VALUE_NUMBER) {\r\n                return ((JsonNumber) scope.getValue()).bigDecimalValue();\r\n            }\r\n            throw new IllegalStateException(\"Target json value must a number, not \" + state);\r\n        }\r\n\r\n        @Override\r\n        public JsonLocation getLocation() {\r\n            throw new UnsupportedOperationException(\"JSON-P adapter does not support getLocation()\");\r\n        }\r\n\r\n        @Override\r\n        public void skipArray() {\r\n            if (scope instanceof JsonArrayScope) {\r\n                while (scope.hasNext()) {\r\n                    scope.next();\r\n                }\r\n                state = Event.END_ARRAY;\r\n            }\r\n        }\r\n\r\n        @Override\r\n        public void skipObject() {\r\n            if (scope instanceof JsonObjectScope) {\r\n                while (scope.hasNext()) {\r\n                    scope.next();\r\n                }\r\n                state = Event.END_OBJECT;\r\n            }\r\n        }\r\n\r\n        @Override\r\n        public void close() {\r\n            // JSON objects are read-only\r\n        }\r\n\r\n        private JsonStructureScope createScope(JsonValue value) {\r\n            if (value instanceof JsonArray) {\r\n                return new JsonArrayScope((JsonArray) value);\r\n            } else if (value instanceof JsonObject) {\r\n                return new JsonObjectScope((JsonObject) value);\r\n            }\r\n            throw new JsonException(\"Cannot create JSON iterator for \" + value);\r\n        }\r\n\r\n        private Event getState(JsonValue value) {\r\n            switch (value.getValueType()) {\r\n            case ARRAY:\r\n                return Event.START_ARRAY;\r\n            case OBJECT:\r\n                return Event.START_OBJECT;\r\n            case STRING:\r\n                return Event.VALUE_STRING;\r\n            case NUMBER:\r\n                return Event.VALUE_NUMBER;\r\n            case TRUE:\r\n                return Event.VALUE_TRUE;\r\n            case FALSE:\r\n                return Event.VALUE_FALSE;\r\n            case NULL:\r\n                return Event.VALUE_NULL;\r\n            default:\r\n                throw new JsonException(\"Unknown value type \" + value.getValueType());\r\n            }\r\n        }\r\n    }\r\n\r\n    private static abstract class JsonStructureScope implements Iterator<JsonValue> {\r\n        /**\r\n         * Returns current {@link JsonValue}, that the parser is pointing on. Before\r\n         * the {@link #next()} method has been called, this returns {@code null}.\r\n         *\r\n         * @return JsonValue value object.\r\n         */\r\n        abstract JsonValue getValue();\r\n    }\r\n\r\n    private static class JsonArrayScope extends JsonStructureScope {\r\n        private final Iterator<JsonValue> it;\r\n        private JsonValue value;\r\n\r\n        JsonArrayScope(JsonArray array) {\r\n            this.it = array.iterator();\r\n        }\r\n\r\n        @Override\r\n        public boolean hasNext() {\r\n            return it.hasNext();\r\n        }\r\n\r\n        @Override\r\n        public JsonValue next() {\r\n            value = it.next();\r\n            return value;\r\n        }\r\n\r\n        @Override\r\n        JsonValue getValue() {\r\n            return value;\r\n        }\r\n    }\r\n\r\n    private static class JsonObjectScope extends JsonStructureScope {\r\n        private final Iterator<Map.Entry<String, JsonValue>> it;\r\n        private JsonValue value;\r\n        private String key;\r\n\r\n        JsonObjectScope(JsonObject object) {\r\n            this.it = object.entrySet().iterator();\r\n        }\r\n\r\n        @Override\r\n        public boolean hasNext() {\r\n            return it.hasNext();\r\n        }\r\n\r\n        @Override\r\n        public JsonValue next() {\r\n            Map.Entry<String, JsonValue> next = it.next();\r\n            this.key = next.getKey();\r\n            this.value = next.getValue();\r\n            return value;\r\n        }\r\n\r\n        @Override\r\n        JsonValue getValue() {\r\n            return value;\r\n        }\r\n\r\n        String getKey() {\r\n            return key;\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/mapper/JsonOrgMappingProvider.java",
    "content": "package com.jayway.jsonpath.spi.mapper;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.TypeRef;\nimport org.json.JSONArray;\nimport org.json.JSONObject;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class JsonOrgMappingProvider implements MappingProvider {\n    @Override\n    public <T> T map(Object source, Class<T> targetType, Configuration configuration) {\n        if(source == null){\n            return null;\n        }\n        if(targetType.equals(Object.class) || targetType.equals(List.class) || targetType.equals(Map.class)){\n            return (T) mapToObject(source);\n        }\n        return (T)source;\n    }\n\n    @Override\n    public <T> T map(Object source, TypeRef<T> targetType, Configuration configuration) {\n        throw new UnsupportedOperationException(\"JsonOrg provider does not support TypeRef! Use a Jackson or Gson based provider\");\n    }\n\n\n    private Object mapToObject(Object source){\n        if(source instanceof JSONArray){\n            List<Object> mapped = new ArrayList<Object>();\n            JSONArray array = (JSONArray) source;\n\n            for (int i = 0; i < array.length(); i++){\n                mapped.add(mapToObject(array.get(i)));\n            }\n\n            return mapped;\n        }\n        else if (source instanceof JSONObject){\n            Map<String, Object> mapped = new HashMap<String, Object>();\n            JSONObject obj = (JSONObject) source;\n\n            for (Object o : obj.keySet()) {\n                String key = o.toString();\n                mapped.put(key, mapToObject(obj.get(key)));\n            }\n            return mapped;\n        }\n        else if (source == JSONObject.NULL){\n            return null;\n        } else {\n            return source;\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/mapper/JsonSmartMappingProvider.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.mapper;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.TypeRef;\nimport net.minidev.json.JSONValue;\nimport net.minidev.json.writer.JsonReader;\nimport net.minidev.json.writer.JsonReaderI;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.text.DateFormat;\nimport java.text.ParseException;\nimport java.util.Date;\nimport java.util.concurrent.Callable;\n\npublic class JsonSmartMappingProvider implements MappingProvider {\n\n    private static JsonReader DEFAULT = new JsonReader();\n\n    static {\n        DEFAULT.registerReader(Long.class, new LongReader());\n        DEFAULT.registerReader(long.class, new LongReader());\n        DEFAULT.registerReader(Integer.class, new IntegerReader());\n        DEFAULT.registerReader(int.class, new IntegerReader());\n        DEFAULT.registerReader(Double.class, new DoubleReader());\n        DEFAULT.registerReader(double.class, new DoubleReader());\n        DEFAULT.registerReader(Float.class, new FloatReader());\n        DEFAULT.registerReader(float.class, new FloatReader());\n        DEFAULT.registerReader(BigDecimal.class, new BigDecimalReader());\n        DEFAULT.registerReader(String.class, new StringReader());\n        DEFAULT.registerReader(Date.class, new DateReader());\n        DEFAULT.registerReader(BigInteger.class, new BigIntegerReader());\n        DEFAULT.registerReader(boolean.class, new BooleanReader());\n    }\n\n\n    private final Callable<JsonReader> factory;\n\n    public JsonSmartMappingProvider(final JsonReader jsonReader) {\n        this(new Callable<JsonReader>() {\n            @Override\n            public JsonReader call() {\n                return jsonReader;\n            }\n        });\n    }\n\n    public JsonSmartMappingProvider(Callable<JsonReader> factory) {\n        this.factory = factory;\n    }\n\n    public JsonSmartMappingProvider() {\n        this(DEFAULT);\n    }\n\n\n\n    @Override\n    public <T> T map(Object source, Class<T> targetType, Configuration configuration) {\n        if(source == null){\n            return null;\n        }\n        if (targetType.isAssignableFrom(source.getClass())) {\n            return (T) source;\n        }\n        try {\n            if(!configuration.jsonProvider().isMap(source) && !configuration.jsonProvider().isArray(source)){\n                return factory.call().getMapper(targetType).convert(source);\n            }\n            String s = configuration.jsonProvider().toJson(source);\n            return (T) JSONValue.parse(s, targetType);\n        } catch (Exception e) {\n            throw new MappingException(e);\n        }\n\n    }\n\n    @Override\n    public <T> T map(Object source, TypeRef<T> targetType, Configuration configuration) {\n        throw new UnsupportedOperationException(\"Json-smart provider does not support TypeRef! Use a Jackson or Gson based provider\");\n    }\n\n    private static class StringReader extends JsonReaderI<String> {\n        public StringReader() {\n            super(null);\n        }\n        public String convert(Object src) {\n            if(src == null){\n                return null;\n            }\n            return src.toString();\n        }\n    }\n    private static class IntegerReader extends JsonReaderI<Integer> {\n        public IntegerReader() {\n            super(null);\n        }\n        public Integer convert(Object src) {\n            if(src == null){\n                return null;\n            }\n            if(Integer.class.isAssignableFrom(src.getClass())){\n               return (Integer) src;\n            } else if (Long.class.isAssignableFrom(src.getClass())) {\n                return ((Long) src).intValue();\n            } else if (Double.class.isAssignableFrom(src.getClass())) {\n                return ((Double) src).intValue();\n            } else if (BigDecimal.class.isAssignableFrom(src.getClass())) {\n                return ((BigDecimal) src).intValue();\n            } else if (Float.class.isAssignableFrom(src.getClass())) {\n                return ((Float) src).intValue();\n            } else if (String.class.isAssignableFrom(src.getClass())) {\n                return Integer.valueOf(src.toString());\n            }\n            throw new MappingException(\"can not map a \" + src.getClass() + \" to \" + Integer.class.getName());\n        }\n    }\n    private static class LongReader extends JsonReaderI<Long> {\n        public LongReader() {\n            super(null);\n        }\n        public Long convert(Object src) {\n            if(src == null){\n                return null;\n            }\n            if(Long.class.isAssignableFrom(src.getClass())){\n                return (Long) src;\n            } else if (Integer.class.isAssignableFrom(src.getClass())) {\n                return ((Integer) src).longValue();\n            } else if (Double.class.isAssignableFrom(src.getClass())) {\n                return ((Double) src).longValue();\n            } else if (BigDecimal.class.isAssignableFrom(src.getClass())) {\n                return ((BigDecimal) src).longValue();\n            } else if (Float.class.isAssignableFrom(src.getClass())) {\n                return ((Float) src).longValue();\n            } else if (String.class.isAssignableFrom(src.getClass())) {\n                return Long.valueOf(src.toString());\n            }\n            throw new MappingException(\"can not map a \" + src.getClass() + \" to \" + Long.class.getName());\n        }\n    }\n\n    private static class DoubleReader extends JsonReaderI<Double> {\n        public DoubleReader() {\n            super(null);\n        }\n        public Double convert(Object src) {\n            if(src == null){\n                return null;\n            }\n            if(Double.class.isAssignableFrom(src.getClass())){\n                return (Double) src;\n            } else if (Integer.class.isAssignableFrom(src.getClass())) {\n                return ((Integer) src).doubleValue();\n            } else if (Long.class.isAssignableFrom(src.getClass())) {\n                return ((Long) src).doubleValue();\n            } else if (BigDecimal.class.isAssignableFrom(src.getClass())) {\n                return ((BigDecimal) src).doubleValue();\n            } else if (Float.class.isAssignableFrom(src.getClass())) {\n                return ((Float) src).doubleValue();\n            } else if (String.class.isAssignableFrom(src.getClass())) {\n                return Double.valueOf(src.toString());\n            }\n            throw new MappingException(\"can not map a \" + src.getClass() + \" to \" + Double.class.getName());\n        }\n    }\n    private static class FloatReader extends JsonReaderI<Float> {\n        public FloatReader() {\n            super(null);\n        }\n        public Float convert(Object src) {\n            if(src == null){\n                return null;\n            }\n            if(Float.class.isAssignableFrom(src.getClass())){\n                return (Float) src;\n            } else if (Integer.class.isAssignableFrom(src.getClass())) {\n                return ((Integer) src).floatValue();\n            } else if (Long.class.isAssignableFrom(src.getClass())) {\n                return ((Long) src).floatValue();\n            } else if (BigDecimal.class.isAssignableFrom(src.getClass())) {\n                return ((BigDecimal) src).floatValue();\n            } else if (Double.class.isAssignableFrom(src.getClass())) {\n                return ((Double) src).floatValue();\n            } else if (String.class.isAssignableFrom(src.getClass())) {\n                return Float.valueOf(src.toString());\n            }\n            throw new MappingException(\"can not map a \" + src.getClass() + \" to \" + Float.class.getName());\n        }\n    }\n    private static class BigDecimalReader extends JsonReaderI<BigDecimal> {\n        public BigDecimalReader() {\n            super(null);\n        }\n        public BigDecimal convert(Object src) {\n            if(src == null){\n                return null;\n            }\n            return new BigDecimal(src.toString());\n        }\n    }\n    private static class BigIntegerReader extends JsonReaderI<BigInteger> {\n        public BigIntegerReader() {\n            super(null);\n        }\n        public BigInteger convert(Object src) {\n            if(src == null){\n                return null;\n            }\n            return new BigInteger(src.toString());\n        }\n    }\n    private static class DateReader extends JsonReaderI<Date> {\n        public DateReader() {\n            super(null);\n        }\n        public Date convert(Object src) {\n            if(src == null){\n                return null;\n            }\n            if(Date.class.isAssignableFrom(src.getClass())){\n                return (Date) src;\n            } else if(Long.class.isAssignableFrom(src.getClass())){\n                return new Date((Long) src);\n            } else if(String.class.isAssignableFrom(src.getClass())){\n                try {\n                    return DateFormat.getInstance().parse(src.toString());\n                } catch (ParseException e) {\n                    throw new MappingException(e);\n                }\n            }\n            throw new MappingException(\"can not map a \" + src.getClass() + \" to \" + Date.class.getName());\n        }\n    }\n    private static class BooleanReader extends JsonReaderI<Boolean> {\n        public BooleanReader() {\n            super(null);\n        }\n        public Boolean convert(Object src) {\n            if(src == null){\n                return null;\n            }\n            if (Boolean.class.isAssignableFrom(src.getClass())) {\n                return (Boolean) src;\n            }\n            throw new MappingException(\"can not map a \" + src.getClass() + \" to \" + Boolean.class.getName());\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/mapper/MappingException.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.mapper;\n\nimport com.jayway.jsonpath.JsonPathException;\n\npublic class MappingException extends JsonPathException {\n\n    public MappingException(Throwable cause) {\n        super(cause);\n    }\n\n    public MappingException(String message) {\n        super(message);\n    }\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/mapper/MappingProvider.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.mapper;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.TypeRef;\n\n/**\n * Maps object between different Types\n */\npublic interface MappingProvider {\n\n\n    /**\n     *\n     * @param source object to map\n     * @param targetType the type the source object should be mapped to\n     * @param configuration current configuration\n     * @param <T> the mapped result type\n     * @return return the mapped object\n     */\n    <T> T map(Object source, Class<T> targetType, Configuration configuration);\n\n    /**\n     *\n     * @param source object to map\n     * @param targetType the type the source object should be mapped to\n     * @param configuration current configuration\n     * @param <T> the mapped result type\n     * @return return the mapped object\n     */\n    <T> T map(Object source, TypeRef<T> targetType, Configuration configuration);\n}\n"
  },
  {
    "path": "json-path/src/main/java/com/jayway/jsonpath/spi/mapper/TapestryMappingProvider.java",
    "content": "/*\n * Copyright 2011 the original author or authors.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.jayway.jsonpath.spi.mapper;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.TypeRef;\n\nimport java.util.ArrayList;\n\npublic class TapestryMappingProvider implements MappingProvider {\n\n  @Override\n  public <T> T map(final Object source, final Class<T> targetType, final Configuration configuration) {\n    if (source == null) {\n      return null;\n    }\n    if (targetType.isAssignableFrom(source.getClass())) {\n      return (T) source;\n    }\n    try {\n      if (targetType.isAssignableFrom(ArrayList.class) && configuration.jsonProvider().isArray(source)) {\n        int length = configuration.jsonProvider().length(source);\n        @SuppressWarnings(\"rawtypes\")\n        ArrayList list = new ArrayList(length);\n        for (Object o : configuration.jsonProvider().toIterable(source)) {\n          list.add(o);\n        }\n        return (T) list;\n      }\n    } catch (Exception e) {\n\n    }\n    throw new MappingException(\"Cannot convert a \" + source.getClass().getName() + \" to a \" + targetType\n        + \" use Tapestry's TypeCoercer instead.\");\n  }\n\n  @Override\n  public <T> T map(final Object source, final TypeRef<T> targetType, final Configuration configuration) {\n    throw new UnsupportedOperationException(\n        \"Tapestry JSON provider does not support TypeRef! Use a Jackson or Gson based provider\");\n  }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/BaseTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport com.jayway.jsonpath.internal.Path;\nimport com.jayway.jsonpath.internal.path.PredicateContextImpl;\nimport com.jayway.jsonpath.spi.json.GsonJsonProvider;\nimport com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider;\nimport com.jayway.jsonpath.spi.json.JacksonJsonProvider;\nimport com.jayway.jsonpath.spi.json.Jackson3JsonNodeJsonProvider;\nimport com.jayway.jsonpath.spi.json.Jackson3JsonProvider;\nimport com.jayway.jsonpath.spi.json.JakartaJsonProvider;\nimport com.jayway.jsonpath.spi.json.JettisonProvider;\nimport com.jayway.jsonpath.spi.json.JsonOrgJsonProvider;\nimport com.jayway.jsonpath.spi.json.JsonSmartJsonProvider;\nimport com.jayway.jsonpath.spi.json.TapestryJsonProvider;\nimport com.jayway.jsonpath.spi.mapper.GsonMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.Jackson3MappingProvider;\nimport com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.JakartaMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.JsonOrgMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.TapestryMappingProvider;\n\nimport java.util.HashMap;\n\npublic class BaseTest {\n\n    public static final Configuration JSON_ORG_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new JsonOrgMappingProvider())\n            .jsonProvider(new JsonOrgJsonProvider())\n            .build();\n\n    public static final Configuration GSON_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new GsonMappingProvider())\n            .jsonProvider(new GsonJsonProvider())\n            .build();\n\n    public static final Configuration JACKSON_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new JacksonMappingProvider())\n            .jsonProvider(new JacksonJsonProvider())\n            .build();\n\n    public static final Configuration JACKSON_JSON_NODE_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new JacksonMappingProvider())\n            .jsonProvider(new JacksonJsonNodeJsonProvider())\n            .build();\n\n    public static final Configuration JACKSON3_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new Jackson3MappingProvider())\n            .jsonProvider(new Jackson3JsonProvider())\n            .build();\n\n    public static final Configuration JACKSON3_JSON_NODE_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new Jackson3MappingProvider())\n            .jsonProvider(new Jackson3JsonNodeJsonProvider())\n            .build();\n\n    public static final Configuration JETTISON_CONFIGURATION = Configuration\n            .builder()\n            .jsonProvider(new JettisonProvider())\n            .build();\n\n    public static final Configuration JSON_SMART_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new JsonSmartMappingProvider())\n            .jsonProvider(new JsonSmartJsonProvider())\n            .build();\n    \n    public static final Configuration TAPESTRY_JSON_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new TapestryMappingProvider())\n            .jsonProvider(TapestryJsonProvider.INSTANCE)\n            .build();\n\n    public static final Configuration JAKARTA_JSON_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new JakartaMappingProvider())\n            .jsonProvider(new JakartaJsonProvider())\n            .build();\n\n    // extension to Jakarta EE 9 JSON-P with mutable objects and array\n    public static final Configuration JAKARTA_JSON_RW_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new JakartaMappingProvider())\n            .jsonProvider(new JakartaJsonProvider(true))\n            .build();\n\n    public static final String JSON_BOOK_DOCUMENT =\n            \"{ \" +\n            \"   \\\"category\\\" : \\\"reference\\\",\\n\" +\n            \"   \\\"author\\\" : \\\"Nigel Rees\\\",\\n\" +\n            \"   \\\"title\\\" : \\\"Sayings of the Century\\\",\\n\" +\n            \"   \\\"display-price\\\" : 8.95\\n\" +\n            \"}\";\n    public static final String JSON_DOCUMENT = \"{\\n\" +\n            \"   \\\"string-property\\\" : \\\"string-value\\\", \\n\" +\n            \"   \\\"int-max-property\\\" : \" + Integer.MAX_VALUE + \", \\n\" +\n            \"   \\\"long-max-property\\\" : \" + Long.MAX_VALUE + \", \\n\" +\n            \"   \\\"boolean-property\\\" : true, \\n\" +\n            \"   \\\"null-property\\\" : null, \\n\" +\n            \"   \\\"int-small-property\\\" : 1, \\n\" +\n            \"   \\\"max-price\\\" : 10, \\n\" +\n            \"   \\\"store\\\" : {\\n\" +\n            \"      \\\"book\\\" : [\\n\" +\n            \"         {\\n\" +\n            \"            \\\"category\\\" : \\\"reference\\\",\\n\" +\n            \"            \\\"author\\\" : \\\"Nigel Rees\\\",\\n\" +\n            \"            \\\"title\\\" : \\\"Sayings of the Century\\\",\\n\" +\n            \"            \\\"display-price\\\" : 8.95\\n\" +\n            \"         },\\n\" +\n            \"         {\\n\" +\n            \"            \\\"category\\\" : \\\"fiction\\\",\\n\" +\n            \"            \\\"author\\\" : \\\"Evelyn Waugh\\\",\\n\" +\n            \"            \\\"title\\\" : \\\"Sword of Honour\\\",\\n\" +\n            \"            \\\"display-price\\\" : 12.99\\n\" +\n            \"         },\\n\" +\n            \"         {\\n\" +\n            \"            \\\"category\\\" : \\\"fiction\\\",\\n\" +\n            \"            \\\"author\\\" : \\\"Herman Melville\\\",\\n\" +\n            \"            \\\"title\\\" : \\\"Moby Dick\\\",\\n\" +\n            \"            \\\"isbn\\\" : \\\"0-553-21311-3\\\",\\n\" +\n            \"            \\\"display-price\\\" : 8.99\\n\" +\n            \"         },\\n\" +\n            \"         {\\n\" +\n            \"            \\\"category\\\" : \\\"fiction\\\",\\n\" +\n            \"            \\\"author\\\" : \\\"J. R. R. Tolkien\\\",\\n\" +\n            \"            \\\"title\\\" : \\\"The Lord of the Rings\\\",\\n\" +\n            \"            \\\"isbn\\\" : \\\"0-395-19395-8\\\",\\n\" +\n            \"            \\\"display-price\\\" : 22.99\\n\" +\n            \"         }\\n\" +\n            \"      ],\\n\" +\n            \"      \\\"bicycle\\\" : {\\n\" +\n            \"         \\\"foo\\\" : \\\"baz\\\",\\n\" +\n            \"         \\\"escape\\\" : \\\"Esc\\\\b\\\\f\\\\n\\\\r\\\\t\\\\n\\\\t\\\\u002A\\\",\\n\" +\n            \"         \\\"color\\\" : \\\"red\\\",\\n\" +\n            \"         \\\"display-price\\\" : 19.95,\\n\" +\n            \"         \\\"foo:bar\\\" : \\\"fooBar\\\",\\n\" +\n            \"         \\\"dot.notation\\\" : \\\"new\\\",\\n\" +\n            \"         \\\"dash-notation\\\" : \\\"dashes\\\"\\n\" +\n            \"      }\\n\" +\n            \"   },\\n\" +\n            \"   \\\"foo\\\" : \\\"bar\\\",\\n\" +\n            \"   \\\"@id\\\" : \\\"ID\\\"\\n\" +\n            \"}\";\n\n    public static String JSON_BOOK_STORE_DOCUMENT = \"{\\n\" +\n            \"    \\\"store\\\": {\\n\" +\n            \"        \\\"book\\\": [\\n\" +\n            \"            {\\n\" +\n            \"                \\\"category\\\": \\\"reference\\\"\\n\" +\n            \"            },\\n\" +\n            \"            {\\n\" +\n            \"                \\\"category\\\": \\\"fiction\\\"\\n\" +\n            \"            },\\n\" +\n            \"            {\\n\" +\n            \"                \\\"category\\\": \\\"fiction\\\"\\n\" +\n            \"            },\\n\" +\n            \"            {\\n\" +\n            \"                \\\"category\\\": \\\"fiction\\\"\\n\" +\n            \"            }\\n\" +\n            \"        ]\\n\" +\n            \"    },\\n\" +\n            \"    \\\"expensive\\\": 10\\n\" +\n            \"}\";\n\n    public Predicate.PredicateContext createPredicateContext(final Object check) {\n\n        return new PredicateContextImpl(check, check, Configuration.defaultConfiguration(), new HashMap<Path, Object>());\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/Configurations.java",
    "content": "package com.jayway.jsonpath;\n\nimport com.jayway.jsonpath.spi.json.GsonJsonProvider;\nimport com.jayway.jsonpath.spi.json.Jackson3JsonNodeJsonProvider;\nimport com.jayway.jsonpath.spi.json.Jackson3JsonProvider;\nimport com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider;\nimport com.jayway.jsonpath.spi.json.JacksonJsonProvider;\nimport com.jayway.jsonpath.spi.json.JakartaJsonProvider;\nimport com.jayway.jsonpath.spi.json.JsonOrgJsonProvider;\nimport com.jayway.jsonpath.spi.json.JsonSmartJsonProvider;\nimport com.jayway.jsonpath.spi.mapper.GsonMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.Jackson3MappingProvider;\nimport com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.JakartaMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.JsonOrgMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider;\n\nimport java.util.Arrays;\n\npublic class Configurations {\n\n    public static final Configuration JSON_ORG_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new JsonOrgMappingProvider())\n            .jsonProvider(new JsonOrgJsonProvider())\n            .build();\n\n    public static final Configuration GSON_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new GsonMappingProvider())\n            .jsonProvider(new GsonJsonProvider())\n            .build();\n\n    public static final Configuration JACKSON_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new JacksonMappingProvider())\n            .jsonProvider(new JacksonJsonProvider())\n            .build();\n\n    public static final Configuration JACKSON_JSON_NODE_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new JacksonMappingProvider())\n            .jsonProvider(new JacksonJsonNodeJsonProvider())\n            .build();\n\n    public static final Configuration JACKSON3_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new Jackson3MappingProvider())\n            .jsonProvider(new Jackson3JsonProvider())\n            .build();\n\n    public static final Configuration JACKSON3_JSON_NODE_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new Jackson3MappingProvider())\n            .jsonProvider(new Jackson3JsonNodeJsonProvider())\n            .build();\n\n    public static final Configuration JSON_SMART_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new JsonSmartMappingProvider())\n            .jsonProvider(new JsonSmartJsonProvider())\n            .build();\n\n    public static final Configuration JAKARTA_CONFIGURATION = Configuration\n            .builder()\n            .mappingProvider(new JakartaMappingProvider())\n            .jsonProvider(new JakartaJsonProvider())\n            .build();\n\n    public static Iterable<Configuration> configurations() {\n        return Arrays.asList(\n               JSON_SMART_CONFIGURATION\n               ,GSON_CONFIGURATION\n               ,JACKSON_CONFIGURATION\n               ,JACKSON_JSON_NODE_CONFIGURATION\n               ,JACKSON3_CONFIGURATION\n               ,JACKSON3_JSON_NODE_CONFIGURATION\n               ,JSON_ORG_CONFIGURATION\n               ,JAKARTA_CONFIGURATION\n        );\n    }\n\n    public static Iterable<Configuration> objectMappingConfigurations() {\n        return Arrays.asList(\n                 GSON_CONFIGURATION\n                ,JACKSON_CONFIGURATION\n                ,JACKSON_JSON_NODE_CONFIGURATION\n                ,JACKSON3_CONFIGURATION\n                ,JACKSON3_JSON_NODE_CONFIGURATION\n                ,JAKARTA_CONFIGURATION\n        );\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/DeepScanTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.jayway.jsonpath.JsonPath.parse;\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static com.jayway.jsonpath.TestUtils.assertEvaluationThrows;\nimport static java.util.Collections.singletonMap;\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * Deep scan is indefinite, so certain \"illegal\" actions become a no-op instead of a path evaluation exception.\n */\npublic class DeepScanTest extends BaseTest {\n\n    @Test\n    public void when_deep_scanning_non_array_subscription_is_ignored() {\n        Object result = JsonPath.parse(\"{\\\"x\\\": [0,1,[0,1,2,3,null],null]}\").read(\"$..[2][3]\");\n        assertThat(result).asList().containsOnly(3);\n        result = JsonPath.parse(\"{\\\"x\\\": [0,1,[0,1,2,3,null],null], \\\"y\\\": [0,1,2]}\").read(\"$..[2][3]\");\n        assertThat(result).asList().containsOnly(3);\n\n        result = JsonPath.parse(\"{\\\"x\\\": [0,1,[0,1,2],null], \\\"y\\\": [0,1,2]}\").read(\"$..[2][3]\");\n        assertThat(result).asList().isEmpty();\n    }\n\n    @Test\n    public void when_deep_scanning_null_subscription_is_ignored() {\n        Object result = JsonPath.parse(\"{\\\"x\\\": [null,null,[0,1,2,3,null],null]}\").read(\"$..[2][3]\");\n        assertThat(result).asList().containsOnly(3);\n        result = JsonPath.parse(\"{\\\"x\\\": [null,null,[0,1,2,3,null],null], \\\"y\\\": [0,1,null]}\").read(\"$..[2][3]\");\n        assertThat(result).asList().containsOnly(3);\n    }\n\n    @Test\n    public void when_deep_scanning_array_index_oob_is_ignored() {\n        Object result = JsonPath.parse(\"{\\\"x\\\": [0,1,[0,1,2,3,10],null]}\").read(\"$..[4]\");\n        assertThat(result).asList().containsOnly(10);\n\n        result = JsonPath.parse(\"{\\\"x\\\": [null,null,[0,1,2,3]], \\\"y\\\": [null,null,[0,1]]}\").read(\"$..[2][3]\");\n        assertThat(result).asList().containsOnly(3);\n    }\n\n    @Test\n    public void definite_upstream_illegal_array_access_throws() {\n        assertEvaluationThrows(\"{\\\"foo\\\": {\\\"bar\\\": null}}\", \"$.foo.bar.[5]\", PathNotFoundException.class);\n        assertEvaluationThrows(\"{\\\"foo\\\": {\\\"bar\\\": null}}\", \"$.foo.bar.[5, 10]\", PathNotFoundException.class);\n\n        assertEvaluationThrows(\"{\\\"foo\\\": {\\\"bar\\\": 4}}\", \"$.foo.bar.[5]\", PathNotFoundException.class);\n        assertEvaluationThrows(\"{\\\"foo\\\": {\\\"bar\\\": 4}}\", \"$.foo.bar.[5, 10]\", PathNotFoundException.class);\n\n        assertEvaluationThrows(\"{\\\"foo\\\": {\\\"bar\\\": []}}\", \"$.foo.bar.[5]\", PathNotFoundException.class);\n    }\n\n    @Test\n    public void when_deep_scanning_illegal_property_access_is_ignored() {\n        Object result = JsonPath.parse(\"{\\\"x\\\": {\\\"foo\\\": {\\\"bar\\\": 4}}, \\\"y\\\": {\\\"foo\\\": 1}}\").read(\"$..foo\");\n        assertThat(result).asList().hasSize(2);\n\n        result = JsonPath.parse(\"{\\\"x\\\": {\\\"foo\\\": {\\\"bar\\\": 4}}, \\\"y\\\": {\\\"foo\\\": 1}}\").read(\"$..foo.bar\");\n        assertThat(result).asList().containsOnly(4);\n        result = JsonPath.parse(\"{\\\"x\\\": {\\\"foo\\\": {\\\"bar\\\": 4}}, \\\"y\\\": {\\\"foo\\\": 1}}\").read(\"$..[*].foo.bar\");\n        assertThat(result).asList().containsOnly(4);\n        result = JsonPath.parse(\"{\\\"x\\\": {\\\"foo\\\": {\\\"baz\\\": 4}}, \\\"y\\\": {\\\"foo\\\": 1}}\").read(\"$..[*].foo.bar\");\n        assertThat(result).asList().isEmpty();\n    }\n\n    @Test\n    public void when_deep_scanning_illegal_predicate_is_ignored() {\n        Object result = JsonPath.parse(\"{\\\"x\\\": {\\\"foo\\\": {\\\"bar\\\": 4}}, \\\"y\\\": {\\\"foo\\\": 1}}\").read(\n                \"$..foo[?(@.bar)].bar\");\n        assertThat(result).asList().containsOnly(4);\n\n        result = JsonPath.parse(\"{\\\"x\\\": {\\\"foo\\\": {\\\"bar\\\": 4}}, \\\"y\\\": {\\\"foo\\\": 1}}\").read(\n                \"$..[*]foo[?(@.bar)].bar\");\n        assertThat(result).asList().containsOnly(4);\n    }\n\n    @Test\n    public void when_deep_scanning_require_properties_is_ignored_on_scan_target() {\n        final Configuration conf = Configuration.defaultConfiguration().addOptions(Option.REQUIRE_PROPERTIES);\n\n        Object result = JsonPath.parse(\"[{\\\"x\\\": {\\\"foo\\\": {\\\"x\\\": 4}, \\\"x\\\": null}, \\\"y\\\": {\\\"x\\\": 1}}, {\\\"x\\\": []}]\").read(\n                \"$..x\");\n        assertThat(result).asList().hasSize(5);\n\n\n        List<Integer> result1 = JsonPath.using(conf).parse(\"{\\\"foo\\\": {\\\"bar\\\": 4}}\").read(\"$..foo.bar\");\n        assertThat(result1).containsExactly(4);\n\n        assertEvaluationThrows(\"{\\\"foo\\\": {\\\"baz\\\": 4}}\", \"$..foo.bar\", PathNotFoundException.class, conf);\n    }\n\n    @Test\n    public void when_deep_scanning_require_properties_is_ignored_on_scan_target_but_not_on_children() {\n        final Configuration conf = Configuration.defaultConfiguration().addOptions(Option.REQUIRE_PROPERTIES);\n\n        assertEvaluationThrows(\"{\\\"foo\\\": {\\\"baz\\\": 4}}\", \"$..foo.bar\", PathNotFoundException.class, conf);\n    }\n\n    @Test\n    public void when_deep_scanning_leaf_multi_props_work() {\n        Object result = JsonPath.parse(\"[{\\\"a\\\": \\\"a-val\\\", \\\"b\\\": \\\"b-val\\\", \\\"c\\\": \\\"c-val\\\"}, [1, 5], {\\\"a\\\": \\\"a-val\\\"}]\").read(\n                \"$..['a', 'c']\");\n        // This is current deep scan semantics: only objects containing all properties specified in multiprops token are\n        // considered.\n        assertThat(result).asList().hasSize(1);\n        result = ((List)result).get(0);\n\n        assertThat(result).isInstanceOf(Map.class);\n        assertThat((Map)result).hasSize(2).containsEntry(\"a\", \"a-val\").containsEntry(\"c\", \"c-val\");\n\n        // But this semantics changes when DEFAULT_PATH_LEAF_TO_NULL comes into play.\n        Configuration conf = Configuration.defaultConfiguration().addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL);\n        result = using(conf).parse(\"[{\\\"a\\\": \\\"a-val\\\", \\\"b\\\": \\\"b-val\\\", \\\"c\\\": \\\"c-val\\\"}, [1, 5], {\\\"a\\\": \\\"a-val\\\"}]\").read(\n                \"$..['a', 'c']\");\n        // todo: deep equality test, but not tied to any json provider\n        assertThat(result).asList().hasSize(2);\n        for (final Object node : (List)result) {\n            assertThat(node).isInstanceOf(Map.class);\n            assertThat((Map)node).hasSize(2).containsEntry(\"a\", \"a-val\");\n        }\n    }\n\n    @Test\n    public void require_single_property_ok() {\n\n        List json = new ArrayList() {{\n            add(singletonMap(\"a\", \"a0\"));\n            add(singletonMap(\"a\", \"a1\"));\n        }};\n\n        Configuration configuration = JSON_SMART_CONFIGURATION.addOptions(Option.REQUIRE_PROPERTIES);\n\n        Object result = JsonPath.using(configuration).parse(json).read(\"$..a\");\n\n        assertThat(result).asList().containsExactly(\"a0\",\"a1\");\n    }\n\n    @Test\n    public void require_single_property() {\n\n        List json = new ArrayList() {{\n            add(singletonMap(\"a\", \"a0\"));\n            add(singletonMap(\"b\", \"b2\"));\n        }};\n\n        Configuration configuration = JSON_SMART_CONFIGURATION.addOptions(Option.REQUIRE_PROPERTIES);\n\n        Object result = JsonPath.using(configuration).parse(json).read(\"$..a\");\n\n        assertThat(result).asList().containsExactly(\"a0\");\n    }\n\n    @Test\n    public void require_multi_property_all_match() {\n\n        final Map ab = new HashMap(){{\n            put(\"a\", \"aa\");\n            put(\"b\", \"bb\");\n        }};\n\n        List json = new ArrayList() {{\n            add(ab);\n            add(ab);\n        }};\n\n        Configuration configuration = JSON_SMART_CONFIGURATION.addOptions(Option.REQUIRE_PROPERTIES);\n\n        List<Map<String, String>> result = JsonPath.using(configuration).parse(json).read(\"$..['a', 'b']\");\n\n        assertThat(result).containsExactly(ab, ab);\n    }\n\n    @Test\n    public void require_multi_property_some_match() {\n\n        final Map ab = new HashMap(){{\n            put(\"a\", \"aa\");\n            put(\"b\", \"bb\");\n        }};\n\n        final Map ad = new HashMap(){{\n            put(\"a\", \"aa\");\n            put(\"d\", \"dd\");\n        }};\n\n        List json = new ArrayList() {{\n            add(ab);\n            add(ad);\n        }};\n\n        Configuration configuration = JSON_SMART_CONFIGURATION.addOptions(Option.REQUIRE_PROPERTIES);\n\n        List<Map<String, String>>  result = JsonPath.using(configuration).parse(json).read(\"$..['a', 'b']\");\n\n        assertThat(result).containsExactly(ab);\n    }\n\n    @Test\n    public void scan_for_single_property() {\n        final Map a = new HashMap(){{\n            put(\"a\", \"aa\");\n        }};\n        final Map b = new HashMap(){{\n            put(\"b\", \"bb\");\n        }};\n        final Map ab = new HashMap(){{\n            put(\"a\", a);\n            put(\"b\", b);\n        }};\n        final Map b_ab = new HashMap(){{\n            put(\"b\", b);\n            put(\"ab\", ab);\n        }};\n        List json = new ArrayList() {{\n            add(a);\n            add(b);\n            add(b_ab);\n        }};\n        assertThat(parse(json).read(\"$..['a']\", List.class)).containsExactly(\"aa\", a, \"aa\");\n    }\n\n    @Test\n    public void scan_for_property_path() {\n        final Map a = new HashMap(){{\n            put(\"a\", \"aa\");\n        }};\n        final Map x = new HashMap(){{\n            put(\"x\", \"xx\");\n        }};\n        final Map y = new HashMap(){{\n            put(\"a\", x);\n        }};\n        final Map z = new HashMap(){{\n            put(\"z\", y);\n        }};\n        List json = new ArrayList() {{\n            add(a);\n            add(x);\n            add(y);\n            add(z);\n        }};\n        assertThat(parse(json).read(\"$..['a'].x\", List.class)).containsExactly(\"xx\", \"xx\");\n    }\n\n    @Test\n    public void scan_for_property_path_missing_required_property() {\n        final Map a = new HashMap(){{\n            put(\"a\", \"aa\");\n        }};\n        final Map x = new HashMap(){{\n            put(\"x\", \"xx\");\n        }};\n        final Map y = new HashMap(){{\n            put(\"a\", x);\n        }};\n        final Map z = new HashMap(){{\n            put(\"z\", y);\n        }};\n        List json = new ArrayList() {{\n            add(a);\n            add(x);\n            add(y);\n            add(z);\n        }};\n        assertThat(using(JSON_SMART_CONFIGURATION.addOptions(Option.REQUIRE_PROPERTIES)).parse(json).read(\"$..['a'].x\", List.class)).containsExactly(\"xx\", \"xx\");\n    }\n\n\n    @Test\n    public void scans_can_be_filtered() {\n\n        final Map brown = singletonMap(\"val\", \"brown\");\n        final Map white = singletonMap(\"val\", \"white\");\n\n        final Map cow = new HashMap(){{\n            put(\"mammal\", true);\n            put(\"color\", brown);\n        }};\n        final Map dog = new HashMap(){{\n            put(\"mammal\", true);\n            put(\"color\", white);\n        }};\n        final Map frog = new HashMap(){{\n            put(\"mammal\", false);\n        }};\n        List animals = new ArrayList() {{\n            add(cow);\n            add(dog);\n            add(frog);\n        }};\n        assertThat(using(JSON_SMART_CONFIGURATION.addOptions(Option.REQUIRE_PROPERTIES)).parse(animals).read(\"$..[?(@.mammal == true)].color\", List.class)).containsExactly(brown, white);\n    }\n\n    @Test\n    public void scan_with_a_function_filter() {\n        List result = JsonPath.parse(JSON_DOCUMENT).read(\"$..*[?(@.length() > 5)]\");\n        assertThat(result).hasSize(1);\n    }\n\n    @Test\n    public void deepScanPathDefault() {\n        executeScanPath();\n    }\n\n    @Test\n    public void deepScanPathRequireProperties() {\n        executeScanPath(Option.REQUIRE_PROPERTIES);\n    }\n\n    private void executeScanPath(Option... options) {\n        String json = \"{'index': 'index', 'data': {'array': [{ 'object1': { 'name': 'robert'} }]}}\";\n        Map<String, Object> expected = new HashMap<String, Object>() {{\n            put(\"object1\", new HashMap<String, String>() {{\n                put(\"name\", \"robert\");\n            }});\n        }};\n\n        Configuration configuration = Configuration\n                .builder()\n                .options(options)\n                .build();\n\n        List<Map<String, Object>> result = JsonPath\n                .using(configuration)\n                .parse(json)\n                .read(\"$..array[0]\");\n        assertThat(result.get(0)).isEqualTo(expected);\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/EscapeTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport net.minidev.json.JSONStyle;\nimport net.minidev.json.JSONValue;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class EscapeTest extends BaseTest {\n\n    private static JSONStyle style;\n\n    @BeforeAll\n    public static void before(){\n        style = JSONValue.COMPRESSION;\n        JSONValue.COMPRESSION = JSONStyle.LT_COMPRESS;\n    }\n\n    @AfterAll\n    public static void after(){\n        JSONValue.COMPRESSION = style;\n    }\n\n    @Test\n    public void urls_are_not_escaped() {\n\n        JSONStyle orig = JSONValue.COMPRESSION;\n\n\n\n        String json = \"[\" +\n                \"\\\"https://a/b/1\\\",\" +\n                \"\\\"https://a/b/2\\\",\" +\n                \"\\\"https://a/b/3\\\"\" +\n                \"]\";\n\n        String resAsString = JsonPath.using(JSON_SMART_CONFIGURATION).parse(json).read(\"$\").toString();\n\n        assertThat(resAsString).contains(\"https://a/b/1\");\n\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/EvaluationListenerTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class EvaluationListenerTest extends BaseTest {\n\n\n    @Test\n    public void an_evaluation_listener_can_abort_after_one_result_using_fluent_api() {\n        EvaluationListener firstResultListener = new EvaluationListener() {\n            @Override\n            public EvaluationContinuation resultFound(FoundResult found) {\n                return EvaluationContinuation.ABORT;\n            }\n        };\n        List<String> title = JsonPath.parse(JSON_DOCUMENT).withListeners(firstResultListener).read(\"$..title\", List.class);\n        assertThat(title).containsExactly(\"Sayings of the Century\");\n    }\n\n    @Test\n    public void an_evaluation_listener_can_abort_after_one_result_using_configuration() {\n        EvaluationListener firstResultListener = new EvaluationListener() {\n            @Override\n            public EvaluationContinuation resultFound(FoundResult found) {\n                return EvaluationContinuation.ABORT;\n            }\n        };\n        Configuration configuration = Configuration.builder().evaluationListener(firstResultListener).build();\n\n        List<String> title = JsonPath.using(configuration).parse(JSON_DOCUMENT).read(\"$..title\", List.class);\n        assertThat(title).containsExactly(\"Sayings of the Century\");\n    }\n\n    @Test\n    public void an_evaluation_lister_can_continue() {\n\n        final List<Integer> idxs = new ArrayList<Integer>();\n\n        EvaluationListener firstResultListener = new EvaluationListener() {\n            @Override\n            public EvaluationContinuation resultFound(FoundResult found) {\n                idxs.add(found.index());\n                return EvaluationContinuation.CONTINUE;\n            }\n        };\n        List<String> title = JsonPath.parse(JSON_DOCUMENT).withListeners(firstResultListener).read(\"$..title\", List.class);\n        assertThat(title).containsExactly(\"Sayings of the Century\", \"Sword of Honour\", \"Moby Dick\", \"The Lord of the Rings\");\n        assertThat(idxs).containsExactly(0, 1, 2, 3);\n    }\n\n\n    @Test\n    public void evaluation_results_can_be_limited() {\n\n        List<String> res = JsonPath.parse(JSON_DOCUMENT).limit(1).read(\"$..title\", List.class);\n        assertThat(res).containsExactly(\"Sayings of the Century\");\n\n        res = JsonPath.parse(JSON_DOCUMENT).limit(2).read(\"$..title\", List.class);\n        assertThat(res).containsExactly(\"Sayings of the Century\", \"Sword of Honour\");\n    }\n\n    @Test\n    public void multiple_evaluation_listeners_can_be_added() {\n\n        final List<Integer> idxs1 = new ArrayList<Integer>();\n        final List<Integer> idxs2 = new ArrayList<Integer>();\n\n        EvaluationListener listener1 = new EvaluationListener() {\n            @Override\n            public EvaluationContinuation resultFound(FoundResult found) {\n                idxs1.add(found.index());\n                return EvaluationContinuation.CONTINUE;\n            }\n        };\n\n        EvaluationListener listener2 = new EvaluationListener() {\n            @Override\n            public EvaluationContinuation resultFound(FoundResult found) {\n                idxs2.add(found.index());\n                return EvaluationContinuation.CONTINUE;\n            }\n        };\n\n        List<String> title = JsonPath.parse(JSON_DOCUMENT).withListeners(listener1, listener2).read(\"$..title\", List.class);\n        assertThat(title).containsExactly(\"Sayings of the Century\", \"Sword of Honour\", \"Moby Dick\", \"The Lord of the Rings\");\n        assertThat(idxs1).containsExactly(0, 1, 2, 3);\n        assertThat(idxs2).containsExactly(0, 1, 2, 3);\n    }\n\n    @Test\n    public void evaluation_listeners_can_be_cleared() {\n\n        EvaluationListener listener = new EvaluationListener() {\n            @Override\n            public EvaluationContinuation resultFound(FoundResult found) {\n                return EvaluationContinuation.CONTINUE;\n            }\n        };\n\n        Configuration configuration1 = Configuration.builder().evaluationListener(listener).build();\n        Configuration configuration2 = configuration1.setEvaluationListeners();\n\n        assertThat(configuration1.getEvaluationListeners()).hasSize(1);\n        assertThat(configuration2.getEvaluationListeners()).hasSize(0);\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/FilterCompilerTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport static com.jayway.jsonpath.internal.filter.FilterCompiler.compile;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\npublic class FilterCompilerTest {\n\n    @Test\n    public void valid_filters_compile() {\n        assertThat(compile(\"[?(@)]\").toString()).isEqualTo(\"[?(@)]\");\n        assertThat(compile(\"[?(@)]\").toString()).isEqualTo(\"[?(@)]\");\n        assertThat(compile(\"[?(@.firstname)]\").toString()).isEqualTo(\"[?(@['firstname'])]\");\n        assertThat(compile(\"[?($.firstname)]\").toString()).isEqualTo(\"[?($['firstname'])]\");\n        assertThat(compile(\"[?(@['firstname'])]\").toString()).isEqualTo(\"[?(@['firstname'])]\");\n        assertThat(compile(\"[?($['firstname'].lastname)]\").toString()).isEqualTo(\"[?($['firstname']['lastname'])]\");\n        assertThat(compile(\"[?($['firstname']['lastname'])]\").toString()).isEqualTo(\"[?($['firstname']['lastname'])]\");\n        assertThat(compile(\"[?($['firstname']['lastname'].*)]\").toString()).isEqualTo(\"[?($['firstname']['lastname'][*])]\");\n        assertThat(compile(\"[?($['firstname']['num_eq'] == 1)]\").toString()).isEqualTo(\"[?($['firstname']['num_eq'] == 1)]\");\n        assertThat(compile(\"[?($['firstname']['num_gt'] > 1.1)]\").toString()).isEqualTo(\"[?($['firstname']['num_gt'] > 1.1)]\");\n        assertThat(compile(\"[?($['firstname']['num_lt'] < 11.11)]\").toString()).isEqualTo(\"[?($['firstname']['num_lt'] < 11.11)]\");\n        assertThat(compile(\"[?($['firstname']['str_eq'] == 'hej')]\").toString()).isEqualTo(\"[?($['firstname']['str_eq'] == 'hej')]\");\n        assertThat(compile(\"[?($['firstname']['str_eq'] == '')]\").toString()).isEqualTo(\"[?($['firstname']['str_eq'] == '')]\");\n        assertThat(compile(\"[?($['firstname']['str_eq'] == null)]\").toString()).isEqualTo(\"[?($['firstname']['str_eq'] == null)]\");\n        assertThat(compile(\"[?($['firstname']['str_eq'] == true)]\").toString()).isEqualTo(\"[?($['firstname']['str_eq'] == true)]\");\n        assertThat(compile(\"[?($['firstname']['str_eq'] == false)]\").toString()).isEqualTo(\"[?($['firstname']['str_eq'] == false)]\");\n        assertThat(compile(\"[?(@.firstname && @.lastname)]\").toString()).isEqualTo(\"[?(@['firstname'] && @['lastname'])]\");\n        assertThat(compile(\"[?((@.firstname || @.lastname) && @.and)]\").toString()).isEqualTo(\"[?((@['firstname'] || @['lastname']) && @['and'])]\");\n        assertThat(compile(\"[?((@.a || @.b || @.c) && @.x)]\").toString()).isEqualTo(\"[?((@['a'] || @['b'] || @['c']) && @['x'])]\");\n        assertThat(compile(\"[?((@.a && @.b && @.c) || @.x)]\").toString()).isEqualTo(\"[?((@['a'] && @['b'] && @['c']) || @['x'])]\");\n        assertThat(compile(\"[?((@.a && @.b || @.c) || @.x)]\").toString()).isEqualTo(\"[?(((@['a'] && @['b']) || @['c']) || @['x'])]\");\n        assertThat(compile(\"[?((@.a && @.b) || (@.c && @.d))]\").toString()).isEqualTo(\"[?((@['a'] && @['b']) || (@['c'] && @['d']))]\");\n        assertThat(compile(\"[?(@.a IN [1,2,3])]\").toString()).isEqualTo(\"[?(@['a'] IN [1,2,3])]\");\n        assertThat(compile(\"[?(@.a IN {'foo':'bar'})]\").toString()).isEqualTo(\"[?(@['a'] IN {'foo':'bar'})]\");\n        assertThat(compile(\"[?(@.value<'7')]\").toString()).isEqualTo(\"[?(@['value'] < '7')]\");\n        assertThat(compile(\"[?(@.message == 'it\\\\\\\\')]\").toString()).isEqualTo(\"[?(@['message'] == 'it\\\\\\\\')]\");\n        assertThat(compile(\"[?(@.message.min() > 10)]\").toString()).isEqualTo(\"[?(@['message'].min() > 10)]\");\n        assertThat(compile(\"[?(@.message.min()==10)]\").toString()).isEqualTo(\"[?(@['message'].min() == 10)]\");\n        assertThat(compile(\"[?(10 == @.message.min())]\").toString()).isEqualTo(\"[?(10 == @['message'].min())]\");\n        assertThat(compile(\"[?(((@)))]\").toString()).isEqualTo(\"[?(@)]\");\n        assertThat(compile(\"[?(@.name =~ /.*?/i)]\").toString()).isEqualTo(\"[?(@['name'] =~ /.*?/i)]\");\n        assertThat(compile(\"[?(@.name =~ /.*?/)]\").toString()).isEqualTo(\"[?(@['name'] =~ /.*?/)]\");\n        assertThat(compile(\"[?($[\\\"firstname\\\"][\\\"lastname\\\"])]\").toString()).isEqualTo(\"[?($[\\\"firstname\\\"][\\\"lastname\\\"])]\");\n        assertThat(compile(\"[?($[\\\"firstname\\\"].lastname)]\").toString()).isEqualTo(\"[?($[\\\"firstname\\\"]['lastname'])]\");\n        assertThat(compile(\"[?($[\\\"firstname\\\", \\\"lastname\\\"])]\").toString()).isEqualTo(\"[?($[\\\"firstname\\\",\\\"lastname\\\"])]\");\n        assertThat(compile(\"[?(((@.a && @.b || @.c)) || @.x)]\").toString()).isEqualTo(\"[?(((@['a'] && @['b']) || @['c']) || @['x'])]\");\n\n    }\n\n    @Test\n    public void string_quote_style_is_serialized() {\n        assertThat(compile(\"[?('apa' == 'apa')]\").toString()).isEqualTo(\"[?('apa' == 'apa')]\");\n        assertThat(compile(\"[?('apa' == \\\"apa\\\")]\").toString()).isEqualTo(\"[?('apa' == \\\"apa\\\")]\");\n    }\n\n    @Test\n    public void string_can_contain_path_chars() {\n        assertThat(compile(\"[?(@[')]@$)]'] == ')]@$)]')]\").toString()).isEqualTo(\"[?(@[')]@$)]'] == ')]@$)]')]\");\n        assertThat(compile(\"[?(@[\\\")]@$)]\\\"] == \\\")]@$)]\\\")]\").toString()).isEqualTo(\"[?(@[\\\")]@$)]\\\"] == \\\")]@$)]\\\")]\");\n    }\n\n    @Test\n    public void invalid_path_when_string_literal_is_unquoted() {\n        assertThrows(InvalidPathException.class, () -> compile(\"[?(@.foo == x)]\"));\n    }\n\n    @Test\n    public void or_has_lower_priority_than_and() {\n        assertThat(compile(\"[?(@.category == 'fiction' && @.author == 'Evelyn Waugh' || @.price > 15)]\").toString())\n                .isEqualTo(\"[?((@['category'] == 'fiction' && @['author'] == 'Evelyn Waugh') || @['price'] > 15)]\");\n    }\n\n    @Test\n    public void invalid_filters_does_not_compile() {\n        assertInvalidPathException(\"[?(@))]\");\n        assertInvalidPathException(\"[?(@ FOO 1)]\");\n        assertInvalidPathException(\"[?(@ || )]\");\n        assertInvalidPathException(\"[?(@ == 'foo )]\");\n        assertInvalidPathException(\"[?(@ == 1' )]\");\n        assertInvalidPathException(\"[?(@.foo bar == 1)]\");\n        assertInvalidPathException(\"[?(@.i == 5 @.i == 8)]\");\n        assertInvalidPathException(\"[?(!5)]\");\n        assertInvalidPathException(\"[?(!'foo')]\");\n    }\n\n    @Test\n    // issue #178\n    public void compile_and_serialize_not_exists_filter() {\n        Filter compiled = compile(\"[?(!@.foo)]\");\n        String serialized = compiled.toString();\n        assertThat(serialized).isEqualTo(\"[?(!@['foo'])]\");\n    }\n\n\n    private void assertInvalidPathException(String filter) {\n        try {\n            compile(filter);\n            throw new AssertionError(\"Expected \" + filter + \" to throw InvalidPathException\");\n        } catch (InvalidPathException e) {\n            //e.printStackTrace();\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/FilterParseTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.regex.Pattern;\n\nimport static com.jayway.jsonpath.Criteria.where;\nimport static com.jayway.jsonpath.Filter.filter;\nimport static com.jayway.jsonpath.Filter.parse;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class FilterParseTest {\n\n    @Test\n    public void a_filter_can_be_parsed() {\n\n        parse(\"[?(@.foo)]\");\n        parse(\"[?(@.foo == 1)]\");\n        parse(\"[?(@.foo == 1 || @['bar'])]\");\n        parse(\"[?(@.foo == 1 && @['bar'])]\");\n    }\n\n    @Test\n    public void an_invalid_filter_can_not_be_parsed() {\n        try {\n            parse(\"[?(@.foo == 1)\");\n            Assertions.fail(\"expected \" + InvalidPathException.class.getName());\n        } catch (InvalidPathException ipe){}\n\n        try {\n            parse(\"[?(@.foo == 1) ||]\");\n            Assertions.fail(\"expected \" + InvalidPathException.class.getName());\n        } catch (InvalidPathException ipe){}\n\n        try {\n            parse(\"[(@.foo == 1)]\");\n            Assertions.fail(\"expected \" + InvalidPathException.class.getName());\n        } catch (InvalidPathException ipe){}\n\n        try {\n            parse(\"[?@.foo == 1)]\");\n            Assertions.fail(\"expected \" + InvalidPathException.class.getName());\n        } catch (InvalidPathException ipe){}\n    }\n\n\n    @Test\n    public void a_gte_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").gte(1)).toString();\n        String parsed = parse(\"[?(@['a'] >= 1)]\").toString();\n\n        assertThat(filter).isEqualTo(parse(parsed).toString());\n    }\n\n    @Test\n    public void a_lte_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").lte(1)).toString();\n        String parsed = parse(\"[?(@['a'] <= 1)]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_eq_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").eq(1)).toString();\n        String parsed = parse(\"[?(@['a'] == 1)]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_ne_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").ne(1)).toString();\n        String parsed = parse(\"[?(@['a'] != 1)]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_lt_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").lt(1)).toString();\n        String parsed = parse(\"[?(@['a'] < 1)]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_gt_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").gt(1)).toString();\n        String parsed = parse(\"[?(@['a'] > 1)]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_nin_filter_can_be_serialized() {\n        String filter = filter(where(\"a\").nin(1)).toString();\n        String parsed = parse(\"[?(@['a'] NIN [1])]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_in_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").in(\"a\")).toString();\n        String parsed = parse(\"[?(@['a'] IN ['a'])]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_contains_filter_can_be_serialized() {\n        String filter = filter(where(\"a\").contains(\"a\")).toString();\n        String parsed = parse(\"[?(@['a'] CONTAINS 'a')]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_all_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").all(\"a\", \"b\")).toString();\n        String parsed = parse(\"[?(@['a'] ALL ['a','b'])]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_size_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").size(5)).toString();\n        String parsed = parse(\"[?(@['a'] SIZE 5)]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_subsetof_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").subsetof(Collections.emptyList())).toString();\n        String parsed = parse(\"[?(@['a'] SUBSETOF [])]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_anyof_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").anyof(Collections.emptyList())).toString();\n        String parsed = parse(\"[?(@['a'] ANYOF [])]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_noneof_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").noneof(Collections.emptyList())).toString();\n        String parsed = parse(\"[?(@['a'] NONEOF [])]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_exists_filter_can_be_serialized() {\n\n        Filter a = filter(where(\"a\").exists(true));\n        String filter = a.toString();\n        String parsed = parse(\"[?(@['a'])]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_not_exists_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").exists(false)).toString();\n        String parsed = parse(\"[?(!@['a'])]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_type_filter_can_be_serialized() {\n        assertThat(filter(where(\"a\").type(String.class)).toString()).isEqualTo(\"[?(@['a'] TYPE java.lang.String)]\");\n    }\n\n    @Test\n    public void a_matches_filter_can_be_serialized() {\n        Filter a = filter(where(\"x\").eq(1000));\n\n        assertThat(filter(where(\"a\").matches(a)).toString()).isEqualTo(\"[?(@['a'] MATCHES [?(@['x'] == 1000)])]\");\n    }\n\n    @Test\n    public void a_not_empty_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").empty(false)).toString();\n        String parsed = parse(\"[?(@['a'] EMPTY false)]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void and_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").eq(1).and(\"b\").eq(2)).toString();\n        String parsed = parse(\"[?(@['a'] == 1 && @['b'] == 2)]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void in_string_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a\").in(\"1\",\"2\")).toString();\n        String parsed = parse(\"[?(@['a'] IN ['1','2'])]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_deep_path_filter_can_be_serialized() {\n\n        String filter = filter(where(\"a.b.c\").in(\"1\", \"2\")).toString();\n        String parsed = parse(\"[?(@['a']['b']['c'] IN ['1','2'])]\").toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void a_regex_filter_can_be_serialized() {\n        assertThat(filter(where(\"a\").regex(Pattern.compile(\"/.*?/i\"))).toString()).isEqualTo(\"[?(@['a'] =~ /.*?/i)]\");\n    }\n\n    @Test\n    public void a_doc_ref_filter_can_be_serialized() {\n        Filter f = parse(\"[?(@.display-price <= $.max-price)]\");\n        assertThat(f.toString()).isEqualTo(\"[?(@['display-price'] <= $['max-price'])]\");\n    }\n\n    @Test\n    public void and_combined_filters_can_be_serialized() {\n\n        Filter a = filter(where(\"a\").eq(1));\n        Filter b = filter(where(\"b\").eq(2));\n        Filter c = a.and(b);\n\n        String filter = c.toString();\n        String parsed = parse(\"[?(@['a'] == 1 && @['b'] == 2)]\").toString();\n\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n\n    @Test\n    public void or_combined_filters_can_be_serialized() {\n\n        Filter a = filter(where(\"a\").eq(1));\n        Filter b = filter(where(\"b\").eq(2));\n        Filter c = a.or(b);\n\n        String filter = c.toString();\n        Filter d = parse(\"[?(@['a'] == 1 || @['b'] == 2)]\");\n        String parsed = d.toString();\n\n        assertThat(filter).isEqualTo(parsed);\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/FilterTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.assertj.core.util.Lists;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.regex.Pattern;\n\nimport static com.jayway.jsonpath.Criteria.where;\nimport static com.jayway.jsonpath.Filter.filter;\nimport static com.jayway.jsonpath.Filter.parse;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class FilterTest extends BaseTest {\n\n\n    Object json = Configuration.defaultConfiguration().jsonProvider().parse(\n            \"{\" +\n            \"  \\\"int-key\\\" : 1, \" +\n            \"  \\\"long-key\\\" : 3000000000, \" +\n            \"  \\\"double-key\\\" : 10.1, \" +\n            \"  \\\"boolean-key\\\" : true, \" +\n            \"  \\\"null-key\\\" : null, \" +\n            \"  \\\"string-key\\\" : \\\"string\\\", \" +\n            \"  \\\"string-key-empty\\\" : \\\"\\\", \" +\n            \"  \\\"char-key\\\" : \\\"c\\\", \" +\n            \"  \\\"arr-empty\\\" : [], \" +\n            \"  \\\"int-arr\\\" : [0,1,2,3,4], \" +\n            \"  \\\"string-arr\\\" : [\\\"a\\\",\\\"b\\\",\\\"c\\\",\\\"d\\\",\\\"e\\\"], \" +\n            \"  \\\"obj\\\": {\\\"foo\\\": \\\"bar\\\"}\" +\n            \"}\"\n    );\n\n    //----------------------------------------------------------------------------\n    //\n    // EQ\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void int_eq_evals() {\n        assertThat(filter(where(\"int-key\").eq(1)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"int-key\").eq(666)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void int_eq_string_evals() {\n        assertThat(filter(where(\"int-key\").eq(\"1\")).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"int-key\").eq(\"666\")).apply(createPredicateContext(json))).isEqualTo(false);\n\n\n        assertThat(Filter.parse(\"[?(1 == '1')]\").apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(Filter.parse(\"[?('1' == 1)]\").apply(createPredicateContext(json))).isEqualTo(true);\n\n        assertThat(Filter.parse(\"[?(1 === '1')]\").apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(Filter.parse(\"[?('1' === 1)]\").apply(createPredicateContext(json))).isEqualTo(false);\n\n        assertThat(Filter.parse(\"[?(1 === 1)]\").apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    @Test\n    public void long_eq_evals() {\n        assertThat(filter(where(\"long-key\").eq(3000000000L)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"long-key\").eq(666L)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void double_eq_evals() {\n        assertThat(filter(where(\"double-key\").eq(10.1D)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"double-key\").eq(10.10D)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"double-key\").eq(10.11D)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void string_eq_evals() {\n        assertThat(filter(where(\"string-key\").eq(\"string\")).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-key\").eq(\"666\")).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void boolean_eq_evals() {\n        assertThat(filter(where(\"boolean-key\").eq(true)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"boolean-key\").eq(false)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void null_eq_evals() {\n        assertThat(filter(where(\"null-key\").eq(null)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"null-key\").eq(\"666\")).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"string-key\").eq(null)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void arr_eq_evals() {\n        assertThat(filter(where(\"arr-empty\").eq(\"[]\")).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"int-arr\").eq(\"[0,1,2,3,4]\")).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"int-arr\").eq(\"[0,1,2,3]\")).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"int-arr\").eq(\"[0,1,2,3,4,5]\")).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n    //----------------------------------------------------------------------------\n    //\n    // NE\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void int_ne_evals() {\n        assertThat(filter(where(\"int-key\").ne(1)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"int-key\").ne(666)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    @Test\n    public void long_ne_evals() {\n        assertThat(filter(where(\"long-key\").ne(3000000000L)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"long-key\").ne(666L)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    @Test\n    public void double_ne_evals() {\n        assertThat(filter(where(\"double-key\").ne(10.1D)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"double-key\").ne(10.10D)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"double-key\").ne(10.11D)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    @Test\n    public void string_ne_evals() {\n        assertThat(filter(where(\"string-key\").ne(\"string\")).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"string-key\").ne(\"666\")).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    @Test\n    public void boolean_ne_evals() {\n        assertThat(filter(where(\"boolean-key\").ne(true)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"boolean-key\").ne(false)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    @Test\n    public void null_ne_evals() {\n        assertThat(filter(where(\"null-key\").ne(null)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"null-key\").ne(\"666\")).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-key\").ne(null)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // LT\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void int_lt_evals() {\n        assertThat(filter(where(\"int-key\").lt(10)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"int-key\").lt(0)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void long_lt_evals() {\n        assertThat(filter(where(\"long-key\").lt(4000000000L)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"long-key\").lt(666L)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void double_lt_evals() {\n        assertThat(filter(where(\"double-key\").lt(100.1D)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"double-key\").lt(1.1D)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void string_lt_evals() {\n        assertThat(filter(where(\"char-key\").lt(\"x\")).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"char-key\").lt(\"a\")).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // LTE\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void int_lte_evals() {\n        assertThat(filter(where(\"int-key\").lte(10)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"int-key\").lte(1)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"int-key\").lte(0)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void long_lte_evals() {\n        assertThat(filter(where(\"long-key\").lte(4000000000L)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"long-key\").lte(3000000000L)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"long-key\").lte(666L)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void double_lte_evals() {\n        assertThat(filter(where(\"double-key\").lte(100.1D)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"double-key\").lte(10.1D)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"double-key\").lte(1.1D)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // GT\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void int_gt_evals() {\n        assertThat(filter(where(\"int-key\").gt(10)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"int-key\").gt(0)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    @Test\n    public void long_gt_evals() {\n        assertThat(filter(where(\"long-key\").gt(4000000000L)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"long-key\").gt(666L)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    @Test\n    public void double_gt_evals() {\n        assertThat(filter(where(\"double-key\").gt(100.1D)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"double-key\").gt(1.1D)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    @Test\n    public void string_gt_evals() {\n        assertThat(filter(where(\"char-key\").gt(\"x\")).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"char-key\").gt(\"a\")).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // GTE\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void int_gte_evals() {\n        assertThat(filter(where(\"int-key\").gte(10)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"int-key\").gte(1)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"int-key\").gte(0)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    @Test\n    public void long_gte_evals() {\n        assertThat(filter(where(\"long-key\").gte(4000000000L)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"long-key\").gte(3000000000L)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"long-key\").gte(666L)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    @Test\n    public void double_gte_evals() {\n        assertThat(filter(where(\"double-key\").gte(100.1D)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"double-key\").gte(10.1D)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"double-key\").gte(1.1D)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // Regex\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void string_regex_evals() {\n        assertThat(filter(where(\"string-key\").regex(Pattern.compile(\"^string$\"))).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-key\").regex(Pattern.compile(\"^tring$\"))).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"null-key\").regex(Pattern.compile(\"^string$\"))).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"int-key\").regex(Pattern.compile(\"^string$\"))).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void list_regex_evals() {\n        assertThat(filter(where(\"string-arr\").regex(Pattern.compile(\"^d$\"))).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-arr\").regex(Pattern.compile(\"^q$\"))).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void obj_regex_doesnt_break() {\n        assertThat(filter(where(\"obj\").regex(Pattern.compile(\"^foo$\"))).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // JSON equality\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void json_evals() {\n        String nest = \"{\\\"a\\\":true}\";\n        String arr = \"[1,2]\";\n        String json = \"{\\\"foo\\\":\" + arr + \", \\\"bar\\\":\" + nest + \"}\";\n        Object tree = Configuration.defaultConfiguration().jsonProvider().parse(json);\n        Predicate.PredicateContext context = createPredicateContext(tree);\n        Filter farr = parse(\"[?(@.foo == \" + arr + \")]\");\n        //Filter fobjF = parse(\"[?(@.foo == \" + nest + \")]\");\n        //Filter fobjT = parse(\"[?(@.bar == \" + nest + \")]\");\n        boolean apply = farr.apply(context);\n        assertThat(apply).isEqualTo(true);\n        //assertThat(fobjF.apply(context)).isEqualTo(false);\n        //assertThat(fobjT.apply(context)).isEqualTo(true);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // IN\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void string_in_evals() {\n        assertThat(filter(where(\"string-key\").in(\"a\", null, \"string\")).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-key\").in(\"a\", null)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"null-key\").in(\"a\", null)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"null-key\").in(\"a\", \"b\")).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"string-arr\").in(\"a\")).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // NIN\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void string_nin_evals() {\n        assertThat(filter(where(\"string-key\").nin(\"a\", null, \"string\")).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"string-key\").nin(\"a\", null)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"null-key\").nin(\"a\", null)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"null-key\").nin(\"a\", \"b\")).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-arr\").nin(\"a\")).apply(createPredicateContext(json))).isEqualTo(true);\n\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // ALL\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void int_all_evals() {\n        assertThat(filter(where(\"int-arr\").all(0,1)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"int-arr\").all(0,7)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n    @Test\n    public void string_all_evals() {\n        assertThat(filter(where(\"string-arr\").all(\"a\",\"b\")).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-arr\").all(\"a\",\"x\")).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n    @Test\n    public void not_array_all_evals() {\n        assertThat(filter(where(\"string-key\").all(\"a\",\"b\")).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // SIZE\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void array_size_evals() {\n        assertThat(filter(where(\"string-arr\").size(5)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-arr\").size(7)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void string_size_evals() {\n        assertThat(filter(where(\"string-key\").size(6)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-key\").size(7)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void other_size_evals() {\n        assertThat(filter(where(\"int-key\").size(6)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    @Test\n    public void null_size_evals() {\n        assertThat(filter(where(\"null-key\").size(6)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // SUBSETOF\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void array_subsetof_evals() {\n        // list is a superset\n        List<String> list = Lists.newArrayList(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\");\n        assertThat(filter(where(\"string-arr\").subsetof(list)).apply(createPredicateContext(json))).isEqualTo(true);\n        // list is exactly the same set (but in a different order)\n        list = Lists.newArrayList(\"e\", \"d\", \"b\", \"c\", \"a\");\n        assertThat(filter(where(\"string-arr\").subsetof(list)).apply(createPredicateContext(json))).isEqualTo(true);\n        // list is missing one element\n        list = Lists.newArrayList(\"a\", \"b\", \"c\", \"d\");\n        assertThat(filter(where(\"string-arr\").subsetof(list)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // ANYOF\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void array_anyof_evals() {\n        List<String> list = Lists.newArrayList(\"a\", \"z\");\n        assertThat(filter(where(\"string-arr\").anyof(list)).apply(createPredicateContext(json))).isEqualTo(true);\n        list = Lists.newArrayList(\"z\", \"b\", \"a\");\n        assertThat(filter(where(\"string-arr\").anyof(list)).apply(createPredicateContext(json))).isEqualTo(true);\n        list = Lists.newArrayList(\"x\", \"y\", \"z\");\n        assertThat(filter(where(\"string-arr\").anyof(list)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // NONEOF\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void array_noneof_evals() {\n        List<String> list = Lists.newArrayList(\"a\", \"z\");\n        assertThat(filter(where(\"string-arr\").noneof(list)).apply(createPredicateContext(json))).isEqualTo(false);\n        list = Lists.newArrayList(\"z\", \"b\", \"a\");\n        assertThat(filter(where(\"string-arr\").noneof(list)).apply(createPredicateContext(json))).isEqualTo(false);\n        list = Lists.newArrayList(\"x\", \"y\", \"z\");\n        assertThat(filter(where(\"string-arr\").noneof(list)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // EXISTS\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void exists_evals() {\n        assertThat(filter(where(\"string-key\").exists(true)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-key\").exists(false)).apply(createPredicateContext(json))).isEqualTo(false);\n\n        assertThat(filter(where(\"missing-key\").exists(true)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"missing-key\").exists(false)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // TYPE\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void type_evals() {\n        assertThat(filter(where(\"string-key\").type(String.class)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-key\").type(Number.class)).apply(createPredicateContext(json))).isEqualTo(false);\n\n        assertThat(filter(where(\"int-key\").type(String.class)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"int-key\").type(Number.class)).apply(createPredicateContext(json))).isEqualTo(true);\n\n        assertThat(filter(where(\"null-key\").type(String.class)).apply(createPredicateContext(json))).isEqualTo(false);\n\n        assertThat(filter(where(\"int-arr\").type(List.class)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // NOT EMPTY\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void not_empty_evals() {\n        assertThat(filter(where(\"string-key\").empty(false)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-key-empty\").empty(false)).apply(createPredicateContext(json))).isEqualTo(false);\n\n        assertThat(filter(where(\"int-arr\").empty(false)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"arr-empty\").empty(false)).apply(createPredicateContext(json))).isEqualTo(false);\n\n        assertThat(filter(where(\"null-key\").empty(false)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // EMPTY\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void empty_evals() {\n        assertThat(filter(where(\"string-key\").empty(false)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-key\").empty(true)).apply(createPredicateContext(json))).isEqualTo(false);\n\n        assertThat(filter(where(\"string-key-empty\").empty(true)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"string-key-empty\").empty(false)).apply(createPredicateContext(json))).isEqualTo(false);\n\n        assertThat(filter(where(\"int-arr\").empty(false)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"int-arr\").empty(true)).apply(createPredicateContext(json))).isEqualTo(false);\n\n        assertThat(filter(where(\"arr-empty\").empty(true)).apply(createPredicateContext(json))).isEqualTo(true);\n        assertThat(filter(where(\"arr-empty\").empty(false)).apply(createPredicateContext(json))).isEqualTo(false);\n\n        assertThat(filter(where(\"null-key\").empty(true)).apply(createPredicateContext(json))).isEqualTo(false);\n        assertThat(filter(where(\"null-key\").empty(false)).apply(createPredicateContext(json))).isEqualTo(false);\n    }\n\n\n    //----------------------------------------------------------------------------\n    //\n    // MATCHES\n    //\n    //----------------------------------------------------------------------------\n\n    @Test\n    public void matches_evals() {\n        Predicate p = new Predicate() {\n            @Override\n            public boolean apply(PredicateContext ctx) {\n                Map<String, Object> t = (Map<String, Object>) ctx.item();\n\n                Object o = t.get(\"int-key\");\n\n                Integer i = (Integer) o;\n\n                return i == 1;\n            }\n        };\n        assertThat(filter(where(\"string-key\").eq(\"string\").and(\"$\").matches(p)).apply(createPredicateContext(json))).isEqualTo(true);\n    }\n\n    //----------------------------------------------------------------------------\n    //\n    // OR\n    //\n    //----------------------------------------------------------------------------\n    @Test\n    public void or_and_filters_evaluates() {\n\n        Map<String, Object> model = new HashMap<String, Object>();\n        model.put(\"foo\", true);\n        model.put(\"bar\", false);\n\n        Filter isFoo = filter(where(\"foo\").is(true));\n        Filter isBar = filter(where(\"bar\").is(true));\n\n\n        Filter fooOrBar = filter(where(\"foo\").is(true)).or(where(\"bar\").is(true));\n        Filter fooAndBar = filter(where(\"foo\").is(true)).and(where(\"bar\").is(true));\n\n        assertThat(isFoo.or(isBar).apply(createPredicateContext(model))).isTrue();\n        assertThat(isFoo.and(isBar).apply(createPredicateContext(model))).isFalse();\n        assertThat(fooOrBar.apply(createPredicateContext(model))).isTrue();\n        assertThat(fooAndBar.apply(createPredicateContext(model))).isFalse();\n\n    }\n\n\n    @Test\n    public void testFilterWithOrShortCircuit1() throws Exception {\n        Object json = Configuration.defaultConfiguration().jsonProvider().parse( \"{\\\"firstname\\\":\\\"Bob\\\",\\\"surname\\\":\\\"Smith\\\",\\\"age\\\":30}\");\n        assertThat(Filter.parse(\"[?((@.firstname == 'Bob' || @.firstname == 'Jane') && @.surname == 'Doe')]\").apply(createPredicateContext(json))).isFalse();\n    }\n\n    @Test\n    public void testFilterWithOrShortCircuit2() throws Exception {\n        Object json = Configuration.defaultConfiguration().jsonProvider().parse(\"{\\\"firstname\\\":\\\"Bob\\\",\\\"surname\\\":\\\"Smith\\\",\\\"age\\\":30}\");\n        assertThat(Filter.parse(\"[?((@.firstname == 'Bob' || @.firstname == 'Jane') && @.surname == 'Smith')]\").apply(createPredicateContext(json))).isTrue();\n    }\n\n    @Test\n    public void criteria_can_be_parsed() {\n\n        Filter criteria = Filter.parse(\"[?(@.foo == 'baar')]\");\n        assertThat(criteria.toString()).isEqualTo(\"[?(@['foo'] == 'baar')]\");\n\n        criteria = Filter.parse(\"[?(@.foo)]\");\n        assertThat(criteria.toString()).isEqualTo(\"[?(@['foo'])]\");\n    }\n\n\n    @Test\n    public void inline_in_criteria_evaluates() {\n        List list = JsonPath.read(JSON_DOCUMENT, \"$.store.book[?(@.category in ['reference', 'fiction'])]\");\n        assertThat(list).hasSize(4);\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/GsonJsonProviderTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport com.jayway.jsonpath.spi.json.GsonJsonProvider;\nimport com.jayway.jsonpath.spi.mapper.GsonMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.MappingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\npublic class GsonJsonProviderTest extends BaseTest {\n\n    private static final String JSON =\n            \"[\" +\n                    \"{\\n\" +\n                    \"   \\\"foo\\\" : \\\"foo0\\\",\\n\" +\n                    \"   \\\"bar\\\" : 0,\\n\" +\n                    \"   \\\"baz\\\" : true,\\n\" +\n                    \"   \\\"gen\\\" : {\\\"eric\\\" : \\\"yepp\\\"}\" +\n                    \"},\" +\n                    \"{\\n\" +\n                    \"   \\\"foo\\\" : \\\"foo1\\\",\\n\" +\n                    \"   \\\"bar\\\" : 1,\\n\" +\n                    \"   \\\"baz\\\" : true,\\n\" +\n                    \"   \\\"gen\\\" : {\\\"eric\\\" : \\\"yepp\\\"}\" +\n                    \"},\" +\n                    \"{\\n\" +\n                    \"   \\\"foo\\\" : \\\"foo2\\\",\\n\" +\n                    \"   \\\"bar\\\" : 2,\\n\" +\n                    \"   \\\"baz\\\" : true,\\n\" +\n                    \"   \\\"gen\\\" : {\\\"eric\\\" : \\\"yepp\\\"}\" +\n                    \"}\" +\n                    \"]\";\n\n    @Test\n    public void json_can_be_parsed() {\n        JsonObject node = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$\");\n        assertThat(node.get(\"string-property\").getAsString()).isEqualTo(\"string-value\");\n    }\n\n    @Test\n    public void strings_are_unwrapped() {\n        JsonElement node = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.string-property\");\n        String unwrapped = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.string-property\", String.class);\n\n        assertThat(unwrapped).isEqualTo(\"string-value\");\n        assertThat(unwrapped).isEqualTo(node.getAsString());\n    }\n\n    @Test\n    public void ints_are_unwrapped() {\n        JsonElement node = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.int-max-property\");\n        int unwrapped = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.int-max-property\", int.class);\n\n        assertThat(unwrapped).isEqualTo(Integer.MAX_VALUE);\n        assertThat(unwrapped).isEqualTo(node.getAsInt());\n    }\n\n    @Test\n    public void longs_are_unwrapped() {\n        JsonElement node = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.long-max-property\");\n        long val = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.long-max-property\", Long.class);\n\n        assertThat(val).isEqualTo(Long.MAX_VALUE);\n        assertThat(val).isEqualTo(node.getAsLong());\n    }\n\n    @Test\n    public void doubles_are_unwrapped() {\n        final String json = \"{double-property = 56.78}\";\n\n        JsonElement node = using(GSON_CONFIGURATION).parse(json).read(\"$.double-property\");\n        Double val = using(GSON_CONFIGURATION).parse(json).read(\"$.double-property\", Double.class);\n\n        assertThat(val).isEqualTo(56.78);\n        assertThat(val).isEqualTo(node.getAsDouble());\n    }\n\n    @Test\n    public void bigdecimals_are_unwrapped() {\n        final BigDecimal bd = BigDecimal.valueOf(Long.MAX_VALUE).add(BigDecimal.valueOf(10.5));\n        final String json = \"{bd-property = \" + bd.toString() + \"}\";\n\n        JsonElement node = using(GSON_CONFIGURATION).parse(json).read(\"$.bd-property\");\n        BigDecimal val = using(GSON_CONFIGURATION).parse(json).read(\"$.bd-property\", BigDecimal.class);\n\n        assertThat(val).isEqualTo(bd);\n        assertThat(val).isEqualTo(node.getAsBigDecimal());\n    }\n\n    @Test\n    public void small_bigdecimals_are_unwrapped() {\n        final BigDecimal bd = BigDecimal.valueOf(10.5);\n        final String json = \"{bd-property = \" + bd.toString() + \"}\";\n\n        JsonElement node = using(GSON_CONFIGURATION).parse(json).read(\"$.bd-property\");\n        BigDecimal val = using(GSON_CONFIGURATION).parse(json).read(\"$.bd-property\", BigDecimal.class);\n\n        assertThat(val).isEqualTo(bd);\n        assertThat(val).isEqualTo(node.getAsBigDecimal());\n    }\n\n    @Test\n    public void bigintegers_are_unwrapped() {\n        final BigInteger bi = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.TEN);\n        final String json = \"{bi-property = \" + bi.toString() + \"}\";\n\n        JsonElement node = using(GSON_CONFIGURATION).parse(json).read(\"$.bi-property\");\n        BigInteger val = using(GSON_CONFIGURATION).parse(json).read(\"$.bi-property\", BigInteger.class);\n\n        assertThat(val).isEqualTo(bi);\n        assertThat(val).isEqualTo(node.getAsBigInteger());\n    }\n\n    @Test\n    public void small_bigintegers_are_unwrapped() {\n        final BigInteger bi = BigInteger.valueOf(Long.MAX_VALUE);\n        final String json = \"{bi-property = \" + bi.toString() + \"}\";\n\n        JsonElement node = using(GSON_CONFIGURATION).parse(json).read(\"$.bi-property\");\n        BigInteger val = using(GSON_CONFIGURATION).parse(json).read(\"$.bi-property\", BigInteger.class);\n\n        assertThat(val).isEqualTo(bi);\n        assertThat(val).isEqualTo(node.getAsBigInteger());\n    }\n\n    @Test\n    public void int_to_long_mapping() {\n        assertThat(using(GSON_CONFIGURATION).parse(\"{\\\"val\\\": 1}\").read(\"val\", Long.class)).isEqualTo(1L);\n    }\n\n    @Test\n    public void an_Integer_can_be_converted_to_a_Double() {\n        assertThat(using(GSON_CONFIGURATION).parse(\"{\\\"val\\\": 1}\").read(\"val\", Double.class)).isEqualTo(1D);\n    }\n\n    @Test\n    public void list_of_numbers() {\n        JsonArray objs = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.store.book[*].display-price\");\n        List<Double> actual = new ArrayList<>();\n        for (JsonElement obj : objs) {\n            actual.add(obj.getAsDouble());\n        }\n        assertThat(actual).containsExactly(8.95D, 12.99D, 8.99D, 22.99D);\n    }\n\n    @Test\n    public void an_object_can_be_mapped_to_pojo() {\n\n        String json = \"{\\n\" +\n                \"   \\\"foo\\\" : \\\"foo\\\",\\n\" +\n                \"   \\\"bar\\\" : 10,\\n\" +\n                \"   \\\"baz\\\" : true\\n\" +\n                \"}\";\n\n\n        TestClazz testClazz = JsonPath.using(GSON_CONFIGURATION).parse(json).read(\"$\", TestClazz.class);\n\n        assertThat(testClazz.foo).isEqualTo(\"foo\");\n        assertThat(testClazz.bar).isEqualTo(10L);\n        assertThat(testClazz.baz).isEqualTo(true);\n\n    }\n\n    @Test\n    public void test_type_ref() throws IOException {\n        TypeRef<List<FooBarBaz<Gen>>> typeRef = new TypeRef<List<FooBarBaz<Gen>>>() {\n        };\n\n        List<FooBarBaz<Gen>> list = JsonPath.using(GSON_CONFIGURATION).parse(JSON).read(\"$\", typeRef);\n\n        assertThat(list.get(0).gen.eric).isEqualTo(\"yepp\");\n    }\n\n    @Test\n    public void test_type_ref_fail() throws IOException {\n        TypeRef<List<FooBarBaz<Integer>>> typeRef = new TypeRef<List<FooBarBaz<Integer>>>() {\n        };\n\n        assertThrows(MappingException.class, () -> using(GSON_CONFIGURATION).parse(JSON).read(\"$\", typeRef));\n    }\n\n    @Test\n    // https://github.com/json-path/JsonPath/issues/351\n    public void no_error_when_mapping_null() throws IOException {\n\n        Configuration configuration = Configuration\n                .builder()\n                .mappingProvider(new GsonMappingProvider())\n                .jsonProvider(new GsonJsonProvider())\n                .options(Option.DEFAULT_PATH_LEAF_TO_NULL, Option.SUPPRESS_EXCEPTIONS)\n                .build();\n\n        String json = \"{\\\"M\\\":[]}\";\n\n        String result = JsonPath.using(configuration).parse(json).read(\"$.M[0].A[0]\", String.class);\n\n        assertThat(result).isNull();\n    }\n\n\n    public static class FooBarBaz<T> {\n        public T gen;\n        public String foo;\n        public Long bar;\n        public boolean baz;\n    }\n\n\n    public static class Gen {\n        public String eric;\n    }\n\n    public static class TestClazz {\n        public String foo;\n        public Long bar;\n        public boolean baz;\n    }\n\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/InlineFilterTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\nimport java.math.BigDecimal;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static com.jayway.jsonpath.TestUtils.assertHasNoResults;\nimport static com.jayway.jsonpath.TestUtils.assertHasOneResult;\nimport static java.util.Arrays.asList;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class InlineFilterTest extends BaseTest {\n\n    private static int bookCount = 4;\n\n    public static final String MULTI_STORE_JSON_DOCUMENT = \"{\\n\" +\n            \"   \\\"store\\\" : [{\\n\" +\n            \"      \\\"name\\\": \\\"First\\\",\" +\n            \"      \\\"book\\\" : [\\n\" +\n            \"         {\\n\" +\n            \"            \\\"category\\\" : \\\"reference\\\",\\n\" +\n            \"            \\\"author\\\" : \\\"Nigel Rees\\\",\\n\" +\n            \"            \\\"title\\\" : \\\"Sayings of the Century\\\",\\n\" +\n            \"            \\\"display-price\\\" : 8.95\\n\" +\n            \"         },\\n\" +\n            \"         {\\n\" +\n            \"            \\\"category\\\" : \\\"fiction\\\",\\n\" +\n            \"            \\\"author\\\" : \\\"Evelyn Waugh\\\",\\n\" +\n            \"            \\\"title\\\" : \\\"Sword of Honour\\\",\\n\" +\n            \"            \\\"display-price\\\" : 12.99\\n\" +\n            \"         },\\n\" +\n            \"         {\\n\" +\n            \"            \\\"category\\\" : \\\"fiction\\\",\\n\" +\n            \"            \\\"author\\\" : \\\"Herman Melville\\\",\\n\" +\n            \"            \\\"title\\\" : \\\"Moby Dick\\\",\\n\" +\n            \"            \\\"isbn\\\" : \\\"0-553-21311-3\\\",\\n\" +\n            \"            \\\"display-price\\\" : 8.99\\n\" +\n            \"         },\\n\" +\n            \"         {\\n\" +\n            \"            \\\"category\\\" : \\\"fiction\\\",\\n\" +\n            \"            \\\"author\\\" : \\\"J. R. R. Tolkien\\\",\\n\" +\n            \"            \\\"title\\\" : \\\"The Lord of the Rings\\\",\\n\" +\n            \"            \\\"isbn\\\" : \\\"0-395-19395-8\\\",\\n\" +\n            \"            \\\"display-price\\\" : 22.99\\n\" +\n            \"         }]\\n\" +\n            \"      },\\n\" +\n            \"      {\\n\" +\n            \"       \\\"name\\\": \\\"Second\\\",\\n\" +\n            \"       \\\"book\\\": [\\n\" +\n            \"         {\\n\" +\n            \"            \\\"category\\\" : \\\"fiction\\\",\\n\" +\n            \"            \\\"author\\\" : \\\"Ernest Hemmingway\\\",\\n\" +\n            \"            \\\"title\\\" : \\\"The Old Man and the Sea\\\",\\n\" +\n            \"            \\\"display-price\\\" : 12.99\\n\" +\n            \"         }]\\n\" +\n            \"      }]}\";\n\n\n    public static Iterable<Configuration> configurations() {\n        return Configurations.configurations();\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void root_context_can_be_referred_in_predicate(Configuration conf) {\n        List<?> prices = using(conf).parse(JSON_DOCUMENT).read(\"store.book[?(@.display-price <= $.max-price)].display-price\", List.class);\n\n        assertThat(prices.stream().map(this::asDouble)).containsAll(asList(8.95D, 8.99D));\n    }\n\n    private Double asDouble(Object object) {\n        // For json-org implementation returns a list of big decimals\n        return object instanceof BigDecimal ? ((BigDecimal) object).doubleValue() : (Double) object;\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void multiple_context_object_can_be_refered(Configuration conf) {\n\n        List all = using(conf).parse(JSON_DOCUMENT).read(\"store.book[ ?(@.category == @.category) ]\", List.class);\n        assertThat(all.size()).isEqualTo(bookCount);\n\n        List all2 = using(conf).parse(JSON_DOCUMENT).read(\"store.book[ ?(@.category == @['category']) ]\", List.class);\n        assertThat(all2.size()).isEqualTo(bookCount);\n\n        List all3 = using(conf).parse(JSON_DOCUMENT).read(\"store.book[ ?(@ == @) ]\", List.class);\n        assertThat(all3.size()).isEqualTo(bookCount);\n\n        List none = using(conf).parse(JSON_DOCUMENT).read(\"store.book[ ?(@.category != @.category) ]\", List.class);\n        assertThat(none.size()).isEqualTo(0);\n\n        List none2 = using(conf).parse(JSON_DOCUMENT).read(\"store.book[ ?(@.category != @) ]\", List.class);\n        assertThat(none2.size()).isEqualTo(4);\n\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void simple_inline_or_statement_evaluates(Configuration conf) {\n\n        List a = using(conf).parse(JSON_DOCUMENT).read(\"store.book[ ?(@.author == 'Nigel Rees' || @.author == 'Evelyn Waugh') ].author\", List.class);\n        assertThat(a).containsExactly(\"Nigel Rees\", \"Evelyn Waugh\");\n\n        List b = using(conf).parse(JSON_DOCUMENT).read(\"store.book[ ?((@.author == 'Nigel Rees' || @.author == 'Evelyn Waugh') && @.display-price < 15) ].author\", List.class);\n        assertThat(b).containsExactly(\"Nigel Rees\", \"Evelyn Waugh\");\n\n        List c = using(conf).parse(JSON_DOCUMENT).read(\"store.book[ ?((@.author == 'Nigel Rees' || @.author == 'Evelyn Waugh') && @.category == 'reference') ].author\", List.class);\n        assertThat(c).containsExactly(\"Nigel Rees\");\n\n        List d = using(conf).parse(JSON_DOCUMENT).read(\"store.book[ ?((@.author == 'Nigel Rees') || (@.author == 'Evelyn Waugh' && @.category != 'fiction')) ].author\", List.class);\n        assertThat(d).containsExactly(\"Nigel Rees\");\n    }\n\n\n    public void no_path_ref_in_filter_hit_all() {\n\n        List<String> res = JsonPath.parse(JSON_DOCUMENT).read(\"$.store.book[?('a' == 'a')].author\");\n\n        assertThat(res).containsExactly(\"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\");\n\n    }\n\n    @Test\n    public void no_path_ref_in_filter_hit_none() {\n\n        List<String> res = JsonPath.parse(JSON_DOCUMENT).read(\"$.store.book[?('a' == 'b')].author\");\n\n        assertThat(res).isEmpty();\n\n    }\n\n    @Test\n    public void path_can_be_on_either_side_of_operator() {\n        List<String> resLeft = JsonPath.parse(JSON_DOCUMENT).read(\"$.store.book[?(@.category == 'reference')].author\");\n        List<String> resRight = JsonPath.parse(JSON_DOCUMENT).read(\"$.store.book[?('reference' == @.category)].author\");\n\n        assertThat(resLeft).containsExactly(\"Nigel Rees\");\n        assertThat(resRight).containsExactly(\"Nigel Rees\");\n    }\n\n    @Test\n    public void path_can_be_on_both_side_of_operator() {\n        List<String> res = JsonPath.parse(JSON_DOCUMENT).read(\"$.store.book[?(@.category == @.category)].author\");\n\n        assertThat(res).containsExactly(\"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\");\n    }\n\n    @Test\n    public void patterns_can_be_evaluated() {\n        List<String> resLeft = JsonPath.parse(JSON_DOCUMENT).read(\"$.store.book[?(@.category =~ /reference/)].author\");\n        assertThat(resLeft).containsExactly(\"Nigel Rees\");\n\n        resLeft = JsonPath.parse(JSON_DOCUMENT).read(\"$.store.book[?(/reference/ =~ @.category)].author\");\n        assertThat(resLeft).containsExactly(\"Nigel Rees\");\n    }\n\n    @Test\n    public void patterns_can_be_evaluated_with_ignore_case() {\n        List<String> resLeft = JsonPath.parse(JSON_DOCUMENT).read(\"$.store.book[?(@.category =~ /REFERENCE/)].author\");\n        assertThat(resLeft).isEmpty();\n\n        resLeft = JsonPath.parse(JSON_DOCUMENT).read(\"$.store.book[?(@.category =~ /REFERENCE/i)].author\");\n        assertThat(resLeft).containsExactly(\"Nigel Rees\");\n    }\n\n    @Test\n    public void patterns_match_against_lists() {\n        List<String> haveRefBooks = JsonPath.parse(MULTI_STORE_JSON_DOCUMENT).read(\"$.store[?(@.book[*].category =~ /Reference/i)].name\");\n        assertThat(haveRefBooks).containsExactly(\"First\");\n    }\n\n    @Test\n    public void negate_exists_check() {\n        List<String> hasIsbn = JsonPath.parse(JSON_DOCUMENT).read(\"$.store.book[?(@.isbn)].author\");\n        assertThat(hasIsbn).containsExactly(\"Herman Melville\", \"J. R. R. Tolkien\");\n\n        List<String> noIsbn = JsonPath.parse(JSON_DOCUMENT).read(\"$.store.book[?(!@.isbn)].author\");\n\n        assertThat(noIsbn).containsExactly(\"Nigel Rees\", \"Evelyn Waugh\");\n    }\n\n    @Test\n    public void negate_exists_check_primitive() {\n        List<Integer> ints = new ArrayList<Integer>();\n        ints.add(0);\n        ints.add(1);\n        ints.add(null);\n        ints.add(2);\n        ints.add(3);\n\n\n        List<Integer> hits = JsonPath.parse(ints).read(\"$[?(@)]\");\n        assertThat(hits).containsExactly(0, 1, null, 2, 3);\n\n        hits = JsonPath.parse(ints).read(\"$[?(@ != null)]\");\n        assertThat(hits).containsExactly(0, 1, 2, 3);\n\n        List<Integer> isNull = JsonPath.parse(ints).read(\"$[?(!@)]\");\n        assertThat(isNull).containsExactly(new Integer[]{});\n        assertThat(isNull).containsExactly(new Integer[]{});\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void equality_check_does_not_break_evaluation(Configuration conf) {\n        assertHasOneResult(\"[{\\\"value\\\":\\\"5\\\"}]\", \"$[?(@.value=='5')]\", conf);\n        assertHasOneResult(\"[{\\\"value\\\":5}]\", \"$[?(@.value==5)]\", conf);\n\n        assertHasOneResult(\"[{\\\"value\\\":\\\"5.1.26\\\"}]\", \"$[?(@.value=='5.1.26')]\", conf);\n\n        assertHasNoResults(\"[{\\\"value\\\":\\\"5\\\"}]\", \"$[?(@.value=='5.1.26')]\", conf);\n        assertHasNoResults(\"[{\\\"value\\\":5}]\", \"$[?(@.value=='5.1.26')]\", conf);\n        assertHasNoResults(\"[{\\\"value\\\":5.1}]\", \"$[?(@.value=='5.1.26')]\", conf);\n\n        assertHasNoResults(\"[{\\\"value\\\":\\\"5.1.26\\\"}]\", \"$[?(@.value=='5')]\", conf);\n        assertHasNoResults(\"[{\\\"value\\\":\\\"5.1.26\\\"}]\", \"$[?(@.value==5)]\", conf);\n        assertHasNoResults(\"[{\\\"value\\\":\\\"5.1.26\\\"}]\", \"$[?(@.value==5.1)]\", conf);\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void lt_check_does_not_break_evaluation(Configuration conf) {\n        assertHasOneResult(\"[{\\\"value\\\":\\\"5\\\"}]\", \"$[?(@.value<'7')]\", conf);\n\n        assertHasNoResults(\"[{\\\"value\\\":\\\"7\\\"}]\", \"$[?(@.value<'5')]\", conf);\n\n        assertHasOneResult(\"[{\\\"value\\\":5}]\", \"$[?(@.value<7)]\", conf);\n        assertHasNoResults(\"[{\\\"value\\\":7}]\", \"$[?(@.value<5)]\", conf);\n\n        assertHasOneResult(\"[{\\\"value\\\":5}]\", \"$[?(@.value<7.1)]\", conf);\n        assertHasNoResults(\"[{\\\"value\\\":7}]\", \"$[?(@.value<5.1)]\", conf);\n\n        assertHasOneResult(\"[{\\\"value\\\":5.1}]\", \"$[?(@.value<7)]\", conf);\n        assertHasNoResults(\"[{\\\"value\\\":7.1}]\", \"$[?(@.value<5)]\", conf);\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void escaped_literals(Configuration conf) {\n        if (conf.jsonProvider().getClass().getSimpleName().startsWith(\"Jackson\")) {\n            return;\n        }\n        if (conf.jsonProvider().getClass().getSimpleName().startsWith(\"Jakarta\")) {\n            // single quotes are not valid in JSON; see json.org\n            return;\n        }\n        assertHasOneResult(\"[\\\"\\\\'foo\\\"]\", \"$[?(@ == '\\\\'foo')]\", conf);\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void escaped_literals2(Configuration conf) {\n        if (conf.jsonProvider().getClass().getSimpleName().startsWith(\"Jackson\")) {\n            return;\n        }\n        assertHasOneResult(\"[\\\"\\\\\\\\'foo\\\"]\", \"$[?(@ == \\\"\\\\\\\\'foo\\\")]\", conf);\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void escape_pattern(Configuration conf) {\n        assertHasOneResult(\"[\\\"x\\\"]\", \"$[?(@ =~ /\\\\/|x/)]\", conf);\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void escape_pattern_after_literal(Configuration conf) {\n        assertHasOneResult(\"[\\\"x\\\"]\", \"$[?(@ == \\\"abc\\\" || @ =~ /\\\\/|x/)]\", conf);\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void escape_pattern_before_literal(Configuration conf) {\n        assertHasOneResult(\"[\\\"x\\\"]\", \"$[?(@ =~ /\\\\/|x/ || @ == \\\"abc\\\")]\", conf);\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void filter_evaluation_does_not_break_path_evaluation(Configuration conf) {\n        assertHasOneResult(\"[{\\\"s\\\": \\\"fo\\\", \\\"expected_size\\\": \\\"m\\\"}, {\\\"s\\\": \\\"lo\\\", \\\"expected_size\\\": 2}]\", \"$[?(@.s size @.expected_size)]\", conf);\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/Issue_487.java",
    "content": "package com.jayway.jsonpath;\r\n\r\nimport org.junit.jupiter.api.Test;\r\n\r\npublic class Issue_487 {\r\n\r\n    public static final Configuration jsonConf = Configuration.defaultConfiguration();\r\n\r\n    @Test//(expected = InvalidPathException.class)\r\n    public void test_read_with_comma_1(){  // originally throws InvalidPathException\r\n        DocumentContext dc = JsonPath.using(jsonConf)\r\n                .parse(\"{ \\\"key,\\\" : \\\"value\\\" }\");\r\n        Object ans = dc.read(JsonPath.compile(\"$['key,']\"));\r\n        //System.out.println(ans);\r\n        assert(ans.toString().equals(\"value\"));\r\n    }\r\n\r\n    @Test\r\n    public void test_read_with_comma_2(){  // originally passed\r\n        DocumentContext dc = JsonPath.using(jsonConf)\r\n                .parse(\"{ \\\"key,\\\" : \\\"value\\\" }\");\r\n        Object ans = dc.read(JsonPath.compile(\"$['key\\\\,']\"));\r\n        //System.out.println(ans);\r\n        assert(ans.toString().equals(\"value\"));\r\n    }\r\n}\r\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/Issue_537.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\npublic class Issue_537 {\n\n    public static final Configuration jsonConf = Configuration.defaultConfiguration().addOptions(Option.SUPPRESS_EXCEPTIONS);\n\n    @Test\n    public void test_read(){  // originally passed\n        Object ans = JsonPath.using(jsonConf).parse(\"{}\").read(\"missing\");\n        assert(ans == null);\n    }\n\n    @Test\n    public void test_renameKey(){  // originally throws PathNotFoundException\n        List<Object> ans = JsonPath.using(jsonConf)\n                .parse(\"{\\\"list\\\":[\" +\n                        \"{\\\"data\\\":{\\\"old\\\":1}},\" +\n                        \"{\\\"data\\\":{}},\" +\n                        \"{\\\"data\\\":{\\\"old\\\":2}}\" +\n                        \"]}\")\n                .renameKey(\"$..data\", \"old\", \"new\")\n                .read(\"$.list\");\n        assert(ans.toString().equals(\"[{\\\"data\\\":{\\\"new\\\":1}},{\\\"data\\\":{}},{\\\"data\\\":{\\\"new\\\":2}}]\"));\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/Issue_721.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\npublic class Issue_721 {\n\n    public static final Configuration jsonConf = Configuration.defaultConfiguration().addOptions(Option.SUPPRESS_EXCEPTIONS);\n\n    @Test\n    public void test_delete_1(){  // originally throws PathNotFoundException\n        DocumentContext dc = JsonPath.using(jsonConf)\n                    .parse(\"{\\\"top\\\": {\\\"middle\\\": null}}\")\n                    .delete(JsonPath.compile(\"$.top.middle.bottom\"));\n        Object ans = dc.read(\"$\");\n        //System.out.println(ans);\n        assert(ans.toString().equals(\"{top={middle=null}}\"));\n    }\n\n    @Test\n    public void test_delete_2(){  // originally passed\n        DocumentContext dc = JsonPath.using(jsonConf)\n                .parse(\"[\" +\n                        \"{\\\"top\\\": {\\\"middle\\\": null}},\" +\n                        \"{\\\"top\\\": {\\\"middle\\\": {}  }},\" +\n                        \"{\\\"top\\\": {\\\"middle\\\": {bottom: 2}  }},\" +\n                        \"]\")\n                .delete(JsonPath.compile(\"$[*].top.middle.bottom\"));\n        Object ans = dc.read(\"$\");\n        //System.out.println(ans);\n        assert(ans.toString().equals(\"[{\\\"top\\\":{\\\"middle\\\":null}},{\\\"top\\\":{\\\"middle\\\":{}}},{\\\"top\\\":{\\\"middle\\\":{}}}]\"));\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/Issue_762.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\n\n/**\n * test for issue 762\n */\n\npublic class Issue_762 {\n    @Test\n    public void testParseJsonValue(){\n        assert(JsonPath.parse(5).jsonString().equals(\"5\"));\n        assert(JsonPath.parse(5.0).jsonString().equals(\"5.0\"));\n        assert(JsonPath.parse(true).jsonString().equals(\"true\"));\n        assert(JsonPath.parse(false).jsonString().equals(\"false\"));\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/Issue_786.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * test for issue 786\n */\npublic class Issue_786 extends BaseTest{\n\n    @Test\n    public void test(){\n        assertThat(bookLength()).describedAs(\"First run\").isEqualTo(4);\n        assertThat(bookLength()).describedAs(\"Second run\").isEqualTo(4);\n        assertThat(bookLength()).describedAs(\"Third run\").isEqualTo(4);\n    }\n\n    private int bookLength() {\n        return JsonPath.read(JSON_DOCUMENT, \"$..book.length()\");\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/Issue_970.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.assertThatNoException;\n\npublic class Issue_970 {\n    @Test\n    public void shouldNotCauseStackOverflow() {\n        assertThatNoException().isThrownBy(() -> Criteria.where(\"[']',\"));\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/Issue_973.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.assertj.core.api.Assertions.*;\n\npublic class Issue_973 {\n    @Test\n    public void shouldNotCauseStackOverflow() {\n        assertThatNoException().isThrownBy(() -> Criteria.parse(\"@[\\\"\\\",/\\\\\"));\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/Jackson3JsonNodeJsonProviderMapperSupportTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport tools.jackson.databind.JsonNode;\nimport tools.jackson.databind.ObjectMapper;\nimport tools.jackson.databind.node.StringNode;\nimport com.jayway.jsonpath.spi.json.Jackson3JsonNodeJsonProvider;\nimport com.jayway.jsonpath.spi.mapper.Jackson3MappingProvider;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class Jackson3JsonNodeJsonProviderMapperSupportTest {\n\n    @ParameterizedTest\n    @MethodSource(\"testDataSource\")\n    public void mapMethod_withJacksonJsonNodeJsonProvider_shouldUsingJsonNodeForMappingValues(TestData testData) {\n        DocumentContext testJsonDocumentContext = cloneDocumentContext(testData.jsonDocumentContext);\n\n        testJsonDocumentContext.map(testData.jsonPath, (value, config) -> {\n            assertThat(value.getClass()).isEqualTo(testData.expectedJsonValueNodeType);\n            return testData.newJsonValue;\n        });\n        assertThat((JsonNode) testJsonDocumentContext.json())\n                .isEqualTo(testData.expectedUpdatedJsonDocument);\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"testDataSource\")\n    public void readMethod_withJacksonJsonNodeJsonProvider_shouldReturnJsonNode(TestData testData) {\n        DocumentContext testJsonDocumentContext = cloneDocumentContext(testData.jsonDocumentContext);\n\n        final JsonNode actualJsonValue = testJsonDocumentContext.read(testData.jsonPath);\n        assertThat(actualJsonValue).isEqualTo(testData.expectedJsonValue);\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"testDataSource\")\n    public void setMethod_withJacksonJsonNodeJsonProvider_shouldAcceptJsonNode(TestData testData) {\n        DocumentContext testJsonDocumentContext = cloneDocumentContext(testData.jsonDocumentContext);\n\n        testJsonDocumentContext.set(testData.jsonPath, testData.newJsonValue);\n        assertThat((JsonNode) testJsonDocumentContext.json())\n                .isEqualTo(testData.expectedUpdatedJsonDocument);\n    }\n\n    private static class TestData {\n\n        public final DocumentContext jsonDocumentContext;\n        public final String jsonPath;\n        public final JsonNode newJsonValue;\n        public final JsonNode expectedJsonValue;\n        public final Class<? extends JsonNode> expectedJsonValueNodeType;\n        public final JsonNode expectedUpdatedJsonDocument;\n\n        public TestData(\n                DocumentContext jsonDocumentContext,\n                String jsonPath,\n                JsonNode newJsonValue,\n                JsonNode expectedJsonValue,\n                Class<? extends JsonNode> expectedJsonValueNodeType,\n                JsonNode expectedUpdatedJsonDocument) {\n            this.jsonDocumentContext = jsonDocumentContext;\n            this.jsonPath = jsonPath;\n            this.newJsonValue = newJsonValue;\n            this.expectedJsonValue = expectedJsonValue;\n            this.expectedJsonValueNodeType = expectedJsonValueNodeType;\n            this.expectedUpdatedJsonDocument = expectedUpdatedJsonDocument;\n        }\n    }\n\n\n    public static List<TestData> testDataSource() throws Exception {\n        final Configuration configuration = Configuration.builder()\n                .jsonProvider(new Jackson3JsonNodeJsonProvider())\n                .mappingProvider(new Jackson3MappingProvider())\n                .build();\n        final ParseContext parseContext = JsonPath.using(configuration);\n        final ObjectMapper objectMapper = new ObjectMapper();\n\n        return Arrays.asList(\n                // Single value JSON path\n                new TestData(\n                        parseContext.parse(\"{\"\n                                + \"    \\\"attr1\\\":  \\\"val1\\\",\"\n                                + \"    \\\"attr2\\\":  \\\"val2\\\"\"\n                                + \"}\"),\n                        \"$.attr1\",\n                        objectMapper.readTree(\"{\\\"attr1\\\": \\\"val1\\\"}\"),\n                        objectMapper.readTree(\"\\\"val1\\\"\"),\n                        StringNode.class,\n                        objectMapper.readTree(\"{\"\n                                + \"    \\\"attr1\\\": {\\\"attr1\\\": \\\"val1\\\"},\"\n                                + \"    \\\"attr2\\\": \\\"val2\\\"\"\n                                + \"}\")),\n                // Multi-value JSON path\n                new TestData(\n                        parseContext.parse(\"{\"\n                                + \"    \\\"attr1\\\":  [\\\"val1\\\", \\\"val2\\\"],\"\n                                + \"    \\\"attr2\\\":  \\\"val2\\\"\"\n                                + \"}\"),\n                        \"$.attr1[*]\",\n                        objectMapper.readTree(\"{\\\"attr1\\\": \\\"val1\\\"}\"),\n                        objectMapper.readTree(\"[\\\"val1\\\", \\\"val2\\\"]\"),\n                        StringNode.class,\n                        objectMapper.readTree(\"{\"\n                                + \"    \\\"attr1\\\": [{\\\"attr1\\\": \\\"val1\\\"}, {\\\"attr1\\\": \\\"val1\\\"}],\"\n                                + \"    \\\"attr2\\\": \\\"val2\\\"\"\n                                + \"}\")),\n                // Multi-value object JSON path\n                new TestData(\n                        parseContext.parse(\"{\"\n                                + \"    \\\"attr1\\\":  [\"\n                                + \"         {\\\"inAttr1\\\": \\\"val1a\\\", \\\"inAttr2\\\": \\\"val2a\\\"},\"\n                                + \"         {\\\"inAttr1\\\": \\\"val1a\\\", \\\"inAttr2\\\": \\\"val2b\\\"},\"\n                                + \"         {\\\"inAttr1\\\": \\\"val1b\\\", \\\"inAttr2\\\": \\\"val2c\\\"}\"\n                                + \"    ],\"\n                                + \"    \\\"attr2\\\":  \\\"val2\\\"\"\n                                + \"}\"),\n                        \"$.attr1.[?(@.inAttr1 == \\\"val1a\\\")].inAttr2\",\n                        objectMapper.readTree(\"{\\\"attr1\\\": \\\"val1\\\"}\"),\n                        objectMapper.readTree(\"[\\\"val2a\\\", \\\"val2b\\\"]\"),\n                        StringNode.class,\n                        objectMapper.readTree(\"{\"\n                                + \"    \\\"attr1\\\": [\"\n                                + \"         {\\\"inAttr1\\\": \\\"val1a\\\", \\\"inAttr2\\\": {\\\"attr1\\\": \\\"val1\\\"}},\"\n                                + \"         {\\\"inAttr1\\\": \\\"val1a\\\", \\\"inAttr2\\\": {\\\"attr1\\\": \\\"val1\\\"}},\"\n                                + \"         {\\\"inAttr1\\\": \\\"val1b\\\", \\\"inAttr2\\\": \\\"val2c\\\"}\"\n                                + \"    ],\"\n                                + \"    \\\"attr2\\\": \\\"val2\\\"\"\n                                + \"}\"))\n        );\n    }\n\n    private static DocumentContext cloneDocumentContext(DocumentContext documentContext) {\n        return JsonPath.using(documentContext.configuration()).parse(documentContext.jsonString());\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/Jackson3JsonNodeJsonProviderTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport java.io.IOException;\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.nio.charset.StandardCharsets;\nimport java.util.List;\nimport java.util.UUID;\n\nimport com.fasterxml.jackson.annotation.JsonCreator;\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport tools.jackson.databind.DeserializationFeature;\nimport tools.jackson.databind.JsonNode;\nimport tools.jackson.databind.ObjectMapper;\nimport tools.jackson.databind.SerializationFeature;\nimport tools.jackson.databind.json.JsonMapper;\nimport tools.jackson.databind.node.ArrayNode;\nimport tools.jackson.databind.node.JsonNodeFactory;\nimport tools.jackson.databind.node.ObjectNode;\nimport com.jayway.jsonpath.spi.json.Jackson3JsonNodeJsonProvider;\nimport com.jayway.jsonpath.spi.mapper.Jackson3MappingProvider;\nimport com.jayway.jsonpath.spi.mapper.MappingException;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class Jackson3JsonNodeJsonProviderTest extends BaseTest {\n\n    private static final String JSON =\n            \"[\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo0\\\",\\n\" +\n            \"   \\\"bar\\\" : 0,\\n\" +\n            \"   \\\"baz\\\" : true,\\n\" +\n            \"   \\\"gen\\\" : {\\\"eric\\\" : \\\"yepp\\\"}\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo1\\\",\\n\" +\n            \"   \\\"bar\\\" : 1,\\n\" +\n            \"   \\\"baz\\\" : true,\\n\" +\n            \"   \\\"gen\\\" : {\\\"eric\\\" : \\\"yepp\\\"}\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo2\\\",\\n\" +\n            \"   \\\"bar\\\" : 2,\\n\" +\n            \"   \\\"baz\\\" : true,\\n\" +\n            \"   \\\"gen\\\" : {\\\"eric\\\" : \\\"yepp\\\"}\" +\n            \"}\" +\n            \"]\";\n\n    @Test\n    public void json_can_be_parsed() {\n        ObjectNode node = using(JACKSON3_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$\");\n        assertThat(node.get(\"string-property\").asText()).isEqualTo(\"string-value\");\n    }\n\n    @Test\n    public void bytes_json_can_be_parsed() {\n        ObjectNode node = using(JACKSON3_JSON_NODE_CONFIGURATION).parseUtf8(JSON_DOCUMENT.getBytes(StandardCharsets.UTF_8))\n            .read(\"$\");\n        assertThat(node.get(\"string-property\").asText()).isEqualTo(\"string-value\");\n    }\n\n    @Test\n    public void always_return_same_object() { // Test because of Bug #211\n    \tDocumentContext context = using(JACKSON3_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT);\n        ObjectNode node1 = context.read(\"$\");\n        ObjectNode child1 = new ObjectNode(JsonNodeFactory.instance);\n        child1.put(\"name\", \"test\");\n        context.put(\"$\", \"child\", child1);\n        ObjectNode node2 = context.read(\"$\");\n        ObjectNode child2 = context.read(\"$.child\");\n\n        assertThat(node1).isSameAs(node2);\n        assertThat(child1).isSameAs(child2);\n    }\n\n    @Test\n    public void strings_are_unwrapped() {\n        JsonNode node = using(JACKSON3_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.string-property\");\n        String unwrapped = using(JACKSON3_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.string-property\", String.class);\n\n        assertThat(unwrapped).isEqualTo(\"string-value\");\n        assertThat(unwrapped).isEqualTo(node.asText());\n    }\n\n    @Test\n    public void ints_are_unwrapped() {\n        JsonNode node = using(JACKSON3_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.int-max-property\");\n        int unwrapped = using(JACKSON3_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.int-max-property\", int.class);\n        assertThat(unwrapped).isEqualTo(Integer.MAX_VALUE);\n        assertThat(unwrapped).isEqualTo(node.asInt());\n    }\n\n    @Test\n    public void longs_are_unwrapped() {\n        JsonNode node = using(JACKSON3_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.long-max-property\");\n        long unwrapped = using(JACKSON3_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.long-max-property\", long.class);\n\n        assertThat(unwrapped).isEqualTo(Long.MAX_VALUE);\n        assertThat(unwrapped).isEqualTo(node.asLong());\n    }\n\n    @Test\n    public void list_of_numbers() {\n        ArrayNode objs = using(JACKSON3_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.store.book[*].display-price\");\n\n        assertThat(objs.get(0).asDouble()).isEqualTo(8.95D);\n        assertThat(objs.get(1).asDouble()).isEqualTo(12.99D);\n        assertThat(objs.get(2).asDouble()).isEqualTo(8.99D);\n        assertThat(objs.get(3).asDouble()).isEqualTo(22.99D);\n    }\n\n    ObjectMapper objectMapperDecimal = JsonMapper.builder()\n                                                 .enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS).build();\n    Configuration JACKSON3_JSON_NODE_CONFIGURATION_DECIMAL = Configuration\n            .builder()\n            .mappingProvider(new Jackson3MappingProvider())\n            .jsonProvider(new Jackson3JsonNodeJsonProvider(objectMapperDecimal))\n            .build();\n\n    @Test\n    public void bigdecimals_are_unwrapped() {\n        final BigDecimal bd = BigDecimal.valueOf(Long.MAX_VALUE).add(BigDecimal.valueOf(10.5));\n        final String json = \"{\\\"bd-property\\\" : \" + bd.toString() + \"}\";\n\n        JsonNode node =  using(JACKSON3_JSON_NODE_CONFIGURATION_DECIMAL).parse(json).read(\"$.bd-property\");\n        BigDecimal val =  using(JACKSON3_JSON_NODE_CONFIGURATION_DECIMAL).parse(json).read(\"$.bd-property\", BigDecimal.class);\n\n        assertThat(node.isBigDecimal()).isTrue();\n        assertThat(val).isEqualTo(bd);\n        assertThat(val).isEqualTo(node.decimalValue());\n    }\n\n    @Test\n    public void small_bigdecimals_are_unwrapped() {\n        final BigDecimal bd = BigDecimal.valueOf(10.5);\n        final String json = \"{\\\"bd-property\\\" : \" + bd.toString() + \"}\";\n\n        JsonNode node =  using(JACKSON3_JSON_NODE_CONFIGURATION_DECIMAL).parse(json).read(\"$.bd-property\");\n        BigDecimal val =  using(JACKSON3_JSON_NODE_CONFIGURATION_DECIMAL).parse(json).read(\"$.bd-property\", BigDecimal.class);\n\n        assertThat(node.isBigDecimal()).isTrue();\n        assertThat(val).isEqualTo(bd);\n        assertThat(val).isEqualTo(node.decimalValue());\n    }\n\n    ObjectMapper objectMapperBigInteger = JsonMapper.builder()\n                                                    .enable(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS).build();;\n    Configuration JACKSON3_JSON_NODE_CONFIGURATION_Big_Integer = Configuration\n            .builder()\n            .mappingProvider(new Jackson3MappingProvider())\n            .jsonProvider(new Jackson3JsonNodeJsonProvider(objectMapperBigInteger))\n            .build();\n\n    @Test\n    public void bigintegers_are_unwrapped() {\n        final BigInteger bi = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.TEN);\n        final String json = \"{\\\"bi-property\\\" : \" + bi.toString() + \"}\";\n\n        JsonNode node =  using(JACKSON3_JSON_NODE_CONFIGURATION_Big_Integer).parse(json).read(\"$.bi-property\");\n        BigInteger val =  using(JACKSON3_JSON_NODE_CONFIGURATION_Big_Integer).parse(json).read(\"$.bi-property\", BigInteger.class);\n\n        assertThat(node.isBigInteger()).isTrue();\n        assertThat(val).isEqualTo(bi);\n        assertThat(val).isEqualTo(node.bigIntegerValue());\n    }\n\n    @Test\n    public void small_bigintegers_are_unwrapped() {\n        final BigInteger bi = BigInteger.valueOf(Long.MAX_VALUE);\n        final String json = \"{\\\"bi-property\\\" : \" + bi.toString() + \"}\";\n\n        JsonNode node =  using(JACKSON3_JSON_NODE_CONFIGURATION_Big_Integer).parse(json).read(\"$.bi-property\");\n        BigInteger val =  using(JACKSON3_JSON_NODE_CONFIGURATION_Big_Integer).parse(json).read(\"$.bi-property\", BigInteger.class);\n\n        assertThat(node.isBigInteger()).isTrue();\n        assertThat(val).isEqualTo(bi);\n        assertThat(val).isEqualTo(node.bigIntegerValue());\n    }\n\n    @Test\n    public void test_type_ref() throws IOException {\n        TypeRef<List<FooBarBaz<Gen>>> typeRef = new TypeRef<List<FooBarBaz<Gen>>>() {};\n\n        List<FooBarBaz<Gen>> list = using(JACKSON3_JSON_NODE_CONFIGURATION).parse(JSON).read(\"$\", typeRef);\n\n        assertThat(list.get(0).gen.eric).isEqualTo(\"yepp\");\n    }\n\n    @Test\n    public void test_type_ref_fail() throws IOException {\n        TypeRef<List<FooBarBaz<Integer>>> typeRef = new TypeRef<List<FooBarBaz<Integer>>>() {};\n\n        Assertions.assertThrows(MappingException.class, () -> using(JACKSON3_JSON_NODE_CONFIGURATION).parse(JSON).read(\"$\", typeRef));\n    }\n\n    @Test\n    public void mapPropertyWithPOJO() {\n        String someJson = \"\" +\n                \"{\\n\" +\n                \"  \\\"a\\\": \\\"a\\\",\\n\" +\n                \"  \\\"b\\\": \\\"b\\\"\\n\" +\n                \"}\";\n        ObjectMapper om = JsonMapper.builder()\n                                    .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS).build();\n        Configuration c = Configuration\n                .builder()\n                .mappingProvider(new Jackson3MappingProvider())\n                .jsonProvider(new Jackson3JsonNodeJsonProvider(om))\n                .build();\n        DocumentContext context = JsonPath.using(c).parse(someJson);\n        String someJsonStr = context.jsonString();\n        DocumentContext altered = context.map(\"$['a', 'b', 'c']\", new MapFunction() {\n            @Override\n            public Object map(Object currentValue, Configuration configuration) {\n                return currentValue;\n            }\n        });\n        assertThat(altered.jsonString()).isEqualTo(someJsonStr);\n    }\n\n    @Test\n    // https://github.com/json-path/JsonPath/issues/364\n    public void setPropertyWithPOJO() {\n      DocumentContext context = JsonPath.using(JACKSON3_JSON_NODE_CONFIGURATION).parse(\"{}\");\n      UUID uuid = UUID.randomUUID();\n      context.put(\"$\", \"data\", new Data(uuid));\n      String id = context.read(\"$.data.id\", String.class);\n      assertThat(id).isEqualTo(uuid.toString());\n    }\n    // https://github.com/json-path/JsonPath/issues/366\n    public void empty_array_check_works() throws IOException {\n      String json = \"[\" +\n          \"  {\" +\n          \"    \\\"name\\\": \\\"a\\\",\" +\n          \"    \\\"groups\\\": [{\" +\n          \"      \\\"type\\\": \\\"phase\\\",\" +\n          \"      \\\"name\\\": \\\"alpha\\\"\" +\n          \"    }, {\" +\n          \"      \\\"type\\\": \\\"not_phase\\\",\" +\n          \"      \\\"name\\\": \\\"beta\\\"\" +\n          \"    }]\" +\n          \"  }, {\" +\n          \"    \\\"name\\\": \\\"b\\\",\" +\n          \"    \\\"groups\\\": [{\" +\n          \"      \\\"type\\\": \\\"phase\\\",\" +\n          \"      \\\"name\\\": \\\"beta\\\"\" +\n          \"    }, {\" +\n          \"      \\\"type\\\": \\\"not_phase\\\",\" +\n          \"      \\\"name\\\": \\\"alpha\\\"\" +\n          \"    }]\" +\n          \"  }\" +\n          \"]\";\n      ArrayNode node = using(JACKSON3_JSON_NODE_CONFIGURATION).parse(json).read(\"$[?(@.groups[?(@.type == 'phase' && @.name == 'alpha')] empty false)]\");\n      assertThat(node.size()).isEqualTo(1);\n      assertThat(node.get(0).get(\"name\").asText()).isEqualTo(\"a\");\n    }\n\n    public static class FooBarBaz<T> {\n        public T gen;\n        public String foo;\n        public Long bar;\n        public boolean baz;\n    }\n\n\n    public static class Gen {\n        public String eric;\n    }\n\n    public static final class Data {\n      @JsonProperty(\"id\")\n      UUID id;\n\n      @JsonCreator\n      Data(@JsonProperty(\"id\") final UUID id) {\n        this.id = id;\n      }\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/Jackson3Test.java",
    "content": "package com.jayway.jsonpath;\n\nimport java.util.Date;\n\nimport org.junit.jupiter.api.Test;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\nimport static java.util.Collections.singletonMap;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class Jackson3Test extends BaseTest {\n\n    @Test\n    public void an_object_can_be_mapped_to_pojo() {\n\n        String json = \"{\\n\" +\n                \"   \\\"foo\\\" : \\\"foo\\\",\\n\" +\n                \"   \\\"bar\\\" : 10,\\n\" +\n                \"   \\\"baz\\\" : true\\n\" +\n                \"}\";\n\n\n        FooBarBaz fooBarBaz = JsonPath.using(JACKSON3_CONFIGURATION).parse(json).read(\"$\", FooBarBaz.class);\n\n        assertThat(fooBarBaz.foo).isEqualTo(\"foo\");\n        assertThat(fooBarBaz.bar).isEqualTo(10L);\n        assertThat(fooBarBaz.baz).isEqualTo(true);\n\n        fooBarBaz = JsonPath.using(JACKSON3_CONFIGURATION).parseUtf8(json.getBytes(UTF_8))\n            .read(\"$\", FooBarBaz.class);\n\n        assertThat(fooBarBaz.foo).isEqualTo(\"foo\");\n        assertThat(fooBarBaz.bar).isEqualTo(10L);\n        assertThat(fooBarBaz.baz).isEqualTo(true);\n    }\n\n    public static class FooBarBaz {\n        public String foo;\n        public Long bar;\n        public boolean baz;\n    }\n\n    @Test\n    public void jackson_converts_dates() {\n\n        Date now = new Date();\n\n        Object json = singletonMap(\"date_as_long\", now.getTime());\n\n        Date date = JsonPath.using(JACKSON3_CONFIGURATION).parse(json).read(\"$['date_as_long']\", Date.class);\n\n        assertThat(date).isEqualTo(now);\n    }\n\n    @Test\n    // https://github.com/jayway/JsonPath/issues/275\n    public void single_quotes_work_with_in_filter() {\n        final String jsonArray = \"[{\\\"foo\\\": \\\"bar\\\"}, {\\\"foo\\\": \\\"baz\\\"}]\";\n        final Object readFromSingleQuote = JsonPath.using(JACKSON3_CONFIGURATION).parse(jsonArray).read(\"$.[?(@.foo in ['bar'])].foo\");\n        final Object readFromDoubleQuote = JsonPath.using(JACKSON3_CONFIGURATION).parse(jsonArray).read(\"$.[?(@.foo in [\\\"bar\\\"])].foo\");\n        assertThat(readFromSingleQuote).isEqualTo(readFromDoubleQuote);\n        final Object readFromSingleQuoteBytes = JsonPath.using(JACKSON3_CONFIGURATION).parseUtf8(jsonArray.getBytes(UTF_8))\n            .read(\"$.[?(@.foo in ['bar'])].foo\");\n        final Object readFromDoubleQuoteBytes = JsonPath.using(JACKSON3_CONFIGURATION).parseUtf8(jsonArray.getBytes(UTF_8))\n            .read(\"$.[?(@.foo in [\\\"bar\\\"])].foo\");\n        assertThat(readFromSingleQuoteBytes).isEqualTo(readFromDoubleQuoteBytes);\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/JacksonJsonNodeJsonProviderMapperSupportTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.node.TextNode;\nimport com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider;\nimport com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class JacksonJsonNodeJsonProviderMapperSupportTest {\n\n    @ParameterizedTest\n    @MethodSource(\"testDataSource\")\n    public void mapMethod_withJacksonJsonNodeJsonProvider_shouldUsingJsonNodeForMappingValues(TestData testData) {\n        DocumentContext testJsonDocumentContext = cloneDocumentContext(testData.jsonDocumentContext);\n\n        testJsonDocumentContext.map(testData.jsonPath, (value, config) -> {\n            assertThat(value.getClass()).isEqualTo(testData.expectedJsonValueNodeType);\n            return testData.newJsonValue;\n        });\n        assertThat((JsonNode) testJsonDocumentContext.json())\n                .isEqualTo(testData.expectedUpdatedJsonDocument);\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"testDataSource\")\n    public void readMethod_withJacksonJsonNodeJsonProvider_shouldReturnJsonNode(TestData testData) {\n        DocumentContext testJsonDocumentContext = cloneDocumentContext(testData.jsonDocumentContext);\n\n        final JsonNode actualJsonValue = testJsonDocumentContext.read(testData.jsonPath);\n        assertThat(actualJsonValue).isEqualTo(testData.expectedJsonValue);\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"testDataSource\")\n    public void setMethod_withJacksonJsonNodeJsonProvider_shouldAcceptJsonNode(TestData testData) {\n        DocumentContext testJsonDocumentContext = cloneDocumentContext(testData.jsonDocumentContext);\n\n        testJsonDocumentContext.set(testData.jsonPath, testData.newJsonValue);\n        assertThat((JsonNode) testJsonDocumentContext.json())\n                .isEqualTo(testData.expectedUpdatedJsonDocument);\n    }\n\n    private static class TestData {\n\n        public final DocumentContext jsonDocumentContext;\n        public final String jsonPath;\n        public final JsonNode newJsonValue;\n        public final JsonNode expectedJsonValue;\n        public final Class<? extends JsonNode> expectedJsonValueNodeType;\n        public final JsonNode expectedUpdatedJsonDocument;\n\n        public TestData(\n                DocumentContext jsonDocumentContext,\n                String jsonPath,\n                JsonNode newJsonValue,\n                JsonNode expectedJsonValue,\n                Class<? extends JsonNode> expectedJsonValueNodeType,\n                JsonNode expectedUpdatedJsonDocument) {\n            this.jsonDocumentContext = jsonDocumentContext;\n            this.jsonPath = jsonPath;\n            this.newJsonValue = newJsonValue;\n            this.expectedJsonValue = expectedJsonValue;\n            this.expectedJsonValueNodeType = expectedJsonValueNodeType;\n            this.expectedUpdatedJsonDocument = expectedUpdatedJsonDocument;\n        }\n    }\n\n\n    public static List<TestData> testDataSource() throws Exception {\n        final Configuration configuration = Configuration.builder()\n                .jsonProvider(new JacksonJsonNodeJsonProvider())\n                .mappingProvider(new JacksonMappingProvider())\n                .build();\n        final ParseContext parseContext = JsonPath.using(configuration);\n        final ObjectMapper objectMapper = new ObjectMapper();\n\n        return Arrays.asList(\n                // Single value JSON path\n                new TestData(\n                        parseContext.parse(\"{\"\n                                + \"    \\\"attr1\\\":  \\\"val1\\\",\"\n                                + \"    \\\"attr2\\\":  \\\"val2\\\"\"\n                                + \"}\"),\n                        \"$.attr1\",\n                        objectMapper.readTree(\"{\\\"attr1\\\": \\\"val1\\\"}\"),\n                        objectMapper.readTree(\"\\\"val1\\\"\"),\n                        TextNode.class,\n                        objectMapper.readTree(\"{\"\n                                + \"    \\\"attr1\\\": {\\\"attr1\\\": \\\"val1\\\"},\"\n                                + \"    \\\"attr2\\\": \\\"val2\\\"\"\n                                + \"}\")),\n                // Multi-value JSON path\n                new TestData(\n                        parseContext.parse(\"{\"\n                                + \"    \\\"attr1\\\":  [\\\"val1\\\", \\\"val2\\\"],\"\n                                + \"    \\\"attr2\\\":  \\\"val2\\\"\"\n                                + \"}\"),\n                        \"$.attr1[*]\",\n                        objectMapper.readTree(\"{\\\"attr1\\\": \\\"val1\\\"}\"),\n                        objectMapper.readTree(\"[\\\"val1\\\", \\\"val2\\\"]\"),\n                        TextNode.class,\n                        objectMapper.readTree(\"{\"\n                                + \"    \\\"attr1\\\": [{\\\"attr1\\\": \\\"val1\\\"}, {\\\"attr1\\\": \\\"val1\\\"}],\"\n                                + \"    \\\"attr2\\\": \\\"val2\\\"\"\n                                + \"}\")),\n                // Multi-value object JSON path\n                new TestData(\n                        parseContext.parse(\"{\"\n                                + \"    \\\"attr1\\\":  [\"\n                                + \"         {\\\"inAttr1\\\": \\\"val1a\\\", \\\"inAttr2\\\": \\\"val2a\\\"},\"\n                                + \"         {\\\"inAttr1\\\": \\\"val1a\\\", \\\"inAttr2\\\": \\\"val2b\\\"},\"\n                                + \"         {\\\"inAttr1\\\": \\\"val1b\\\", \\\"inAttr2\\\": \\\"val2c\\\"}\"\n                                + \"    ],\"\n                                + \"    \\\"attr2\\\":  \\\"val2\\\"\"\n                                + \"}\"),\n                        \"$.attr1.[?(@.inAttr1 == \\\"val1a\\\")].inAttr2\",\n                        objectMapper.readTree(\"{\\\"attr1\\\": \\\"val1\\\"}\"),\n                        objectMapper.readTree(\"[\\\"val2a\\\", \\\"val2b\\\"]\"),\n                        TextNode.class,\n                        objectMapper.readTree(\"{\"\n                                + \"    \\\"attr1\\\": [\"\n                                + \"         {\\\"inAttr1\\\": \\\"val1a\\\", \\\"inAttr2\\\": {\\\"attr1\\\": \\\"val1\\\"}},\"\n                                + \"         {\\\"inAttr1\\\": \\\"val1a\\\", \\\"inAttr2\\\": {\\\"attr1\\\": \\\"val1\\\"}},\"\n                                + \"         {\\\"inAttr1\\\": \\\"val1b\\\", \\\"inAttr2\\\": \\\"val2c\\\"}\"\n                                + \"    ],\"\n                                + \"    \\\"attr2\\\": \\\"val2\\\"\"\n                                + \"}\"))\n        );\n    }\n\n    private static DocumentContext cloneDocumentContext(DocumentContext documentContext) {\n        return JsonPath.using(documentContext.configuration()).parse(documentContext.jsonString());\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/JacksonJsonNodeJsonProviderTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport com.fasterxml.jackson.annotation.JsonCreator;\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.SerializationFeature;\nimport com.fasterxml.jackson.databind.node.ArrayNode;\nimport com.fasterxml.jackson.databind.node.JsonNodeFactory;\nimport com.fasterxml.jackson.databind.node.ObjectNode;\nimport com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider;\nimport com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.MappingException;\nimport java.nio.charset.StandardCharsets;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.util.List;\nimport java.util.UUID;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class JacksonJsonNodeJsonProviderTest extends BaseTest {\n\n    private static final String JSON =\n            \"[\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo0\\\",\\n\" +\n            \"   \\\"bar\\\" : 0,\\n\" +\n            \"   \\\"baz\\\" : true,\\n\" +\n            \"   \\\"gen\\\" : {\\\"eric\\\" : \\\"yepp\\\"}\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo1\\\",\\n\" +\n            \"   \\\"bar\\\" : 1,\\n\" +\n            \"   \\\"baz\\\" : true,\\n\" +\n            \"   \\\"gen\\\" : {\\\"eric\\\" : \\\"yepp\\\"}\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo2\\\",\\n\" +\n            \"   \\\"bar\\\" : 2,\\n\" +\n            \"   \\\"baz\\\" : true,\\n\" +\n            \"   \\\"gen\\\" : {\\\"eric\\\" : \\\"yepp\\\"}\" +\n            \"}\" +\n            \"]\";\n\n    @Test\n    public void json_can_be_parsed() {\n        ObjectNode node = using(JACKSON_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$\");\n        assertThat(node.get(\"string-property\").asText()).isEqualTo(\"string-value\");\n    }\n\n    @Test\n    public void bytes_json_can_be_parsed() {\n        ObjectNode node = using(JACKSON_JSON_NODE_CONFIGURATION).parseUtf8(JSON_DOCUMENT.getBytes(StandardCharsets.UTF_8))\n            .read(\"$\");\n        assertThat(node.get(\"string-property\").asText()).isEqualTo(\"string-value\");\n    }\n\n    @Test\n    public void always_return_same_object() { // Test because of Bug #211\n    \tDocumentContext context = using(JACKSON_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT);\n        ObjectNode node1 = context.read(\"$\");\n        ObjectNode child1 = new ObjectNode(JsonNodeFactory.instance);\n        child1.put(\"name\", \"test\");\n        context.put(\"$\", \"child\", child1);\n        ObjectNode node2 = context.read(\"$\");\n        ObjectNode child2 = context.read(\"$.child\");\n\n        assertThat(node1).isSameAs(node2);\n        assertThat(child1).isSameAs(child2);\n    }\n\n    @Test\n    public void strings_are_unwrapped() {\n        JsonNode node = using(JACKSON_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.string-property\");\n        String unwrapped = using(JACKSON_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.string-property\", String.class);\n\n        assertThat(unwrapped).isEqualTo(\"string-value\");\n        assertThat(unwrapped).isEqualTo(node.asText());\n    }\n\n    @Test\n    public void ints_are_unwrapped() {\n        JsonNode node = using(JACKSON_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.int-max-property\");\n        int unwrapped = using(JACKSON_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.int-max-property\", int.class);\n        assertThat(unwrapped).isEqualTo(Integer.MAX_VALUE);\n        assertThat(unwrapped).isEqualTo(node.asInt());\n    }\n\n    @Test\n    public void longs_are_unwrapped() {\n        JsonNode node = using(JACKSON_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.long-max-property\");\n        long unwrapped = using(JACKSON_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.long-max-property\", long.class);\n\n        assertThat(unwrapped).isEqualTo(Long.MAX_VALUE);\n        assertThat(unwrapped).isEqualTo(node.asLong());\n    }\n\n    @Test\n    public void list_of_numbers() {\n        ArrayNode objs = using(JACKSON_JSON_NODE_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.store.book[*].display-price\");\n\n        assertThat(objs.get(0).asDouble()).isEqualTo(8.95D);\n        assertThat(objs.get(1).asDouble()).isEqualTo(12.99D);\n        assertThat(objs.get(2).asDouble()).isEqualTo(8.99D);\n        assertThat(objs.get(3).asDouble()).isEqualTo(22.99D);\n    }\n\n    ObjectMapper objectMapperDecimal = new ObjectMapper().configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);\n    Configuration JACKSON_JSON_NODE_CONFIGURATION_DECIMAL = Configuration\n            .builder()\n            .mappingProvider(new JacksonMappingProvider())\n            .jsonProvider(new JacksonJsonNodeJsonProvider(objectMapperDecimal))\n            .build();\n\n    @Test\n    public void bigdecimals_are_unwrapped() {\n        final BigDecimal bd = BigDecimal.valueOf(Long.MAX_VALUE).add(BigDecimal.valueOf(10.5));\n        final String json = \"{\\\"bd-property\\\" : \" + bd.toString() + \"}\";\n\n        JsonNode node =  using(JACKSON_JSON_NODE_CONFIGURATION_DECIMAL).parse(json).read(\"$.bd-property\");\n        BigDecimal val =  using(JACKSON_JSON_NODE_CONFIGURATION_DECIMAL).parse(json).read(\"$.bd-property\", BigDecimal.class);\n\n        assertThat(node.isBigDecimal()).isTrue();\n        assertThat(val).isEqualTo(bd);\n        assertThat(val).isEqualTo(node.decimalValue());\n    }\n\n    @Test\n    public void small_bigdecimals_are_unwrapped() {\n        final BigDecimal bd = BigDecimal.valueOf(10.5);\n        final String json = \"{\\\"bd-property\\\" : \" + bd.toString() + \"}\";\n\n        JsonNode node =  using(JACKSON_JSON_NODE_CONFIGURATION_DECIMAL).parse(json).read(\"$.bd-property\");\n        BigDecimal val =  using(JACKSON_JSON_NODE_CONFIGURATION_DECIMAL).parse(json).read(\"$.bd-property\", BigDecimal.class);\n\n        assertThat(node.isBigDecimal()).isTrue();\n        assertThat(val).isEqualTo(bd);\n        assertThat(val).isEqualTo(node.decimalValue());\n    }\n\n    ObjectMapper objectMapperBigInteger = new ObjectMapper().configure(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS, true);\n    Configuration JACKSON_JSON_NODE_CONFIGURATION_Big_Integer = Configuration\n            .builder()\n            .mappingProvider(new JacksonMappingProvider())\n            .jsonProvider(new JacksonJsonNodeJsonProvider(objectMapperBigInteger))\n            .build();\n\n    @Test\n    public void bigintegers_are_unwrapped() {\n        final BigInteger bi = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.TEN);\n        final String json = \"{\\\"bi-property\\\" : \" + bi.toString() + \"}\";\n\n        JsonNode node =  using(JACKSON_JSON_NODE_CONFIGURATION_Big_Integer).parse(json).read(\"$.bi-property\");\n        BigInteger val =  using(JACKSON_JSON_NODE_CONFIGURATION_Big_Integer).parse(json).read(\"$.bi-property\", BigInteger.class);\n\n        assertThat(node.isBigInteger()).isTrue();\n        assertThat(val).isEqualTo(bi);\n        assertThat(val).isEqualTo(node.bigIntegerValue());\n    }\n\n    @Test\n    public void small_bigintegers_are_unwrapped() {\n        final BigInteger bi = BigInteger.valueOf(Long.MAX_VALUE);\n        final String json = \"{\\\"bi-property\\\" : \" + bi.toString() + \"}\";\n\n        JsonNode node =  using(JACKSON_JSON_NODE_CONFIGURATION_Big_Integer).parse(json).read(\"$.bi-property\");\n        BigInteger val =  using(JACKSON_JSON_NODE_CONFIGURATION_Big_Integer).parse(json).read(\"$.bi-property\", BigInteger.class);\n\n        assertThat(node.isBigInteger()).isTrue();\n        assertThat(val).isEqualTo(bi);\n        assertThat(val).isEqualTo(node.bigIntegerValue());\n    }\n\n    @Test\n    public void test_type_ref() throws IOException {\n        TypeRef<List<FooBarBaz<Gen>>> typeRef = new TypeRef<List<FooBarBaz<Gen>>>() {};\n\n        List<FooBarBaz<Gen>> list = using(JACKSON_JSON_NODE_CONFIGURATION).parse(JSON).read(\"$\", typeRef);\n\n        assertThat(list.get(0).gen.eric).isEqualTo(\"yepp\");\n    }\n\n    @Test\n    public void test_type_ref_fail() throws IOException {\n        TypeRef<List<FooBarBaz<Integer>>> typeRef = new TypeRef<List<FooBarBaz<Integer>>>() {};\n\n        Assertions.assertThrows(MappingException.class, () -> using(JACKSON_JSON_NODE_CONFIGURATION).parse(JSON).read(\"$\", typeRef));\n    }\n\n    @Test\n    public void mapPropertyWithPOJO() {\n        String someJson = \"\" +\n                \"{\\n\" +\n                \"  \\\"a\\\": \\\"a\\\",\\n\" +\n                \"  \\\"b\\\": \\\"b\\\"\\n\" +\n                \"}\";\n        ObjectMapper om = new ObjectMapper();\n        om.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);\n        Configuration c = Configuration\n                .builder()\n                .mappingProvider(new JacksonMappingProvider())\n                .jsonProvider(new JacksonJsonNodeJsonProvider(om))\n                .build();\n        DocumentContext context = JsonPath.using(c).parse(someJson);\n        String someJsonStr = context.jsonString();\n        DocumentContext altered = context.map(\"$['a', 'b', 'c']\", new MapFunction() {\n            @Override\n            public Object map(Object currentValue, Configuration configuration) {\n                return currentValue;\n            }\n        });\n        assertThat(altered.jsonString()).isEqualTo(someJsonStr);\n    }\n\n    @Test\n    // https://github.com/json-path/JsonPath/issues/364\n    public void setPropertyWithPOJO() {\n      DocumentContext context = JsonPath.using(JACKSON_JSON_NODE_CONFIGURATION).parse(\"{}\");\n      UUID uuid = UUID.randomUUID();\n      context.put(\"$\", \"data\", new Data(uuid));\n      String id = context.read(\"$.data.id\", String.class);\n      assertThat(id).isEqualTo(uuid.toString());\n    }\n    // https://github.com/json-path/JsonPath/issues/366\n    public void empty_array_check_works() throws IOException {\n      String json = \"[\" +\n          \"  {\" +\n          \"    \\\"name\\\": \\\"a\\\",\" +\n          \"    \\\"groups\\\": [{\" +\n          \"      \\\"type\\\": \\\"phase\\\",\" +\n          \"      \\\"name\\\": \\\"alpha\\\"\" +\n          \"    }, {\" +\n          \"      \\\"type\\\": \\\"not_phase\\\",\" +\n          \"      \\\"name\\\": \\\"beta\\\"\" +\n          \"    }]\" +\n          \"  }, {\" +\n          \"    \\\"name\\\": \\\"b\\\",\" +\n          \"    \\\"groups\\\": [{\" +\n          \"      \\\"type\\\": \\\"phase\\\",\" +\n          \"      \\\"name\\\": \\\"beta\\\"\" +\n          \"    }, {\" +\n          \"      \\\"type\\\": \\\"not_phase\\\",\" +\n          \"      \\\"name\\\": \\\"alpha\\\"\" +\n          \"    }]\" +\n          \"  }\" +\n          \"]\";\n      ArrayNode node = using(JACKSON_JSON_NODE_CONFIGURATION).parse(json).read(\"$[?(@.groups[?(@.type == 'phase' && @.name == 'alpha')] empty false)]\");\n      assertThat(node.size()).isEqualTo(1);\n      assertThat(node.get(0).get(\"name\").asText()).isEqualTo(\"a\");\n    }\n\n    public static class FooBarBaz<T> {\n        public T gen;\n        public String foo;\n        public Long bar;\n        public boolean baz;\n    }\n\n\n    public static class Gen {\n        public String eric;\n    }\n\n    public static final class Data {\n      @JsonProperty(\"id\")\n      UUID id;\n\n      @JsonCreator\n      Data(@JsonProperty(\"id\") final UUID id) {\n        this.id = id;\n      }\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/JacksonTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Date;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\nimport static java.util.Collections.singletonMap;\nimport static org.assertj.core.api.Assertions.assertThat;\n\n\npublic class JacksonTest extends BaseTest {\n\n    @Test\n    public void an_object_can_be_mapped_to_pojo() {\n\n        String json = \"{\\n\" +\n                \"   \\\"foo\\\" : \\\"foo\\\",\\n\" +\n                \"   \\\"bar\\\" : 10,\\n\" +\n                \"   \\\"baz\\\" : true\\n\" +\n                \"}\";\n\n\n        FooBarBaz fooBarBaz = JsonPath.using(JACKSON_CONFIGURATION).parse(json).read(\"$\", FooBarBaz.class);\n\n        assertThat(fooBarBaz.foo).isEqualTo(\"foo\");\n        assertThat(fooBarBaz.bar).isEqualTo(10L);\n        assertThat(fooBarBaz.baz).isEqualTo(true);\n\n        fooBarBaz = JsonPath.using(JACKSON_CONFIGURATION).parseUtf8(json.getBytes(UTF_8))\n            .read(\"$\", FooBarBaz.class);\n\n        assertThat(fooBarBaz.foo).isEqualTo(\"foo\");\n        assertThat(fooBarBaz.bar).isEqualTo(10L);\n        assertThat(fooBarBaz.baz).isEqualTo(true);\n    }\n\n    public static class FooBarBaz {\n        public String foo;\n        public Long bar;\n        public boolean baz;\n    }\n\n    @Test\n    public void jackson_converts_dates() {\n\n        Date now = new Date();\n\n        Object json = singletonMap(\"date_as_long\", now.getTime());\n\n        Date date = JsonPath.using(JACKSON_CONFIGURATION).parse(json).read(\"$['date_as_long']\", Date.class);\n\n        assertThat(date).isEqualTo(now);\n    }\n\n    @Test\n    // https://github.com/jayway/JsonPath/issues/275\n    public void single_quotes_work_with_in_filter() {\n        final String jsonArray = \"[{\\\"foo\\\": \\\"bar\\\"}, {\\\"foo\\\": \\\"baz\\\"}]\";\n        final Object readFromSingleQuote = JsonPath.using(JACKSON_CONFIGURATION).parse(jsonArray).read(\"$.[?(@.foo in ['bar'])].foo\");\n        final Object readFromDoubleQuote = JsonPath.using(JACKSON_CONFIGURATION).parse(jsonArray).read(\"$.[?(@.foo in [\\\"bar\\\"])].foo\");\n        assertThat(readFromSingleQuote).isEqualTo(readFromDoubleQuote);\n        final Object readFromSingleQuoteBytes = JsonPath.using(JACKSON_CONFIGURATION).parseUtf8(jsonArray.getBytes(UTF_8))\n            .read(\"$.[?(@.foo in ['bar'])].foo\");\n        final Object readFromDoubleQuoteBytes = JsonPath.using(JACKSON_CONFIGURATION).parseUtf8(jsonArray.getBytes(UTF_8))\n            .read(\"$.[?(@.foo in [\\\"bar\\\"])].foo\");\n        assertThat(readFromSingleQuoteBytes).isEqualTo(readFromDoubleQuoteBytes);\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/JakartaJsonProviderTest.java",
    "content": "package com.jayway.jsonpath;\r\n\r\nimport jakarta.json.JsonObject;\r\nimport jakarta.json.JsonString;\r\nimport org.junit.jupiter.api.Test;\r\n\r\nimport java.io.InputStream;\r\nimport java.util.HashMap;\r\nimport java.util.List;\r\nimport java.util.Map;\r\n\r\nimport static com.jayway.jsonpath.JsonPath.parse;\r\nimport static com.jayway.jsonpath.JsonPath.using;\r\nimport static java.nio.charset.StandardCharsets.UTF_8;\r\nimport static java.util.Collections.emptyMap;\r\nimport static org.assertj.core.api.Assertions.assertThat;\r\nimport static org.junit.jupiter.api.Assertions.assertThrows;\r\n\r\n\r\npublic class JakartaJsonProviderTest extends BaseTest {\r\n\r\n    private static final Map<String, Object> EMPTY_MAP = emptyMap();\r\n\r\n    @Test\r\n    public void an_object_can_be_read() {\r\n        JsonObject book = using(JAKARTA_JSON_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .read(\"$.store.book[0]\");\r\n\r\n        assertThat(((JsonString) book.get(\"author\")).getChars()).isEqualTo(\"Nigel Rees\");\r\n    }\r\n\r\n    @Test\r\n    public void an_object_can_be_read_from_bytes() {\r\n        JsonObject book = using(JAKARTA_JSON_CONFIGURATION)\r\n                .parseUtf8(JSON_DOCUMENT.getBytes(UTF_8))\r\n                .read(\"$.store.book[0]\");\r\n\r\n        assertThat(((JsonString) book.get(\"author\")).getChars()).isEqualTo(\"Nigel Rees\");\r\n    }\r\n\r\n    @Test\r\n    public void a_property_can_be_read() {\r\n        JsonString category = using(JAKARTA_JSON_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .read(\"$.store.book[0].category\");\r\n\r\n        assertThat(category.getString()).isEqualTo(\"reference\");\r\n    }\r\n\r\n    @Test\r\n    public void a_filter_can_be_applied() {\r\n        List<Object> fictionBooks = using(JAKARTA_JSON_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .read(\"$.store.book[?(@.category == 'fiction')]\");\r\n\r\n        assertThat(fictionBooks.size()).isEqualTo(3);\r\n    }\r\n\r\n    @Test\r\n    public void result_can_be_mapped_to_object() {\r\n        @SuppressWarnings(\"unchecked\")\r\n        List<Map<String, Object>> books = using(JAKARTA_JSON_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .read(\"$.store.book\", List.class);\r\n\r\n        assertThat(books.size()).isEqualTo(4);\r\n    }\r\n\r\n    @Test\r\n    public void read_books_with_isbn() {\r\n        List<Object> books = using(JAKARTA_JSON_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$..book[?(@.isbn)]\");\r\n\r\n        assertThat(books.size()).isEqualTo(2);\r\n    }\r\n\r\n    /**\r\n     * Functions take parameters, the length parameter for example takes an entire document which we anticipate\r\n     * will compute to a document that is an array of elements which can determine its length.\r\n     * <p>\r\n     * Since we translate this query from $..books.length() to length($..books) verify that this particular translation\r\n     * works as anticipated.\r\n     */\r\n    @Test\r\n    public void read_book_length_using_translated_query() {\r\n        Integer result = using(JAKARTA_JSON_CONFIGURATION)\r\n                .parse(JSON_BOOK_STORE_DOCUMENT)\r\n                .read(\"$..book.length()\");\r\n        assertThat(result).isEqualTo(4);\r\n    }\r\n\r\n    @Test\r\n    public void read_book_length() {\r\n        Object result = using(JAKARTA_JSON_CONFIGURATION)\r\n                .parse(JSON_BOOK_STORE_DOCUMENT)\r\n                .read(\"$.length($..book)\");\r\n        assertThat(result).isEqualTo(4);\r\n    }\r\n\r\n    @Test\r\n    public void issue_97() {\r\n        String json = \"{ \\\"books\\\": [ \" +\r\n                \"{ \\\"category\\\": \\\"fiction\\\" }, \" +\r\n                \"{ \\\"category\\\": \\\"reference\\\" }, \" +\r\n                \"{ \\\"category\\\": \\\"fiction\\\" }, \" +\r\n                \"{ \\\"category\\\": \\\"fiction\\\" }, \" +\r\n                \"{ \\\"category\\\": \\\"reference\\\" }, \" +\r\n                \"{ \\\"category\\\": \\\"fiction\\\" }, \" +\r\n                \"{ \\\"category\\\": \\\"reference\\\" }, \" +\r\n                \"{ \\\"category\\\": \\\"reference\\\" }, \" +\r\n                \"{ \\\"category\\\": \\\"reference\\\" }, \" +\r\n                \"{ \\\"category\\\": \\\"reference\\\" }, \" +\r\n                \"{ \\\"category\\\": \\\"reference\\\" } ]  }\";\r\n\r\n        DocumentContext dc = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(json)\r\n                .delete(\"$.books[?(@.category == 'reference')]\");\r\n        //System.out.println((Object) dc.read(\"$\"));\r\n        @SuppressWarnings(\"unchecked\")\r\n        List<String> categories = dc.read(\"$..category\", List.class);\r\n\r\n        assertThat(categories).containsOnly(\"fiction\");\r\n    }\r\n\r\n    @Test\r\n    public void test_delete_2() {\r\n        DocumentContext dc = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(\"[\" +\r\n                        \"{\\\"top\\\": {\\\"middle\\\": null}},\" +\r\n                        \"{\\\"top\\\": {\\\"middle\\\": {}  }},\" +\r\n                        \"{\\\"top\\\": {\\\"middle\\\": {\\\"bottom\\\": 2}  }}\" +\r\n                        \"]\")\r\n                .delete(JsonPath.compile(\"$[*].top.middle.bottom\"));\r\n        Object ans = dc.read(\"$\");\r\n        //System.out.println(ans);\r\n        assert (ans.toString().equals(\"[{\\\"top\\\":{\\\"middle\\\":null}},{\\\"top\\\":{\\\"middle\\\":{}}},{\\\"top\\\":{\\\"middle\\\":{}}}]\"));\r\n    }\r\n\r\n    @Test\r\n    public void an_root_property_can_be_updated() {\r\n        Object o = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .set(\"$.int-max-property\", 1)\r\n                .json();\r\n\r\n        Integer result = using(JAKARTA_JSON_RW_CONFIGURATION).parse(o)\r\n                .read(\"$.int-max-property\", Integer.class);\r\n\r\n        assertThat(result).isEqualTo(1);\r\n    }\r\n\r\n    @Test\r\n    public void an_deep_scan_can_update() {\r\n        Object o = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .set(\"$..display-price\", 1)\r\n                .json();\r\n\r\n        List<Integer> result = using(JAKARTA_JSON_RW_CONFIGURATION).parse(o)\r\n                .read(\"$..display-price\", new TypeRef<List<Integer>>() {\r\n                });\r\n\r\n        assertThat(result).containsExactly(1, 1, 1, 1, 1);\r\n    }\r\n\r\n    @Test\r\n    public void an_filter_can_update() {\r\n        final String updatePathFunction = \"$.store.book[?(@.display-price)].display-price\";\r\n        Object o = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .set(updatePathFunction, 1)\r\n                .json();\r\n\r\n        List<Integer> result = using(JAKARTA_JSON_RW_CONFIGURATION).parse(o)\r\n                .read(updatePathFunction, new TypeRef<List<Integer>>() {\r\n                });\r\n\r\n        assertThat(result).containsExactly(1, 1, 1, 1);\r\n    }\r\n\r\n    @Test\r\n    public void a_path_can_be_deleted() {\r\n        final String deletePath = \"$.store.book[*].display-price\";\r\n        Object o = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .delete(deletePath)\r\n                .json();\r\n\r\n        List<Integer> result = using(JAKARTA_JSON_RW_CONFIGURATION).parse(o)\r\n                .read(deletePath, new TypeRef<List<Integer>>() {\r\n                });\r\n\r\n        assertThat(result).isEmpty();\r\n    }\r\n\r\n    @Test\r\n    public void operations_can_chained() {\r\n        Object o = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .delete(\"$.store.book[*].display-price\")\r\n                .set(\"$.store.book[*].category\", \"A\")\r\n                .json();\r\n\r\n        List<Integer> prices = using(JAKARTA_JSON_RW_CONFIGURATION).parse(o)\r\n                .read(\"$.store.book[*].display-price\", new TypeRef<List<Integer>>() {\r\n                });\r\n        List<String> categories = using(JAKARTA_JSON_RW_CONFIGURATION).parse(o)\r\n                .read(\"$.store.book[*].category\", new TypeRef<List<String>>() {\r\n                });\r\n\r\n        assertThat(prices).isEmpty();\r\n        assertThat(categories).containsExactly(\"A\", \"A\", \"A\", \"A\");\r\n    }\r\n\r\n    @Test\r\n    public void an_array_index_can_be_updated() {\r\n        String res = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .set(\"$.store.book[0]\", \"a\")\r\n                .read(\"$.store.book[0]\", String.class);\r\n\r\n        assertThat(res).isEqualTo(\"a\");\r\n    }\r\n\r\n    @Test\r\n    public void an_array_slice_can_be_updated() {\r\n        List<String> res = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .set(\"$.store.book[0:2]\", \"a\")\r\n                .read(\"$.store.book[0:2]\", new TypeRef<List<String>>() {\r\n                });\r\n\r\n        assertThat(res).containsExactly(\"a\", \"a\");\r\n    }\r\n\r\n    @Test\r\n    public void an_array_criteria_can_be_updated() {\r\n        List<String> res = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .set(\"$.store.book[?(@.category == 'fiction')]\", \"a\")\r\n                .read(\"$.store.book[?(@ == 'a')]\", new TypeRef<List<String>>() {\r\n                });\r\n\r\n        assertThat(res).containsExactly(\"a\", \"a\", \"a\");\r\n    }\r\n\r\n    @Test\r\n    public void an_array_criteria_can_be_deleted() {\r\n        List<String> res = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .delete(\"$.store.book[?(@.category == 'fiction')]\")\r\n                .read(\"$.store.book[*].category\", new TypeRef<List<String>>() {\r\n                });\r\n\r\n        assertThat(res).containsExactly(\"reference\");\r\n    }\r\n\r\n    @Test\r\n    public void an_array_criteria_with_multiple_results_can_be_deleted() {\r\n        InputStream stream = this.getClass().getResourceAsStream(\"/json_array_multiple_delete.json\");\r\n        String deletePath = \"$._embedded.mandates[?(@.count=~/0/)]\";\r\n        DocumentContext dc = using(JAKARTA_JSON_RW_CONFIGURATION).parse(stream).delete(deletePath);\r\n        List<Object> result = dc.read(deletePath);\r\n        assertThat(result.size()).isEqualTo(0);\r\n    }\r\n\r\n    @Test\r\n    public void multi_prop_delete() {\r\n        List<Map<String, Object>> res = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .delete(\"$.store.book[*]['author', 'category']\")\r\n                .read(\"$.store.book[*]['author', 'category']\", new TypeRef<List<Map<String, Object>>>() {\r\n                });\r\n\r\n        assertThat(res).containsExactly(EMPTY_MAP, EMPTY_MAP, EMPTY_MAP, EMPTY_MAP);\r\n    }\r\n\r\n    @Test\r\n    public void multi_prop_update() {\r\n        @SuppressWarnings(\"serial\")\r\n        Map<String, Object> expected = new HashMap<String, Object>() {{\r\n            put(\"author\", \"a\");\r\n            put(\"category\", \"a\");\r\n        }};\r\n        List<Map<String, Object>> res = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .set(\"$.store.book[*]['author', 'category']\", \"a\")\r\n                .read(\"$.store.book[*]['author', 'category']\", new TypeRef<List<Map<String, Object>>>() {\r\n                });\r\n        assertThat(res).containsExactly(expected, expected, expected, expected);\r\n    }\r\n\r\n    @Test\r\n    public void add_to_array() {\r\n        Object res = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .add(\"$.store.book\", 1)\r\n                .read(\"$.store.book[4]\");\r\n        res = JAKARTA_JSON_RW_CONFIGURATION.jsonProvider().unwrap(res);\r\n        assertThat(res).isEqualTo(1);\r\n    }\r\n\r\n    @Test\r\n    public void add_to_object() {\r\n        Object res = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .put(\"$.store.book[0]\", \"new-key\", \"new-value\")\r\n                .read(\"$.store.book[0].new-key\");\r\n        res = JAKARTA_JSON_RW_CONFIGURATION.jsonProvider().unwrap(res);\r\n        assertThat(res).isEqualTo(\"new-value\");\r\n    }\r\n\r\n    @Test\r\n    public void add_to_object_on_array() {\r\n        assertThrows(InvalidModificationException.class, () -> using(JAKARTA_JSON_RW_CONFIGURATION).parse(JSON_DOCUMENT).put(\"$.store.book\", \"new-key\", \"new-value\"));\r\n    }\r\n\r\n    @Test\r\n    public void add_to_array_on_object() {\r\n        assertThrows(InvalidModificationException.class, () -> using(JAKARTA_JSON_RW_CONFIGURATION).parse(JSON_DOCUMENT).add(\"$.store.book[0]\", \"new-value\"));\r\n    }\r\n\r\n    @Test\r\n    public void a_path_can_be_renamed() {\r\n        Object o = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .renameKey(\"$.store\", \"book\", \"updated-book\")\r\n                .json();\r\n        List<Object> result = parse(o).read(\"$.store.updated-book\");\r\n\r\n        assertThat(result).isNotEmpty();\r\n    }\r\n\r\n    @Test\r\n    public void map_array_items_can_be_renamed() {\r\n        Object o = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .renameKey(\"$.store.book[*]\", \"category\", \"renamed-category\")\r\n                .json();\r\n        List<Object> result = parse(o).read(\"$.store.book[*].renamed-category\");\r\n        assertThat(result).isNotEmpty();\r\n    }\r\n\r\n    @Test\r\n    public void non_existent_key_rename_not_allowed() {\r\n        assertThrows(PathNotFoundException.class, () -> using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .renameKey(\"$\", \"fake\", \"new-fake\")\r\n                .json());\r\n    }\r\n\r\n    @Test\r\n    public void single_match_value_can_be_mapped() {\r\n        MapFunction mapFunction = new ToStringMapFunction();\r\n        String stringResult = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .map(\"$.string-property\", mapFunction)\r\n                .read(\"$.string-property\", String.class);\r\n        assertThat(stringResult.endsWith(\"converted\")).isTrue();\r\n    }\r\n\r\n    @Test\r\n    public void object_can_be_mapped() {\r\n        TypeRef<List<String>> typeRef = new TypeRef<List<String>>() {\r\n        };\r\n        MapFunction mapFunction = new ToStringMapFunction();\r\n        DocumentContext dc = using(JAKARTA_JSON_RW_CONFIGURATION).parse(JSON_DOCUMENT);\r\n        Object list = dc.read(\"$..book\");\r\n        assertThat(list).isInstanceOf(List.class);\r\n        Object res = dc.map(\"$..book\", mapFunction).read(\"$..book\", typeRef).get(0);\r\n        assertThat(res).isInstanceOf(String.class);\r\n        assertThat((String) res).endsWith(\"converted\");\r\n    }\r\n\r\n    @Test\r\n    public void multi_match_path_can_be_mapped() {\r\n        MapFunction mapFunction = new ToStringMapFunction();\r\n        List<Double> doubleResult = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .read(\"$..display-price\", new TypeRef<List<Double>>() {\r\n                });\r\n        for (Double dRes : doubleResult) {\r\n            assertThat(dRes).isInstanceOf(Double.class);\r\n        }\r\n        List<String> stringResult = using(JAKARTA_JSON_RW_CONFIGURATION)\r\n                .parse(JSON_DOCUMENT)\r\n                .map(\"$..display-price\", mapFunction)\r\n                .read(\"$..display-price\", new TypeRef<List<String>>() {\r\n                });\r\n        for (String sRes : stringResult) {\r\n            assertThat(sRes).isInstanceOf(String.class);\r\n            assertThat(sRes.endsWith(\"converted\")).isTrue();\r\n        }\r\n    }\r\n\r\n    // Helper converter implementation for test cases.\r\n    private class ToStringMapFunction implements MapFunction {\r\n\r\n        @Override\r\n        public Object map(Object currentValue, Configuration configuration) {\r\n            return currentValue.toString() + \"converted\";\r\n        }\r\n    }\r\n\r\n}\r\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/JsonOrgJsonProviderTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport com.jayway.jsonpath.spi.json.JsonOrgJsonProvider;\nimport com.jayway.jsonpath.spi.mapper.JsonOrgMappingProvider;\nimport org.json.JSONArray;\nimport org.json.JSONObject;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class JsonOrgJsonProviderTest extends BaseTest {\n\n\n    @Test\n    public void an_object_can_be_read() {\n\n        JSONObject book = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.store.book[0]\");\n\n        assertThat(book.get(\"author\").toString()).isEqualTo(\"Nigel Rees\");\n    }\n\n    @Test\n    public void a_property_can_be_read() {\n\n        String category = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.store.book[0].category\");\n\n        assertThat(category).isEqualTo(\"reference\");\n    }\n\n    @Test\n    public void a_filter_can_be_applied() {\n\n        JSONArray fictionBooks = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.store.book[?(@.category == 'fiction')]\");\n\n        assertThat(fictionBooks.length()).isEqualTo(3);\n    }\n\n    @Test\n    public void result_can_be_mapped_to_object() {\n\n        List<Map<String, Object>> books = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.store.book\", List.class);\n\n        assertThat(books.size()).isEqualTo(4);\n    }\n\n    @Test\n    public void read_books_with_isbn() {\n\n        JSONArray books = using(JSON_ORG_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$..book[?(@.isbn)]\");\n\n        assertThat(books.length()).isEqualTo(2);\n    }\n\n    /**\n     * Functions take parameters, the length parameter for example takes an entire document which we anticipate\n     * will compute to a document that is an array of elements which can determine its length.\n     *\n     * Since we translate this query from $..books.length() to length($..books) verify that this particular translation\n     * works as anticipated.\n     */\n    @Test\n    public void read_book_length_using_translated_query() {\n        Integer result = using(Configuration.defaultConfiguration())\n                .parse(JSON_BOOK_STORE_DOCUMENT)\n                .read(\"$..book.length()\");\n        assertThat(result).isEqualTo(4);\n    }\n\n    @Test\n    public void read_book_length() {\n        Object result = using(Configuration.defaultConfiguration())\n                .parse(JSON_BOOK_STORE_DOCUMENT)\n                .read(\"$.length($..book)\");\n        assertThat(result).isEqualTo(4);\n    }\n\n    @Test\n    public void test_getPropertyKeys_empty_object() {\n        String json = \"{\\\"foo\\\": \\\"bar\\\", \\\"emptyObject\\\": {},\\\"emptyList\\\":[]}\";\n        Configuration config = Configuration.defaultConfiguration()\n                .jsonProvider(new JsonOrgJsonProvider())\n                .mappingProvider(new JsonOrgMappingProvider());\n        Object result = JsonPath.using(config).parse(json).read(\"$..foo\");\n        assertThat(result.toString()).isEqualTo(\"[\\\"bar\\\"]\");\n    }\n\n    @Test\n    public void test_getPropertyKeys_empty_nest_object() {\n        String json = \"{\\\"foo\\\": \\\"bar\\\", \\\"emptyObject\\\": {\\\"emptyList\\\":[]},\\\"emptyList\\\":[]}\";\n        Configuration config = Configuration.defaultConfiguration()\n                .jsonProvider(new JsonOrgJsonProvider())\n                .mappingProvider(new JsonOrgMappingProvider());\n        Object result = JsonPath.using(config).parse(json).read(\"$..foo\");\n        assertThat(result.toString()).isEqualTo(\"[\\\"bar\\\"]\");\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/JsonProviderTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class JsonProviderTest extends BaseTest {\n\n    public static Iterable<Configuration> configurations() {\n        return Configurations.configurations();\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void strings_are_unwrapped(Configuration conf) {\n        assertThat(using(conf).parse(JSON_DOCUMENT).read(\"$.string-property\", String.class)).isEqualTo(\"string-value\");\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void integers_are_unwrapped(Configuration conf) {\n        assertThat(using(conf).parse(JSON_DOCUMENT).read(\"$.int-max-property\", Integer.class)).isEqualTo(Integer.MAX_VALUE);\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void ints_are_unwrapped(Configuration conf) {\n        assertThat(using(conf).parse(JSON_DOCUMENT).read(\"$.int-max-property\", int.class)).isEqualTo(Integer.MAX_VALUE);\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/JsonProviderTestObjectMapping.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\nimport java.io.IOException;\nimport java.util.List;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class JsonProviderTestObjectMapping extends BaseTest {\n\n    private static final String JSON =\n            \"[\" +\n                    \"{\\n\" +\n                    \"   \\\"foo\\\" : \\\"foo0\\\",\\n\" +\n                    \"   \\\"bar\\\" : 0,\\n\" +\n                    \"   \\\"baz\\\" : true,\\n\" +\n                    \"   \\\"gen\\\" : {\\\"prop\\\" : \\\"yepp0\\\"}\" +\n                    \"},\" +\n                    \"{\\n\" +\n                    \"   \\\"foo\\\" : \\\"foo1\\\",\\n\" +\n                    \"   \\\"bar\\\" : 1,\\n\" +\n                    \"   \\\"baz\\\" : true,\\n\" +\n                    \"   \\\"gen\\\" : {\\\"prop\\\" : \\\"yepp1\\\"}\" +\n                    \"},\" +\n                    \"{\\n\" +\n                    \"   \\\"foo\\\" : \\\"foo2\\\",\\n\" +\n                    \"   \\\"bar\\\" : 2,\\n\" +\n                    \"   \\\"baz\\\" : true,\\n\" +\n                    \"   \\\"gen\\\" : {\\\"prop\\\" : \\\"yepp2\\\"}\" +\n                    \"}\" +\n                    \"]\";\n\n    public static Iterable<Configuration> configurations() {\n        return Configurations.objectMappingConfigurations();\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void list_of_numbers(Configuration conf) {\n\n        TypeRef<List<Double>> typeRef = new TypeRef<List<Double>>() {\n        };\n\n        assertThat(using(conf).parse(JSON_DOCUMENT).read(\"$.store.book[*].display-price\", typeRef)).containsExactly(8.95D, 12.99D, 8.99D, 22.99D);\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void test_type_ref(Configuration conf) throws IOException {\n        TypeRef<List<FooBarBaz<Sub>>> typeRef = new TypeRef<List<FooBarBaz<Sub>>>() {\n        };\n\n        assertThat(using(conf).parse(JSON).read(\"$\", typeRef)).extracting(\"foo\").containsExactly(\"foo0\", \"foo1\", \"foo2\");\n    }\n\n\n    public static class FooBarBaz<T> {\n        public T gen;\n        public String foo;\n        public Long bar;\n        public boolean baz;\n    }\n\n    public static class Sub {\n        public String prop;\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/MapperTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.util.Date;\n\nimport static com.jayway.jsonpath.JsonPath.parse;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class MapperTest extends BaseTest {\n\n\n    @Test\n    public void an_Integer_can_be_converted_to_a_Long() {\n        assertThat(parse(\"{\\\"val\\\": 1}\").read(\"val\", Long.class)).isEqualTo(1L);\n    }\n\n    @Test\n    public void an_String_can_be_converted_to_a_Long() {\n        assertThat(parse(\"{\\\"val\\\": 1}\").read(\"val\", Long.class)).isEqualTo(1L);\n    }\n\n    @Test\n    public void an_Integer_can_be_converted_to_a_String() {\n        assertThat(parse(\"{\\\"val\\\": 1}\").read(\"val\", String.class)).isEqualTo(\"1\");\n    }\n\n    @Test\n    public void an_Integer_can_be_converted_to_a_Double() {\n        assertThat(parse(\"{\\\"val\\\": 1}\").read(\"val\", Double.class)).isEqualTo(1D);\n    }\n\n    @Test\n    public void a_BigDecimal_can_be_converted_to_a_Long() {\n        assertThat(parse(\"{\\\"val\\\": 1.5}\").read(\"val\", Long.class)).isEqualTo(1L);\n    }\n\n    @Test\n    public void a_Long_can_be_converted_to_a_Date() {\n        Date now = new Date();\n        assertThat(parse(\"{\\\"val\\\": \"+now.getTime()+\"}\").read(\"val\", Date.class)).isEqualTo(now);\n    }\n\n    @Test\n    public void a_String_can_be_converted_to_a_BigInteger() {\n        assertThat(parse(\"{\\\"val\\\": \\\"1\\\"}\").read(\"val\", BigInteger.class)).isEqualTo(BigInteger.valueOf(1));\n    }\n\n    @Test\n    public void a_String_can_be_converted_to_a_BigDecimal() {\n        assertThat(parse(\"{\\\"val\\\": \\\"1.5\\\"}\").read(\"val\", BigDecimal.class)).isEqualTo(BigDecimal.valueOf(1.5d));\n    }\n\n    @Test\n    public void a_Boolean_can_be_converted_to_a_primitive_boolean() {\n        assertThat(parse(\"{\\\"val\\\": true}\").read(\"val\", boolean.class)).isTrue();\n        assertThat(parse(\"{\\\"val\\\": false}\").read(\"val\", boolean.class)).isFalse();\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/MultiPropTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static com.jayway.jsonpath.TestUtils.assertEvaluationThrows;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class MultiPropTest {\n\n    @Test\n    public void multi_prop_can_be_read_from_root() {\n\n        Map<String, Object> model = new HashMap<String, Object>(){{\n            put(\"a\", \"a-val\");\n            put(\"b\", \"b-val\");\n            put(\"c\", \"c-val\");\n        }};\n\n        Configuration conf = Configuration.defaultConfiguration();\n\n        assertThat(using(conf).parse(model).read(\"$['a', 'b']\", Map.class))\n                .containsEntry(\"a\", \"a-val\")\n                .containsEntry(\"b\", \"b-val\");\n\n        // current semantics: absent props are skipped\n        assertThat(using(conf).parse(model).read(\"$['a', 'd']\", Map.class))\n                .hasSize(1).containsEntry(\"a\", \"a-val\");\n    }\n\n    @Test\n    public void multi_props_can_be_defaulted_to_null() {\n\n        Map<String, Object> model = new HashMap<String, Object>(){{\n            put(\"a\", \"a-val\");\n            put(\"b\", \"b-val\");\n            put(\"c\", \"c-val\");\n        }};\n\n        Configuration conf = Configuration.defaultConfiguration().addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL);\n\n        assertThat(using(conf).parse(model).read(\"$['a', 'd']\", Map.class))\n                .containsEntry(\"a\", \"a-val\")\n                .containsEntry(\"d\", null);\n    }\n\n    @Test\n    public void multi_props_can_be_required() {\n\n        Map<String, Object> model = new HashMap<String, Object>(){{\n            put(\"a\", \"a-val\");\n            put(\"b\", \"b-val\");\n            put(\"c\", \"c-val\");\n        }};\n\n        Configuration conf = Configuration.defaultConfiguration().addOptions(Option.REQUIRE_PROPERTIES);\n\n        Assertions.assertThrows(PathNotFoundException.class, () -> using(conf).parse(model).read(\"$['a', 'x']\", Map.class));\n    }\n\n    @Test\n    public void multi_props_can_be_non_leafs() {\n        Object result = JsonPath.parse(\"{\\\"a\\\": {\\\"v\\\": 5}, \\\"b\\\": {\\\"v\\\": 4}, \\\"c\\\": {\\\"v\\\": 1}}\").read(\n                \"$['a', 'c'].v\");\n        assertThat(result).asList().containsOnly(5, 1);\n    }\n\n    @Test\n    public void nonexistent_non_leaf_multi_props_ignored() {\n        Object result = JsonPath.parse(\"{\\\"a\\\": {\\\"v\\\": 5}, \\\"b\\\": {\\\"v\\\": 4}, \\\"c\\\": {\\\"v\\\": 1}}\").read(\n                \"$['d', 'a', 'c', 'm'].v\");\n        assertThat(result).asList().containsOnly(5, 1);\n    }\n\n    @Test\n    public void multi_props_with_post_filter() {\n        Object result = JsonPath.parse(\"{\\\"a\\\": {\\\"v\\\": 5}, \\\"b\\\": {\\\"v\\\": 4}, \\\"c\\\": {\\\"v\\\": 1, \\\"flag\\\": true}}\").read(\n                \"$['a', 'c'][?(@.flag)].v\");\n        assertThat(result).asList().containsOnly(1);\n    }\n\n    @Test\n    public void deep_scan_does_not_affect_non_leaf_multi_props() {\n        // deep scan + multiprop is quite redundant scenario, but it's not forbidden, so we'd better check\n        final String json = \"{\\\"v\\\": [[{}, 1, {\\\"a\\\": {\\\"v\\\": 5}, \\\"b\\\": {\\\"v\\\": 4}, \\\"c\\\": {\\\"v\\\": 1, \\\"flag\\\": true}}]]}\";\n        Object result = JsonPath.parse(json).read(\"$..['a', 'c'].v\");\n        assertThat(result).asList().containsOnly(5, 1);\n\n        result = JsonPath.parse(json).read(\"$..['a', 'c'][?(@.flag)].v\");\n        assertThat(result).asList().containsOnly(1);\n    }\n\n    @Test\n    public void multi_props_can_be_in_the_middle() {\n        final String json = \"{\\\"x\\\": [null, {\\\"a\\\": {\\\"v\\\": 5}, \\\"b\\\": {\\\"v\\\": 4}, \\\"c\\\": {\\\"v\\\": 1}}]}\";\n        Object result = JsonPath.parse(json).read(\"$.x[1]['a', 'c'].v\");\n        assertThat(result).asList().containsOnly(5, 1);\n        result = JsonPath.parse(json).read(\"$.x[*]['a', 'c'].v\");\n        assertThat(result).asList().containsOnly(5, 1);\n        result = JsonPath.parse(json).read(\"$[*][*]['a', 'c'].v\");\n        assertThat(result).asList().containsOnly(5, 1);\n\n        result = JsonPath.parse(json).read(\"$.x[1]['d', 'a', 'c', 'm'].v\");\n        assertThat(result).asList().containsOnly(5, 1);\n        result = JsonPath.parse(json).read(\"$.x[*]['d', 'a', 'c', 'm'].v\");\n        assertThat(result).asList().containsOnly(5, 1);\n    }\n\n    @Test\n    public void non_leaf_multi_props_can_be_required() {\n        final Configuration conf = Configuration.defaultConfiguration().addOptions(Option.REQUIRE_PROPERTIES);\n        final String json = \"{\\\"a\\\": {\\\"v\\\": 5}, \\\"b\\\": {\\\"v\\\": 4}, \\\"c\\\": {\\\"v\\\": 1}}\";\n\n        assertThat((List)using(conf).parse(json).read(\"$['a', 'c'].v\")).asList().containsOnly(5, 1);\n        assertEvaluationThrows(json, \"$['d', 'a', 'c', 'm'].v\", PathNotFoundException.class, conf);\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/OptionsTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static com.jayway.jsonpath.Option.*;\nimport static java.util.Arrays.asList;\nimport static java.util.Collections.singletonMap;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.fail;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\npublic class OptionsTest extends BaseTest {\n\n    @Test\n    public void a_leafs_is_not_defaulted_to_null() {\n\n        Configuration conf = Configuration.defaultConfiguration();\n\n        assertThrows(PathNotFoundException.class, () -> using(conf).parse(\"{\\\"foo\\\" : \\\"bar\\\"}\").read(\"$.baz\"));\n    }\n\n    @Test\n    public void a_leafs_can_be_defaulted_to_null() {\n\n        Configuration conf = Configuration.builder().options(DEFAULT_PATH_LEAF_TO_NULL).build();\n\n        assertThat(using(conf).parse(\"{\\\"foo\\\" : \\\"bar\\\"}\").read(\"$.baz\", Object.class)).isNull();\n    }\n\n    @Test\n    public void a_definite_path_is_not_returned_as_list_by_default() {\n\n        Configuration conf = Configuration.defaultConfiguration();\n\n        assertThat((String) using(conf).parse(\"{\\\"foo\\\" : \\\"bar\\\"}\").read(\"$.foo\")).isInstanceOf(String.class);\n    }\n\n    @Test\n    public void a_definite_path_can_be_returned_as_list() {\n\n        Configuration conf = Configuration.builder().options(ALWAYS_RETURN_LIST).build();\n\n        assertThat((List) using(conf).parse(\"{\\\"foo\\\" : \\\"bar\\\"}\").read(\"$.foo\")).isInstanceOf(List.class);\n\n        assertThat((List) using(conf).parse(\"{\\\"foo\\\": null}\").read(\"$.foo\")).isInstanceOf(List.class);\n\n        assertThat((List) using(conf).parse(\"{\\\"foo\\\": [1, 4, 8]}\").read(\"$.foo\")).asList()\n                .containsExactly(Arrays.asList(1, 4, 8));\n    }\n\n    @Test\n    public void an_indefinite_path_can_be_returned_as_list() {\n        Configuration conf = Configuration.builder().options(ALWAYS_RETURN_LIST).build();\n\n        List<Object> result = using(conf).parse(\"{\\\"bar\\\": {\\\"foo\\\": null}}\").read(\"$..foo\");\n        assertThat(result).hasSize(1);\n        assertThat(result.get(0)).isNull();\n\n        assertThat((List) using(conf).parse(\"{\\\"bar\\\": {\\\"foo\\\": [1, 4, 8]}}\").read(\"$..foo\")).asList()\n                .containsExactly(Arrays.asList(1, 4, 8));\n    }\n\n    @Test\n    public void a_path_evaluation_is_returned_as_VALUE_by_default() {\n        Configuration conf = Configuration.defaultConfiguration();\n\n        assertThat((String) using(conf).parse(\"{\\\"foo\\\" : \\\"bar\\\"}\").read(\"$.foo\")).isEqualTo(\"bar\");\n    }\n\n    @Test\n    public void a_path_evaluation_can_be_returned_as_PATH_LIST() {\n        Configuration conf = Configuration.builder().options(AS_PATH_LIST).build();\n\n        List<String> pathList = using(conf).parse(\"{\\\"foo\\\" : \\\"bar\\\"}\").read(\"$.foo\");\n\n        assertThat(pathList).containsOnly(\"$['foo']\");\n    }\n\n    @Test\n    public void multi_properties_are_merged_by_default() {\n\n        Map<String, Object> model = new HashMap<String, Object>();\n        model.put(\"a\", \"a\");\n        model.put(\"b\", \"b\");\n        model.put(\"c\", \"c\");\n\n        Configuration conf = Configuration.defaultConfiguration();\n\n        Map<String, Object> result = using(conf).parse(model).read(\"$.['a', 'b']\");\n\n        //assertThat(result).isInstanceOf(List.class);\n        //assertThat((List)result).containsOnly(\"a\", \"b\");\n\n        assertThat(result)\n                .containsEntry(\"a\", \"a\")\n                .containsEntry(\"b\", \"b\");\n    }\n\n    @Test\n    public void when_property_is_required_exception_is_thrown() {\n        List<Map<String, String>> model = asList(singletonMap(\"a\", \"a-val\"), singletonMap(\"b\", \"b-val\"));\n\n        Configuration conf = Configuration.defaultConfiguration();\n\n        assertThat(using(conf).parse(model).read(\"$[*].a\", List.class)).containsExactly(\"a-val\");\n\n\n        conf = conf.addOptions(Option.REQUIRE_PROPERTIES);\n\n        try {\n            using(conf).parse(model).read(\"$[*].a\", List.class);\n            fail(\"Should throw PathNotFoundException\");\n        } catch (PathNotFoundException pnf) {\n        }\n    }\n\n    @Test\n    public void when_property_is_required_exception_is_thrown_2() {\n        Map<String, Object> model = new HashMap<String, Object>();\n        model.put(\"a\", singletonMap(\"a-key\", \"a-val\"));\n        model.put(\"b\", singletonMap(\"b-key\", \"b-val\"));\n\n        Configuration conf = Configuration.defaultConfiguration();\n\n        assertThat(using(conf).parse(model).read(\"$.*.a-key\", List.class)).containsExactly(\"a-val\");\n\n\n        conf = conf.addOptions(Option.REQUIRE_PROPERTIES);\n\n        try {\n            using(conf).parse(model).read(\"$.*.a-key\", List.class);\n            fail(\"Should throw PathNotFoundException\");\n        } catch (PathNotFoundException pnf) {\n        }\n    }\n\n\n    @Test\n    public void issue_suppress_exceptions_does_not_break_indefinite_evaluation() {\n        Configuration conf = Configuration.builder().options(SUPPRESS_EXCEPTIONS).build();\n\n        assertThat((List) using(conf).parse(\"{\\\"foo2\\\": [5]}\").read(\"$..foo2[0]\")).asList().containsOnly(5);\n        assertThat((List) using(conf).parse(\"{\\\"foo\\\" : {\\\"foo2\\\": [5]}}\").read(\"$..foo2[0]\")).asList().containsOnly(5);\n        assertThat((List) using(conf).parse(\"[null, [{\\\"foo\\\" : {\\\"foo2\\\": [5]}}]]\").read(\"$..foo2[0]\")).asList().containsOnly(5);\n\n        assertThat((List) using(conf).parse(\"[null, [{\\\"foo\\\" : {\\\"foo2\\\": [5]}}]]\").read(\"$..foo.foo2[0]\")).asList().containsOnly(5);\n\n        assertThat((List) using(conf).parse(\"{\\\"aoo\\\" : {}, \\\"foo\\\" : {\\\"foo2\\\": [5]}, \\\"zoo\\\" : {}}\").read(\"$[*].foo2[0]\")).asList().containsOnly(5);\n    }\n\n    @Test\n    public void isbn_is_defaulted_when_option_is_provided() {\n        List<String> result1 = JsonPath.using(JSON_SMART_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.store.book.*.isbn\");\n\n        assertThat(result1).containsExactly(\"0-553-21311-3\", \"0-395-19395-8\");\n\n        List<String> result2 = JsonPath.using(JSON_SMART_CONFIGURATION.addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL)).parse(JSON_DOCUMENT).read(\"$.store.book.*.isbn\");\n\n        assertThat(result2).containsExactly(null, null, \"0-553-21311-3\", \"0-395-19395-8\");\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/PathCompilerTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Disabled;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static com.jayway.jsonpath.internal.path.PathCompiler.compile;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\npublic class PathCompilerTest {\n\n\n    @Disabled(\"Backward compatibility <= 2.0.0\")\n    @Test\n    public void a_path_must_start_with_$_or_at() {\n        assertThrows(InvalidPathException.class, () -> compile(\"x\"));\n    }\n\n    @Disabled(\"Backward compatibility <= 2.0.0\")\n    @Test\n    public void a_square_bracket_may_not_follow_a_period() {\n        assertThrows(InvalidPathException.class, () -> compile(\"$.[\"));\n    }\n\n    @Test\n    public void a_root_path_must_be_followed_by_period_or_bracket() {\n        assertThrows(InvalidPathException.class, () -> compile(\"$X\"));\n    }\n\n    @Test\n    public void a_root_path_can_be_compiled() {\n        assertThat(compile(\"$\").toString()).isEqualTo(\"$\");\n        assertThat(compile(\"@\").toString()).isEqualTo(\"@\");\n    }\n\n    @Test\n    public void a_path_may_not_end_with_period() {\n        assertThrows(InvalidPathException.class, () -> compile(\"$.\"));\n    }\n\n    @Test\n    public void a_path_may_not_end_with_period_2() {\n        assertThrows(InvalidPathException.class, () -> compile(\"$.prop.\"));\n    }\n\n    @Test\n    public void a_path_may_not_end_with_scan() {\n        assertThrows(InvalidPathException.class, () -> compile(\"$..\"));\n    }\n\n    @Test\n    public void a_path_may_not_end_with_scan_2() {\n        assertThrows(InvalidPathException.class, () -> compile(\"$.prop..\"));\n    }\n\n    @Test\n    public void a_property_token_can_be_compiled() {\n        assertThat(compile(\"$.prop\").toString()).isEqualTo(\"$['prop']\");\n        assertThat(compile(\"$.1prop\").toString()).isEqualTo(\"$['1prop']\");\n        assertThat(compile(\"$.@prop\").toString()).isEqualTo(\"$['@prop']\");\n    }\n\n    @Test\n    public void a_bracket_notation_property_token_can_be_compiled() {\n        assertThat(compile(\"$['prop']\").toString()).isEqualTo(\"$['prop']\");\n        assertThat(compile(\"$['1prop']\").toString()).isEqualTo(\"$['1prop']\");\n        assertThat(compile(\"$['@prop']\").toString()).isEqualTo(\"$['@prop']\");\n        assertThat(compile(\"$[  '@prop'  ]\").toString()).isEqualTo(\"$['@prop']\");\n        assertThat(compile(\"$[\\\"prop\\\"]\").toString()).isEqualTo(\"$[\\\"prop\\\"]\");\n    }\n\n    @Test\n    public void a_multi_property_token_can_be_compiled() {\n        assertThat(compile(\"$['prop0', 'prop1']\").toString()).isEqualTo(\"$['prop0','prop1']\");\n        assertThat(compile(\"$[  'prop0'  , 'prop1'  ]\").toString()).isEqualTo(\"$['prop0','prop1']\");\n    }\n\n    @Test\n    public void a_property_chain_can_be_compiled() {\n        assertThat(compile(\"$.abc\").toString()).isEqualTo(\"$['abc']\");\n        assertThat(compile(\"$.aaa.bbb\").toString()).isEqualTo(\"$['aaa']['bbb']\");\n        assertThat(compile(\"$.aaa.bbb.ccc\").toString()).isEqualTo(\"$['aaa']['bbb']['ccc']\");\n    }\n\n    @Test\n    public void a_property_may_not_contain_blanks() {\n        assertThrows(InvalidPathException.class, () -> compile(\"$.foo bar\"));\n    }\n\n    @Test\n    public void a_wildcard_can_be_compiled() {\n        assertThat(compile(\"$.*\").toString()).isEqualTo(\"$[*]\");\n        assertThat(compile(\"$[*]\").toString()).isEqualTo(\"$[*]\");\n        assertThat(compile(\"$[ * ]\").toString()).isEqualTo(\"$[*]\");\n    }\n\n    @Test\n    public void a_wildcard_can_follow_a_property() {\n        assertThat(compile(\"$.prop[*]\").toString()).isEqualTo(\"$['prop'][*]\");\n        assertThat(compile(\"$['prop'][*]\").toString()).isEqualTo(\"$['prop'][*]\");\n    }\n\n    @Test\n    public void an_array_index_path_can_be_compiled() {\n        assertThat(compile(\"$[1]\").toString()).isEqualTo(\"$[1]\");\n        assertThat(compile(\"$[1,2,3]\").toString()).isEqualTo(\"$[1,2,3]\");\n        assertThat(compile(\"$[ 1 , 2 , 3 ]\").toString()).isEqualTo(\"$[1,2,3]\");\n    }\n\n    @Test\n    public void an_array_slice_path_can_be_compiled() {\n        assertThat(compile(\"$[-1:]\").toString()).isEqualTo(\"$[-1:]\");\n        assertThat(compile(\"$[1:2]\").toString()).isEqualTo(\"$[1:2]\");\n        assertThat(compile(\"$[:2]\").toString()).isEqualTo(\"$[:2]\");\n    }\n\n    @Test\n    public void an_inline_criteria_can_be_parsed() {\n        assertThat(compile(\"$[?(@.foo == 'bar')]\").toString()).isEqualTo(\"$[?]\");\n        assertThat(compile(\"$[?(@.foo == \\\"bar\\\")]\").toString()).isEqualTo(\"$[?]\");\n    }\n\n    @Test\n    public void a_placeholder_criteria_can_be_parsed() {\n\n        Predicate p = new Predicate() {\n            @Override\n            public boolean apply(PredicateContext ctx) {\n                return false;\n            }\n        };\n        assertThat(compile(\"$[?]\", p).toString()).isEqualTo(\"$[?]\");\n        assertThat(compile(\"$[?,?]\", p, p).toString()).isEqualTo(\"$[?,?]\");\n        assertThat(compile(\"$[?,?,?]\", p, p, p).toString()).isEqualTo(\"$[?,?,?]\");\n    }\n\n    @Test\n    public void a_scan_token_can_be_parsed() {\n        assertThat(compile(\"$..['prop']..[*]\").toString()).isEqualTo(\"$..['prop']..[*]\");\n    }\n\n    @Test\n    public void issue_predicate_can_have_escaped_backslash_in_prop() {\n        String json = \"{\\n\"\n                + \"    \\\"logs\\\": [\\n\"\n                + \"        {\\n\"\n                + \"            \\\"message\\\": \\\"it\\\\\\\\\\\",\\n\"\n                + \"            \\\"id\\\": 2\\n\"\n                + \"        }\\n\"\n                + \"    ]\\n\"\n                + \"}\";\n        // message: it\\ -> (after json escaping) -> \"it\\\\\" -> (after java escaping) -> \"\\\"it\\\\\\\\\\\"\"\n\n        List<String> result = JsonPath.read(json, \"$.logs[?(@.message == 'it\\\\\\\\')].message\");\n\n        assertThat(result).containsExactly(\"it\\\\\");\n    }\n\n    @Test\n    public void issue_predicate_can_have_bracket_in_regex() {\n        String json = \"{\\n\"\n                + \"    \\\"logs\\\": [\\n\"\n                + \"        {\\n\"\n                + \"            \\\"message\\\": \\\"(it\\\",\\n\"\n                + \"            \\\"id\\\": 2\\n\"\n                + \"        }\\n\"\n                + \"    ]\\n\"\n                + \"}\";\n\n        List<String> result = JsonPath.read(json, \"$.logs[?(@.message =~ /\\\\(it/)].message\");\n\n        assertThat(result).containsExactly(\"(it\");\n    }\n\n    @Test\n    public void issue_predicate_can_have_and_in_regex() {\n        String json = \"{\\n\"\n                + \"    \\\"logs\\\": [\\n\"\n                + \"        {\\n\"\n                + \"            \\\"message\\\": \\\"it\\\",\\n\"\n                + \"            \\\"id\\\": 2\\n\"\n                + \"        }\\n\"\n                + \"    ]\\n\"\n                + \"}\";\n\n        List<String> result = JsonPath.read(json, \"$.logs[?(@.message =~ /&&|it/)].message\");\n\n        assertThat(result).containsExactly(\"it\");\n    }\n\n    @Test\n    public void issue_predicate_can_have_and_in_prop() {\n        String json = \"{\\n\"\n                + \"    \\\"logs\\\": [\\n\"\n                + \"        {\\n\"\n                + \"            \\\"message\\\": \\\"&& it\\\",\\n\"\n                + \"            \\\"id\\\": 2\\n\"\n                + \"        }\\n\"\n                + \"    ]\\n\"\n                + \"}\";\n\n        List<String> result = JsonPath.read(json, \"$.logs[?(@.message == '&& it')].message\");\n\n        assertThat(result).containsExactly(\"&& it\");\n    }\n\n    @Test\n    public void issue_predicate_brackets_must_change_priorities() {\n        String json = \"{\\n\"\n                + \"    \\\"logs\\\": [\\n\"\n                + \"        {\\n\"\n                + \"            \\\"id\\\": 2\\n\"\n                + \"        }\\n\"\n                + \"    ]\\n\"\n                + \"}\";\n\n        List<String> result = JsonPath.read(json, \"$.logs[?(@.message && (@.id == 1 || @.id == 2))].id\");\n        assertThat(result).isEmpty();\n\n        result = JsonPath.read(json, \"$.logs[?((@.id == 2 || @.id == 1) && @.message)].id\");\n        assertThat(result).isEmpty();\n    }\n\n    @Test\n    public void issue_predicate_or_has_lower_priority_than_and() {\n        String json = \"{\\n\"\n                + \"    \\\"logs\\\": [\\n\"\n                + \"        {\\n\"\n                + \"            \\\"id\\\": 2\\n\"\n                + \"        }\\n\"\n                + \"    ]\\n\"\n                + \"}\";\n\n        List<String> result = JsonPath.read(json, \"$.logs[?(@.x && @.y || @.id)]\");\n        assertThat(result).hasSize(1);\n    }\n\n    @Test\n    public void issue_predicate_can_have_double_quotes() {\n        String json = \"{\\n\"\n                + \"    \\\"logs\\\": [\\n\"\n                + \"        {\\n\"\n                + \"            \\\"message\\\": \\\"\\\\\\\"it\\\\\\\"\\\"\\n\"\n                + \"        }\\n\"\n                + \"    ]\\n\"\n                + \"}\";\n        List<String> result = JsonPath.read(json, \"$.logs[?(@.message == '\\\"it\\\"')].message\");\n        assertThat(result).containsExactly(\"\\\"it\\\"\");\n    }\n\n    @Test\n    public void issue_predicate_can_have_single_quotes() {\n        String json = \"{\\n\"\n                + \"    \\\"logs\\\": [\\n\"\n                + \"        {\\n\"\n                + \"            \\\"message\\\": \\\"'it'\\\"\\n\"\n                + \"        }\\n\"\n                + \"    ]\\n\"\n                + \"}\";\n        DocumentContext parse = JsonPath.parse(json);\n        JsonPath compile = JsonPath.compile(\"$.logs[?(@.message == \\\"'it'\\\")].message\");\n        List<String> result = parse.read(compile);\n        assertThat(result).containsExactly(\"'it'\");\n    }\n\n    @Test\n    public void issue_predicate_can_have_single_quotes_escaped() {\n        String json = \"{\\n\"\n                + \"    \\\"logs\\\": [\\n\"\n                + \"        {\\n\"\n                + \"            \\\"message\\\": \\\"'it'\\\"\\n\"\n                + \"        }\\n\"\n                + \"    ]\\n\"\n                + \"}\";\n        DocumentContext parse = JsonPath.parse(json);\n        JsonPath compile = JsonPath.compile(\"$.logs[?(@.message == '\\\\'it\\\\'')].message\");\n        List<String> result = parse.read(compile);\n        assertThat(result).containsExactly(\"'it'\");\n    }\n\n    @Test\n    public void issue_predicate_can_have_square_bracket_in_prop() {\n        String json = \"{\\n\"\n                + \"    \\\"logs\\\": [\\n\"\n                + \"        {\\n\"\n                + \"            \\\"message\\\": \\\"] it\\\",\\n\"\n                + \"            \\\"id\\\": 2\\n\"\n                + \"        }\\n\"\n                + \"    ]\\n\"\n                + \"}\";\n\n        List<String> result = JsonPath.read(json, \"$.logs[?(@.message == '] it')].message\");\n\n        assertThat(result).containsExactly(\"] it\");\n    }\n\n    @Test\n    public void a_function_can_be_compiled() {\n        assertThat(compile(\"$.aaa.foo()\").toString()).isEqualTo(\"$['aaa'].foo()\");\n        assertThat(compile(\"$.aaa.foo(5)\").toString()).isEqualTo(\"$['aaa'].foo(...)\");\n        assertThat(compile(\"$.aaa.foo($.bar)\").toString()).isEqualTo(\"$['aaa'].foo(...)\");\n        assertThat(compile(\"$.aaa.foo(5,10,15)\").toString()).isEqualTo(\"$['aaa'].foo(...)\");\n    }\n\n    @Test\n    public void array_indexes_must_be_separated_by_commas() {\n        assertThrows(InvalidPathException.class, () -> compile(\"$[0, 1, 2 4]\"));\n    }\n\n    @Test\n    public void trailing_comma_after_list_is_not_accepted() {\n        assertThrows(InvalidPathException.class, () -> compile(\"$['1','2',]\"));\n    }\n\n    @Test\n    public void accept_only_a_single_comma_between_indexes() {\n        assertThrows(InvalidPathException.class, () -> compile(\"$['1', ,'3']\"));\n    }\n\n    @Test\n    public void property_must_be_separated_by_commas() {\n        assertThrows(InvalidPathException.class, () -> compile(\"$['aaa'}'bbb']\"));\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/PredicateTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class PredicateTest extends BaseTest {\n\n    private static ReadContext reader = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT);\n\n    @Test\n    public void predicates_filters_can_be_applied() {\n        Predicate booksWithISBN = new Predicate() {\n            @Override\n            public boolean apply(PredicateContext ctx) {\n                return ctx.item(Map.class).containsKey(\"isbn\");\n            }\n        };\n\n        assertThat(reader.read(\"$.store.book[?].isbn\", List.class, booksWithISBN)).containsOnly(\"0-395-19395-8\", \"0-553-21311-3\");\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/ProviderInTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport com.fasterxml.jackson.databind.node.ArrayNode;\nimport com.google.gson.JsonArray;\nimport com.jayway.jsonpath.spi.json.*;\nimport com.jayway.jsonpath.spi.mapper.*;\nimport org.assertj.core.util.Lists;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class ProviderInTest {\n    private final String JSON = \"[{\\\"foo\\\": \\\"bar\\\"}, {\\\"foo\\\": \\\"baz\\\"}]\";\n    private final String EQUALS_FILTER = \"$.[?(@.foo == %s)].foo\";\n    private final String IN_FILTER = \"$.[?(@.foo in [%s])].foo\";\n    private final String DOUBLE_QUOTES = \"\\\"bar\\\"\";\n    private final String DOUBLE_QUOTES_EQUALS_FILTER = String.format(EQUALS_FILTER, DOUBLE_QUOTES);\n    private final String DOUBLE_QUOTES_IN_FILTER = String.format(IN_FILTER, DOUBLE_QUOTES);\n    private final String SINGLE_QUOTES = \"'bar'\";\n    private final String SINGLE_QUOTES_EQUALS_FILTER = String.format(EQUALS_FILTER, SINGLE_QUOTES);\n    private final String SINGLE_QUOTES_IN_FILTER = String.format(IN_FILTER, SINGLE_QUOTES);\n\n\n    @Test\n    public void testJsonPathQuotesJackson() {\n        final Configuration jackson = Configuration.builder().jsonProvider(new JacksonJsonProvider()).mappingProvider(new JacksonMappingProvider()).build();\n        final DocumentContext ctx = JsonPath.using(jackson).parse(JSON);\n\n        final List<String> doubleQuoteEqualsResult = ctx.read(DOUBLE_QUOTES_EQUALS_FILTER);\n        assertEquals(Lists.newArrayList(\"bar\"), doubleQuoteEqualsResult);\n\n        final List<String> singleQuoteEqualsResult = ctx.read(SINGLE_QUOTES_EQUALS_FILTER);\n        assertEquals(doubleQuoteEqualsResult, singleQuoteEqualsResult);\n\n        final List<String> doubleQuoteInResult = ctx.read(DOUBLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, doubleQuoteEqualsResult);\n\n        final List<String> singleQuoteInResult = ctx.read(SINGLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, singleQuoteInResult);\n    }\n\n\n    @Test\n    public void testJsonPathQuotesJacksonJsonNode() {\n        final Configuration jacksonJsonNode = Configuration.builder().jsonProvider(new JacksonJsonNodeJsonProvider()).mappingProvider(new JacksonMappingProvider()).build();\n        final DocumentContext ctx = JsonPath.using(jacksonJsonNode).parse(JSON);\n\n        final ArrayNode doubleQuoteEqualsResult = ctx.read(DOUBLE_QUOTES_EQUALS_FILTER);\n        assertEquals(\"bar\", doubleQuoteEqualsResult.get(0).asText());\n\n        final ArrayNode singleQuoteEqualsResult = ctx.read(SINGLE_QUOTES_EQUALS_FILTER);\n        assertEquals(doubleQuoteEqualsResult, singleQuoteEqualsResult);\n\n        final ArrayNode doubleQuoteInResult = ctx.read(DOUBLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, doubleQuoteEqualsResult);\n\n        final ArrayNode singleQuoteInResult = ctx.read(SINGLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, singleQuoteInResult);\n    }\n\n    @Test\n    public void testJsonPathQuotesJackson3() {\n        final Configuration jackson3 = Configuration.builder().jsonProvider(new Jackson3JsonProvider()).mappingProvider(new Jackson3MappingProvider()).build();\n        final DocumentContext ctx = JsonPath.using(jackson3).parse(JSON);\n\n        final List<String> doubleQuoteEqualsResult = ctx.read(DOUBLE_QUOTES_EQUALS_FILTER);\n        assertEquals(Lists.newArrayList(\"bar\"), doubleQuoteEqualsResult);\n\n        final List<String> singleQuoteEqualsResult = ctx.read(SINGLE_QUOTES_EQUALS_FILTER);\n        assertEquals(doubleQuoteEqualsResult, singleQuoteEqualsResult);\n\n        final List<String> doubleQuoteInResult = ctx.read(DOUBLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, doubleQuoteEqualsResult);\n\n        final List<String> singleQuoteInResult = ctx.read(SINGLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, singleQuoteInResult);\n    }\n\n    @Test\n    public void testJsonPathQuotesJackson3JsonNode() {\n        final Configuration jackson3JsonNode = Configuration.builder().jsonProvider(new Jackson3JsonNodeJsonProvider()).mappingProvider(new Jackson3MappingProvider()).build();\n        final DocumentContext ctx = JsonPath.using(jackson3JsonNode).parse(JSON);\n\n        final tools.jackson.databind.node.ArrayNode doubleQuoteEqualsResult = ctx.read(DOUBLE_QUOTES_EQUALS_FILTER);\n        assertEquals(\"bar\", doubleQuoteEqualsResult.get(0).asText());\n\n        final tools.jackson.databind.node.ArrayNode singleQuoteEqualsResult = ctx.read(SINGLE_QUOTES_EQUALS_FILTER);\n        assertEquals(doubleQuoteEqualsResult, singleQuoteEqualsResult);\n\n        final tools.jackson.databind.node.ArrayNode doubleQuoteInResult = ctx.read(DOUBLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, doubleQuoteEqualsResult);\n\n        final tools.jackson.databind.node.ArrayNode singleQuoteInResult = ctx.read(SINGLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, singleQuoteInResult);\n    }\n\n    @Test\n    public void testJsonPathQuotesGson() {\n        final Configuration gson = Configuration.builder().jsonProvider(new GsonJsonProvider()).mappingProvider(new GsonMappingProvider()).build();\n        final DocumentContext ctx = JsonPath.using(gson).parse(JSON);\n\n        final JsonArray doubleQuoteEqualsResult = ctx.read(DOUBLE_QUOTES_EQUALS_FILTER);\n        assertEquals(\"bar\", doubleQuoteEqualsResult.get(0).getAsString());\n\n        final JsonArray singleQuoteEqualsResult = ctx.read(SINGLE_QUOTES_EQUALS_FILTER);\n        assertEquals(doubleQuoteEqualsResult, singleQuoteEqualsResult);\n\n        final JsonArray doubleQuoteInResult = ctx.read(DOUBLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, doubleQuoteEqualsResult);\n\n        final JsonArray singleQuoteInResult = ctx.read(SINGLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, singleQuoteInResult);\n    }\n\n    @Test\n    public void testJsonPathQuotesJsonOrg() {\n        final Configuration jsonOrg = Configuration.builder().jsonProvider(new JsonOrgJsonProvider()).mappingProvider(new JsonOrgMappingProvider()).build();\n        final DocumentContext ctx = JsonPath.using(jsonOrg).parse(JSON);\n\n        final org.json.JSONArray doubleQuoteEqualsResult = ctx.read(DOUBLE_QUOTES_EQUALS_FILTER);\n        assertEquals(\"bar\", doubleQuoteEqualsResult.get(0));\n\n        final org.json.JSONArray singleQuoteEqualsResult = ctx.read(SINGLE_QUOTES_EQUALS_FILTER);\n        assertEquals(doubleQuoteEqualsResult.get(0), singleQuoteEqualsResult.get(0));\n\n        final org.json.JSONArray doubleQuoteInResult = ctx.read(DOUBLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult.get(0), doubleQuoteEqualsResult.get(0));\n\n        final org.json.JSONArray singleQuoteInResult = ctx.read(SINGLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult.get(0), singleQuoteInResult.get(0));\n    }\n\n    @Test\n    public void testJsonPathQuotesJsonSmart() {\n        final Configuration jsonSmart = Configuration.builder().jsonProvider(new JsonSmartJsonProvider()).mappingProvider(new JsonSmartMappingProvider()).build();\n        final DocumentContext ctx = JsonPath.using(jsonSmart).parse(JSON);\n\n        final net.minidev.json.JSONArray doubleQuoteEqualsResult = ctx.read(DOUBLE_QUOTES_EQUALS_FILTER);\n        assertEquals(\"bar\", doubleQuoteEqualsResult.get(0));\n\n        final net.minidev.json.JSONArray singleQuoteEqualsResult = ctx.read(SINGLE_QUOTES_EQUALS_FILTER);\n        assertEquals(doubleQuoteEqualsResult, singleQuoteEqualsResult);\n\n        final net.minidev.json.JSONArray doubleQuoteInResult = ctx.read(DOUBLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, doubleQuoteEqualsResult);\n\n        final net.minidev.json.JSONArray singleQuoteInResult = ctx.read(SINGLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, singleQuoteInResult);\n    }\n\n    @Test\n    public void testJsonPathQuotesJakarta() {\n        final Configuration gson = Configuration.builder().jsonProvider(new JakartaJsonProvider()).mappingProvider(new JakartaMappingProvider()).build();\n        final DocumentContext ctx = JsonPath.using(gson).parse(JSON);\n\n        final List<jakarta.json.JsonValue> doubleQuoteEqualsResult = ctx.read(DOUBLE_QUOTES_EQUALS_FILTER);\n        // returned string is surrounded by double quotes in Jakarta EE JSON-P implementations \n        assertEquals(\"bar\", ((jakarta.json.JsonString) doubleQuoteEqualsResult.get(0)).getChars());\n\n        final List<jakarta.json.JsonValue> singleQuoteEqualsResult = ctx.read(SINGLE_QUOTES_EQUALS_FILTER);\n        assertEquals(doubleQuoteEqualsResult, singleQuoteEqualsResult);\n\n        final List<jakarta.json.JsonValue> doubleQuoteInResult = ctx.read(DOUBLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, doubleQuoteEqualsResult);\n\n        final List<jakarta.json.JsonValue> singleQuoteInResult = ctx.read(SINGLE_QUOTES_IN_FILTER);\n        assertEquals(doubleQuoteInResult, singleQuoteInResult);\n    }\n}"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/ReadContextTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport static com.jayway.jsonpath.JsonPath.using;\n\npublic class ReadContextTest extends BaseTest {\n\n    @Test\n    public void json_can_be_fetched_as_string() {\n\n        String expected = \"{\\\"category\\\":\\\"reference\\\",\\\"author\\\":\\\"Nigel Rees\\\",\\\"title\\\":\\\"Sayings of the Century\\\",\\\"display-price\\\":8.95}\";\n\n        String jsonString1 = using(JSON_SMART_CONFIGURATION).parse(JSON_BOOK_DOCUMENT).jsonString();\n        String jsonString2 = using(JACKSON_CONFIGURATION).parse(JSON_BOOK_DOCUMENT).jsonString();\n        String jsonString3 = using(JACKSON_JSON_NODE_CONFIGURATION).parse(JSON_BOOK_DOCUMENT).jsonString();\n        String jsonString4 = using(GSON_CONFIGURATION).parse(JSON_BOOK_DOCUMENT).jsonString();\n        \n        Assertions.assertThat(jsonString1).isEqualTo(expected);\n        Assertions.assertThat(jsonString2).isEqualTo(expected);\n        Assertions.assertThat(jsonString3).isEqualTo(expected);\n        Assertions.assertThat(jsonString4).isEqualTo(expected);\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/ReturnTypeTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.jayway.jsonpath.JsonPath.parse;\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static com.jayway.jsonpath.Option.AS_PATH_LIST;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\n@SuppressWarnings(\"ALL\")\npublic class ReturnTypeTest extends BaseTest {\n\n\n    private static ReadContext reader = parse(JSON_DOCUMENT);\n\n    @Test\n    public void assert_strings_can_be_read() {\n        assertThat((String) reader.read(\"$.string-property\")).isEqualTo(\"string-value\");\n    }\n\n    @Test\n    public void assert_ints_can_be_read() {\n        assertThat(reader.read(\"$.int-max-property\", Integer.class)).isEqualTo(Integer.MAX_VALUE);\n    }\n\n    @Test\n    public void assert_longs_can_be_read() {\n        assertThat((Long) reader.read(\"$.long-max-property\")).isEqualTo(Long.MAX_VALUE);\n    }\n\n    @Test\n    public void assert_boolean_values_can_be_read() {\n        assertThat((Boolean) reader.read(\"$.boolean-property\")).isEqualTo(true);\n    }\n\n    @Test\n    public void assert_null_values_can_be_read() {\n        assertThat((String) reader.read(\"$.null-property\")).isNull();\n    }\n\n    @Test\n    public void assert_arrays_can_be_read() {\n        /*\n        Object result = reader.read(\"$.store.book\");\n\n        assertThat(reader.configuration().jsonProvider().isArray(result)).isTrue();\n\n        assertThat(reader.configuration().jsonProvider().length(result)).isEqualTo(4);\n        */\n        assertThat(reader.read(\"$.store.book\", List.class)).hasSize(4);\n    }\n\n    @Test\n    public void assert_maps_can_be_read() {\n\n        assertThat(reader.read(\"$.store.book[0]\", Map.class))\n                .containsEntry(\"category\", \"reference\")\n                .containsEntry(\"author\", \"Nigel Rees\")\n                .containsEntry(\"title\", \"Sayings of the Century\")\n                .containsEntry(\"display-price\", 8.95D);\n\n    }\n\n    @Test\n    public void a_path_evaluation_can_be_returned_as_PATH_LIST() {\n        Configuration conf = Configuration.builder().options(AS_PATH_LIST).build();\n\n        List<String> pathList = using(conf).parse(JSON_DOCUMENT).read(\"$..author\");\n\n        assertThat(pathList).containsExactly(\n                \"$['store']['book'][0]['author']\",\n                \"$['store']['book'][1]['author']\",\n                \"$['store']['book'][2]['author']\",\n                \"$['store']['book'][3]['author']\");\n\n    }\n\n    @Test\n    public void class_cast_exception_is_thrown_when_return_type_is_not_expected() {\n        assertThrows(ClassCastException.class, () -> {\n            List<String> list = reader.read(\"$.store.book[0].author\");\n        });\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/ScientificNotationTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport com.google.gson.JsonArray;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static org.assertj.core.api.Assertions.assertThat;\n\n//test for issue: https://github.com/json-path/JsonPath/issues/590\npublic class ScientificNotationTest extends BaseTest {\n\n    final String sci_rep_array = \"{\\\"num_array\\\": [\" +\n            \"{\\\"num\\\":1},\" +\n            \"{\\\"num\\\":-1e-10},\" +\n            \"{\\\"num\\\":0.1e10},\"+\n            \"{\\\"num\\\":2E-20},\" +\n            \"{\\\"num\\\":-0.2E20}\" +\n            \" ]}\";\n\n    @Test\n    public void testScientificNotation() {\n        List<JsonArray> result = using(Configuration.defaultConfiguration())\n                .parse(sci_rep_array)\n                .read(\"$.num_array[?(@.num == 1 || @.num == -1e-10 || @.num == 0.1e10 || @.num == 2E-20 || @.num == -0.2E20)]\");\n\n        assertThat(result.toString()).isEqualTo(\"[{\\\"num\\\":1},{\\\"num\\\":-1.0E-10},{\\\"num\\\":1.0E9},{\\\"num\\\":2.0E-20},{\\\"num\\\":-2.0E19}]\");\n    }\n    @Test\n    public void testScientificNotation_lt_gt() {\n        List<JsonArray> result;\n        result = using(Configuration.defaultConfiguration())\n                .parse(sci_rep_array)\n                .read(\"$.num_array[?(@.num > -0.0E0)]\");\n\n        assertThat(result.toString()).isEqualTo(\"[{\\\"num\\\":1},{\\\"num\\\":1.0E9},{\\\"num\\\":2.0E-20}]\");\n\n        result = using(Configuration.defaultConfiguration())\n                .parse(sci_rep_array)\n                .read(\"$.num_array[?(@.num < -0.0E0)]\");\n\n        assertThat(result.toString()).isEqualTo(\"[{\\\"num\\\":-1.0E-10},{\\\"num\\\":-2.0E19}]\");\n\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/TapestryJsonProviderTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static org.assertj.core.api.Assertions.assertThat;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport org.apache.tapestry5.json.JSONArray;\nimport org.apache.tapestry5.json.JSONObject;\nimport org.junit.jupiter.api.Test;\n\npublic class TapestryJsonProviderTest extends BaseTest {\n\n  @Test\n  public void an_object_can_be_read() {\n\n    JSONObject book = using(TAPESTRY_JSON_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.store.book[0]\");\n\n    assertThat(book.get(\"author\").toString()).isEqualTo(\"Nigel Rees\");\n  }\n\n  @Test\n  public void a_property_can_be_read() {\n\n    String category = using(TAPESTRY_JSON_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.store.book[0].category\");\n\n    assertThat(category).isEqualTo(\"reference\");\n  }\n\n  @Test\n  public void a_filter_can_be_applied() {\n\n    JSONArray fictionBooks = using(TAPESTRY_JSON_CONFIGURATION).parse(JSON_DOCUMENT)\n        .read(\"$.store.book[?(@.category == 'fiction')]\");\n\n    assertThat(fictionBooks.length()).isEqualTo(3);\n  }\n\n  @Test\n  public void result_can_be_mapped_to_object() {\n\n    List<Map<String, Object>> books = using(TAPESTRY_JSON_CONFIGURATION).parse(JSON_DOCUMENT).read(\"$.store.book\",\n        List.class);\n\n    assertThat(books.size()).isEqualTo(4);\n  }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/TestSuppressExceptions.java",
    "content": "package com.jayway.jsonpath;\n\nimport com.jayway.jsonpath.spi.json.Jackson3JsonProvider;\nimport com.jayway.jsonpath.spi.json.JacksonJsonProvider;\nimport com.jayway.jsonpath.spi.mapper.Jackson3MappingProvider;\nimport com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\n\npublic class TestSuppressExceptions {\n\n    @Test\n    public void testSuppressExceptionsIsRespected() {\n        ParseContext parseContext = JsonPath.using(\n                new Configuration.ConfigurationBuilder().jsonProvider(new JacksonJsonProvider())\n                        .mappingProvider(new JacksonMappingProvider()).options(Option.SUPPRESS_EXCEPTIONS)\n                        .build());\n        String json = \"{}\";\n        assertNull(parseContext.parse(json).read(JsonPath.compile(\"$.missing\")));\n    }\n\n    @Test\n    public void testSuppressExceptionsIsRespectedPath() {\n        ParseContext parseContext = JsonPath.using(\n                new Configuration.ConfigurationBuilder().jsonProvider(new JacksonJsonProvider())\n                        .mappingProvider(new JacksonMappingProvider()).options(Option.SUPPRESS_EXCEPTIONS, Option.AS_PATH_LIST)\n                        .build());\n        String json = \"{}\";\n\n        List<String> result = parseContext.parse(json).read(JsonPath.compile(\"$.missing\"));\n        assertThat(result).isEmpty();\n    }\n    @Test\n    public void testSuppressExceptionsIsRespectedJackson3() {\n        ParseContext parseContext = JsonPath.using(\n            new Configuration.ConfigurationBuilder().jsonProvider(new Jackson3JsonProvider())\n                                                    .mappingProvider(new Jackson3MappingProvider()).options(Option.SUPPRESS_EXCEPTIONS)\n                                                    .build());\n        String json = \"{}\";\n        assertNull(parseContext.parse(json).read(JsonPath.compile(\"$.missing\")));\n    }\n\n    @Test\n    public void testSuppressExceptionsIsRespectedPathJackson3() {\n        ParseContext parseContext = JsonPath.using(\n            new Configuration.ConfigurationBuilder().jsonProvider(new Jackson3JsonProvider())\n                                                    .mappingProvider(new Jackson3MappingProvider()).options(Option.SUPPRESS_EXCEPTIONS, Option.AS_PATH_LIST)\n                                                    .build());\n        String json = \"{}\";\n\n        List<String> result = parseContext.parse(json).read(JsonPath.compile(\"$.missing\"));\n        assertThat(result).isEmpty();\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/TestUtils.java",
    "content": "package com.jayway.jsonpath;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.fail;\n\npublic final class TestUtils {\n    private TestUtils() {}\n\n    public static void assertEvaluationThrows(final String json, final String path,\n                                              Class<? extends JsonPathException> expected) {\n        assertEvaluationThrows(json, path, expected, Configuration.defaultConfiguration());\n    }\n\n    /**\n     * Shortcut for expected exception testing during path evaluation.\n     *\n     * @param json json to parse\n     * @param path jsonpath do evaluate\n     * @param expected expected exception class (reference comparison, not an instanceof)\n     * @param conf conf to use during evaluation\n     */\n    public static void assertEvaluationThrows(final String json, final String path,\n                                              Class<? extends JsonPathException> expected, final Configuration conf) {\n        try {\n            using(conf).parse(json).read(path);\n            fail(\"Should throw \" + expected.getName());\n        } catch (JsonPathException exc) {\n            if (exc.getClass() != expected)\n                throw exc;\n        }\n    }\n\n    /**\n     * Assertion which requires empty list as a result of indefinite path search.\n     * @param json json to be parsed\n     * @param path path to be evaluated\n     * @param conf conf to use during evaluation\n     */\n    public static void assertHasNoResults(final String json, final String path, Configuration conf) {\n        assertHasResults(json, path, 0, conf);\n    }\n\n    /**\n     * Assertion which requires list of one element as a result of indefinite path search.\n     * @param json json to be parsed\n     * @param path path to be evaluated\n     */\n    public static void assertHasOneResult(final String json, final String path, Configuration conf) {\n        assertHasResults(json, path, 1, conf);\n    }\n\n    /**\n     * Shortcut for counting found nodes.\n     * @param json json to be parsed\n     * @param path path to be evaluated\n     * @param expectedResultCount expected number of nodes to be found\n     * @param conf conf to use during evaluation\n     */\n    public static void assertHasResults(final String json, final String path, final int expectedResultCount, Configuration conf) {\n        Object result = JsonPath.using(conf).parse(json).read(path);\n        assertThat(conf.jsonProvider().length(result)).isEqualTo(expectedResultCount);\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/WriteTest.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.io.InputStream;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.jayway.jsonpath.JsonPath.parse;\nimport static java.util.Collections.emptyMap;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\npublic class WriteTest extends BaseTest {\n\n    private static final Map<String, Object> EMPTY_MAP = emptyMap();\n\n    @Test\n    public void an_array_child_property_can_be_updated() {\n\n        Object o = parse(JSON_DOCUMENT).set(\"$.store.book[*].display-price\", 1).json();\n\n        List<Integer> result = parse(o).read(\"$.store.book[*].display-price\");\n\n        assertThat(result).containsExactly(1, 1, 1, 1);\n    }\n\n\n    @Test\n    public void an_root_property_can_be_updated() {\n\n        Object o = parse(JSON_DOCUMENT).set(\"$.int-max-property\", 1).json();\n\n        Integer result = parse(o).read(\"$.int-max-property\");\n\n        assertThat(result).isEqualTo(1);\n    }\n\n    @Test\n    public void an_deep_scan_can_update() {\n\n        Object o = parse(JSON_DOCUMENT).set(\"$..display-price\", 1).json();\n\n        List<Integer> result = parse(o).read(\"$..display-price\");\n\n        assertThat(result).containsExactly(1, 1, 1, 1, 1);\n    }\n\n\n    @Test\n    public void an_filter_can_update() {\n\n        Object o = parse(JSON_DOCUMENT).set(\"$.store.book[?(@.display-price)].display-price\", 1).json();\n\n        List<Integer> result = parse(o).read(\"$.store.book[?(@.display-price)].display-price\");\n\n        assertThat(result).containsExactly(1, 1, 1, 1);\n    }\n\n    @Test\n    public void a_path_can_be_deleted() {\n\n        Object o = parse(JSON_DOCUMENT).delete(\"$.store.book[*].display-price\").json();\n\n        List<Integer> result = parse(o).read(\"$.store.book[*].display-price\");\n\n        assertThat(result).isEmpty();\n    }\n\n    @Test\n    public void operations_can_chained() {\n\n        Object o = parse(JSON_DOCUMENT)\n                .delete(\"$.store.book[*].display-price\")\n                .set(\"$.store.book[*].category\", \"A\")\n                .json();\n\n        List<Integer> prices = parse(o).read(\"$.store.book[*].display-price\");\n        List<String> categories = parse(o).read(\"$.store.book[*].category\");\n\n        assertThat(prices).isEmpty();\n        assertThat(categories).containsExactly(\"A\", \"A\", \"A\", \"A\");\n    }\n\n    @Test\n    public void an_array_can_be_updated() {\n\n        List<Integer> ints = parse(\"[0,1,2,3]\").set(\"$[?(@ == 1)]\", 9).json();\n\n        assertThat(ints).containsExactly(0, 9, 2, 3);\n    }\n\n    @Test\n    public void an_array_index_can_be_updated() {\n\n        String res = parse(JSON_DOCUMENT).set(\"$.store.book[0]\", \"a\").read(\"$.store.book[0]\");\n\n        assertThat(res).isEqualTo(\"a\");\n    }\n\n    @Test\n    public void an_array_slice_can_be_updated() {\n\n        List<String> res = parse(JSON_DOCUMENT).set(\"$.store.book[0:2]\", \"a\").read(\"$.store.book[0:2]\");\n\n        assertThat(res).containsExactly(\"a\", \"a\");\n    }\n\n    @Test\n    public void an_array_criteria_can_be_updated() {\n\n        List<String> res = parse(JSON_DOCUMENT)\n                .set(\"$.store.book[?(@.category == 'fiction')]\", \"a\")\n                .read(\"$.store.book[?(@ == 'a')]\");\n\n        assertThat(res).containsExactly(\"a\", \"a\", \"a\");\n    }\n\n    @Test\n    public void an_array_criteria_can_be_deleted() {\n\n        List<String> res = parse(JSON_DOCUMENT)\n                .delete(\"$.store.book[?(@.category == 'fiction')]\")\n                .read(\"$.store.book[*].category\");\n\n        assertThat(res).containsExactly(\"reference\");\n    }\n\n    @Test\n    public void an_array_criteria_with_multiple_results_can_be_deleted(){\n        InputStream stream = this.getClass().getResourceAsStream(\"/json_array_multiple_delete.json\");\n        String deletePath = \"$._embedded.mandates[?(@.count=~/0/)]\";\n        DocumentContext documentContext = JsonPath.parse(stream);\n        documentContext.delete(deletePath);\n        List<Object> result = documentContext.read(deletePath);\n        assertThat(result.size()).isEqualTo(0);\n    }\n\n\n    @Test\n    public void multi_prop_delete() {\n\n        List<Map<String, Object>> res = parse(JSON_DOCUMENT).delete(\"$.store.book[*]['author', 'category']\").read(\"$.store.book[*]['author', 'category']\");\n\n        assertThat(res).containsExactly(EMPTY_MAP, EMPTY_MAP, EMPTY_MAP, EMPTY_MAP);\n    }\n\n    @Test\n    public void multi_prop_update() {\n\n        Map<String, Object> expected = new HashMap<String, Object>(){{\n            put(\"author\", \"a\");\n            put(\"category\", \"a\");\n        }};\n\n        List<Map<String, Object>> res = parse(JSON_DOCUMENT).set(\"$.store.book[*]['author', 'category']\", \"a\").read(\"$.store.book[*]['author', 'category']\");\n\n        assertThat(res).containsExactly(expected, expected, expected, expected);\n    }\n\n\n    @Test\n    public void multi_prop_update_not_all_defined() {\n\n        Map<String, Object> expected = new HashMap<String, Object>(){{\n            put(\"author\", \"a\");\n            put(\"isbn\", \"a\");\n        }};\n\n        List<Map<String, Object>> res = parse(JSON_DOCUMENT).set(\"$.store.book[*]['author', 'isbn']\", \"a\").read(\"$.store.book[*]['author', 'isbn']\");\n\n        assertThat(res).containsExactly(expected, expected, expected, expected);\n    }\n\n    @Test\n    public void add_to_array() {\n        Object res = parse(JSON_DOCUMENT).add(\"$.store.book\", 1).read(\"$.store.book[4]\");\n        assertThat(res).isEqualTo(1);\n    }\n\n    @Test\n    public void add_to_object() {\n        Object res = parse(JSON_DOCUMENT).put(\"$.store.book[0]\", \"new-key\", \"new-value\").read(\"$.store.book[0].new-key\");\n        assertThat(res).isEqualTo(\"new-value\");\n    }\n\n    @Test\n    public void item_can_be_added_to_root_array() {\n        List<Integer> model = new LinkedList<>();\n        model.add(1);\n        model.add(2);\n\n        List<Integer> ints = parse(model).add(\"$\", 3).read(\"$\");\n\n        assertThat(ints).containsExactly(1,2,3);\n    }\n\n    @Test\n    public void key_val_can_be_added_to_root_object() {\n        Map model = new HashMap();\n        model.put(\"a\", \"a-val\");\n\n        String newVal = parse(model).put(\"$\", \"new-key\", \"new-val\").read(\"$.new-key\");\n\n        assertThat(newVal).isEqualTo(\"new-val\");\n    }\n\n    @Test\n    public void add_to_object_on_array() {\n        assertThrows(InvalidModificationException.class, () -> parse(JSON_DOCUMENT).put(\"$.store.book\", \"new-key\", \"new-value\"));\n    }\n\n    @Test\n    public void add_to_array_on_object() {\n        assertThrows(InvalidModificationException.class, () -> parse(JSON_DOCUMENT).add(\"$.store.book[0]\", \"new-value\"));\n    }\n\n\n    @Test\n    public void root_object_can_not_be_updated() {\n        Map model = new HashMap();\n        model.put(\"a\", \"a-val\");\n\n        assertThrows(InvalidModificationException.class, () -> parse(model).set(\"$[?(@.a == 'a-val')]\", 1));\n    }\n\n    @Test\n    public void a_path_can_be_renamed(){\n        Object o = parse(JSON_DOCUMENT).renameKey(\"$.store\", \"book\", \"updated-book\").json();\n        List<Object> result = parse(o).read(\"$.store.updated-book\");\n\n        assertThat(result).isNotEmpty();\n    }\n\n    @Test\n    public void keys_in_root_containing_map_can_be_renamed(){\n        Object o = parse(JSON_DOCUMENT).renameKey(\"$\", \"store\", \"new-store\").json();\n        List<Object> result = parse(o).read(\"$.new-store[*]\");\n        assertThat(result).isNotEmpty();\n    }\n\n    @Test\n    public void map_array_items_can_be_renamed(){\n        Object o = parse(JSON_DOCUMENT).renameKey(\"$.store.book[*]\", \"category\", \"renamed-category\").json();\n        List<Object> result = parse(o).read(\"$.store.book[*].renamed-category\");\n        assertThat(result).isNotEmpty();\n    }\n\n    @Test\n    public void non_map_array_items_cannot_be_renamed(){\n        List<Integer> model = new LinkedList<>();\n        model.add(1);\n        model.add(2);\n        assertThrows(InvalidModificationException.class, () -> parse(model).renameKey(\"$[*]\", \"oldKey\", \"newKey\"));\n    }\n\n    @Test\n    public void multiple_properties_cannot_be_renamed(){\n        assertThrows(InvalidModificationException.class, () ->parse(JSON_DOCUMENT).renameKey(\"$.store.book[*]['author', 'category']\", \"old-key\", \"new-key\"));\n    }\n\n    @Test\n    public void non_existent_key_rename_not_allowed(){\n        assertThrows(PathNotFoundException.class, () -> parse(JSON_DOCUMENT).renameKey(\"$\", \"fake\", \"new-fake\").json());\n    }\n\n    @Test\n    public void rootCannotBeMapped(){\n        MapFunction mapFunction = new MapFunction() {\n            @Override\n            public Object map(Object currentValue, Configuration configuration) {\n                return currentValue.toString()+\"converted\";\n            }\n        };\n        assertThrows(InvalidModificationException.class, () -> parse(JSON_DOCUMENT).map(\"$\", mapFunction).json());\n    }\n\n    @Test\n    public void single_match_value_can_be_mapped(){\n        MapFunction mapFunction = new ToStringMapFunction();\n        String stringResult = parse(JSON_DOCUMENT).map(\"$.string-property\", mapFunction).read(\"$.string-property\");\n        assertThat(stringResult.endsWith(\"converted\")).isTrue();\n    }\n\n    @Test\n    public void object_can_be_mapped(){\n        TypeRef<List<String>> typeRef = new TypeRef<List<String>>() {};\n        MapFunction mapFunction = new ToStringMapFunction();\n        DocumentContext documentContext = JsonPath.using(JACKSON_CONFIGURATION).parse(JSON_DOCUMENT);\n        Object list = documentContext.read(\"$..book\");\n        assertThat(list).isInstanceOf(List.class);\n        String result = documentContext.map(\"$..book\", mapFunction).read(\"$..book\", typeRef).get(0);\n        assertThat(result).isInstanceOf(String.class);\n        assertThat(result).endsWith(\"converted\");\n    }\n\n    @Test\n    public void multi_match_path_can_be_mapped(){\n        MapFunction mapFunction = new ToStringMapFunction();\n        List<Double> doubleResult = parse(JSON_DOCUMENT).read(\"$..display-price\");\n        for(Double dRes : doubleResult){\n            assertThat(dRes).isInstanceOf(Double.class);\n        }\n        List<String> stringResult = parse(JSON_DOCUMENT).map(\"$..display-price\", mapFunction).read(\"$..display-price\");\n        for(String sRes : stringResult){\n            assertThat(sRes).isInstanceOf(String.class);\n            assertThat(sRes.endsWith(\"converted\")).isTrue();\n        }\n    }\n\n    // Helper converter implementation for test cases.\n    private class ToStringMapFunction implements MapFunction {\n\n        @Override\n        public Object map(Object currentValue, Configuration configuration) {\n            return currentValue.toString()+\"converted\";\n        }\n    }\n}"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/JsonContextTest.java",
    "content": "package com.jayway.jsonpath.internal;\n\nimport com.jayway.jsonpath.BaseTest;\nimport com.jayway.jsonpath.Criteria;\nimport com.jayway.jsonpath.DocumentContext;\nimport com.jayway.jsonpath.Filter;\nimport com.jayway.jsonpath.JsonPath;\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\npublic class JsonContextTest extends BaseTest {\n\n\t@Test\n    public void cached_path_with_predicates() {\n\n        Filter feq = Filter.filter(Criteria.where(\"category\").eq(\"reference\"));\n        Filter fne = Filter.filter(Criteria.where(\"category\").ne(\"reference\"));\n        \n        DocumentContext JsonDoc = JsonPath.parse(JSON_DOCUMENT);\n\n        List<String> eq = JsonDoc.read(\"$.store.book[?].category\", feq);\n        List<String> ne = JsonDoc.read(\"$.store.book[?].category\", fne);\n\n        Assertions.assertThat(eq).contains(\"reference\");\n        Assertions.assertThat(ne).doesNotContain(\"reference\");\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/UtilsTest.java",
    "content": "package com.jayway.jsonpath.internal;\n\nimport com.jayway.jsonpath.JsonPathException;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\n\npublic class UtilsTest {\n\n\n    @Test\n    public void testJoin() {\n        ArrayList<String> strings = new ArrayList<String>();\n        strings.add(\"foo\");\n        strings.add(\"bar\");\n        strings.add(\"baz\");\n\n        Assertions.assertEquals(\"foo,bar,baz\", Utils.join(\",\", strings));\n        Assertions.assertEquals(\"\", Utils.join(\",\", new ArrayList<String>()));\n    }\n\n    @Test\n    public void testConcat() {\n        Assertions.assertEquals(\"\", Utils.concat());\n        Assertions.assertEquals(\"\", Utils.concat(\"\"));\n        Assertions.assertEquals(\"\", Utils.concat(\"\", \"\"));\n        Assertions.assertEquals(\"a\", Utils.concat(\"a\"));\n        Assertions.assertEquals(\"a\", Utils.concat(\"\", \"a\", \"\"));\n        Assertions.assertEquals(\"abc\", Utils.concat(\"a\", \"b\", \"c\"));\n    }\n\n    @Test\n    public void testEscape() {\n        Assertions.assertNull(Utils.escape(null, true));\n\n        Assertions.assertEquals(\"\\\\\\\\f\\\\'o\\\\\\\"o\\\\rb\\\\fa\\\\t\\\\nr\\\\bb\\\\/a\", Utils.escape(\"\\\\f\\'o\\\"o\\rb\\fa\\t\\nr\\bb/a\", true));\n        Assertions.assertEquals(\"\\\\uFFFF\\\\u0FFF\\\\u00FF\\\\u000F\\\\u0010\", Utils.escape(\"\\uffff\\u0fff\\u00ff\\u000f\\u0010\", true));\n    }\n\n    @Test\n    public void testUnescape() {\n        Assertions.assertNull(Utils.unescape(null));\n\n        Assertions.assertEquals(\"foo\", Utils.unescape(\"foo\"));\n        Assertions.assertEquals(\"\\\\\", Utils.unescape(\"\\\\\"));\n        Assertions.assertEquals(\"\\\\\", Utils.unescape(\"\\\\\\\\\"));\n        Assertions.assertEquals(\"\\'\", Utils.unescape(\"\\\\\\'\"));\n        Assertions.assertEquals(\"\\\"\", Utils.unescape(\"\\\\\\\"\"));\n        Assertions.assertEquals(\"\\r\", Utils.unescape(\"\\\\r\"));\n        Assertions.assertEquals(\"\\f\", Utils.unescape(\"\\\\f\"));\n        Assertions.assertEquals(\"\\t\", Utils.unescape(\"\\\\t\"));\n        Assertions.assertEquals(\"\\n\", Utils.unescape(\"\\\\n\"));\n        Assertions.assertEquals(\"\\b\", Utils.unescape(\"\\\\b\"));\n        Assertions.assertEquals(\"a\", Utils.unescape(\"\\\\a\"));\n        Assertions.assertEquals(\"\\uffff\", Utils.unescape(\"\\\\uffff\"));\n    }\n\n    @Test\n    public void testUnescapeThrow() {\n        Assertions.assertThrows(JsonPathException.class, () -> Utils.unescape(\"\\\\uuuuu\"));\n    }\n\n    @Test\n    public void testHex() {\n        Assertions.assertEquals(\"61\", Utils.hex('a'));\n        Assertions.assertEquals(\"24\", Utils.hex('$'));\n    }\n\n    @Test\n    public void testIsEmpty() {\n        Assertions.assertTrue(Utils.isEmpty(null));\n        Assertions.assertTrue(Utils.isEmpty(\"\"));\n\n        Assertions.assertFalse(Utils.isEmpty(\"foo\"));\n    }\n\n    @Test\n    public void testIndexOf() {\n        Assertions.assertEquals(-1, Utils.indexOf(\"bar\", \"foo\", 0));\n        Assertions.assertEquals(-1, Utils.indexOf(\"bar\", \"a\", 2));\n        Assertions.assertEquals(1, Utils.indexOf(\"bar\", \"a\", 0));\n        Assertions.assertEquals(1, Utils.indexOf(\"bar\", \"a\", 1));\n    }\n\n    @Test\n    public void testNotNull() {\n        Assertions.assertEquals(\"\", Utils.notNull(\"\", \"bar\", \"a\", \"b\", \"c\"));\n        Assertions.assertEquals(\"foo\", Utils.notNull(\"foo\", \"bar\", \"a\", \"b\", \"c\"));\n    }\n\n    @Test\n    public void testNotNullThrow() {\n        Assertions.assertThrows(IllegalArgumentException.class, () -> Utils.notNull(null, \"bar\", \"a\", \"b\", \"c\"));\n    }\n\n    @Test\n    public void testCloseQuietly() throws IllegalArgumentException {\n        Assertions.assertThrows(IllegalArgumentException.class, () -> Utils.notNull(null, \"bar\", \"a\", \"b\", \"c\"));\n    }\n\n    @Test\n    public void testIsTrue() {\n        Utils.isTrue(true, \"foo\");\n    }\n\n    @Test\n    public void testIsTrueThrow() {\n        Assertions.assertThrows(IllegalArgumentException.class, () -> Utils.isTrue(false, \"foo\"));\n    }\n\n    @Test\n    public void testOnlyOneIsTrueThrow1() {\n        Assertions.assertThrows(IllegalArgumentException.class, () -> Utils.onlyOneIsTrue(\"foo\", false, false));\n    }\n\n    @Test\n    public void testOnlyOneIsTrueThrow2() {\n        Assertions.assertThrows(IllegalArgumentException.class, () -> Utils.onlyOneIsTrue(\"foo\", true, true));\n    }\n\n    @Test\n    public void testOnlyOneIsTrueNonThrow() {\n        Assertions.assertTrue(Utils.onlyOneIsTrueNonThrow(true));\n\n        Assertions.assertFalse(Utils.onlyOneIsTrueNonThrow(true, true, true));\n        Assertions.assertFalse(Utils.onlyOneIsTrueNonThrow(true, true, false));\n        Assertions.assertFalse(Utils.onlyOneIsTrueNonThrow(false, false, false));\n    }\n\n    @Test\n    public void testNotEmpty() {\n        Assertions.assertEquals(\"bar\", Utils.notEmpty(\"bar\", \"foo\", 1, 2, 3));\n        Assertions.assertEquals(\"baz\", Utils.notEmpty(\"baz\", \"bar\", \"b\", \"a\", \"r\"));\n    }\n\n    @Test\n    public void testNotEmptyThrowNull() {\n        Assertions.assertThrows(IllegalArgumentException.class, () -> Utils.notEmpty(null, \"foo\", 1, 2, 3));\n    }\n\n    @Test\n    public void testNotEmptyThrowLength0() {\n        Assertions.assertThrows(IllegalArgumentException.class, () -> Utils.notEmpty(\"\", \"foo\", 1, 2, 3));\n    }\n\n    @Test\n    public void testToString() {\n        Assertions.assertNull(Utils.toString(null));\n\n        Assertions.assertEquals(\"\", Utils.toString(\"\"));\n        Assertions.assertEquals(\"foo\", Utils.toString(\"foo\"));\n        Assertions.assertEquals(\"123\", Utils.toString(123));\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/filter/PatternFlagTest.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport com.jayway.jsonpath.BaseTest;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\n\nimport java.util.stream.Stream;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class PatternFlagTest extends BaseTest {\n\n\n    @ParameterizedTest\n    @MethodSource(\"testData\")\n    public void testParseFlags(int flags, String expectedFlags) {\n        assertEquals(expectedFlags, PatternFlag.parseFlags(flags));\n    }\n\n    public static Stream<Arguments> testData() {\n        return Stream.of(\n                Arguments.arguments(1, \"d\"),\n                Arguments.arguments(2, \"i\"),\n                Arguments.arguments(4, \"x\"),\n                Arguments.arguments(8, \"m\"),\n                Arguments.arguments(32, \"s\"),\n                Arguments.arguments(64, \"u\"),\n                Arguments.arguments(256, \"U\"),\n                Arguments.arguments(300, \"xmsU\"),\n                Arguments.arguments(13, \"dxm\"),\n                Arguments.arguments(7, \"dix\"),\n                Arguments.arguments(100, \"xsu\"),\n                Arguments.arguments(367, \"dixmsuU\")\n        );\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/filter/RegexpEvaluatorTest.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport com.jayway.jsonpath.BaseTest;\nimport com.jayway.jsonpath.Predicate;\nimport com.jayway.jsonpath.internal.Path;\nimport com.jayway.jsonpath.internal.path.CompiledPath;\nimport com.jayway.jsonpath.internal.path.PathTokenFactory;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\n\nimport java.util.HashMap;\nimport java.util.stream.Stream;\n\nimport static com.jayway.jsonpath.internal.filter.ValueNode.*;\nimport static org.hamcrest.CoreMatchers.equalTo;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.MatcherAssert.assertThat;\n\npublic class RegexpEvaluatorTest extends BaseTest {\n\n\n    @ParameterizedTest\n    @MethodSource(\"testData\")\n    public void should_evaluate_regular_expression(String regexp, ValueNode valueNode, boolean expectedResult) {\n        //given\n        Evaluator evaluator = EvaluatorFactory.createEvaluator(RelationalOperator.REGEX);\n        ValueNode patternNode = createPatternNode(regexp);\n        Predicate.PredicateContext ctx = createPredicateContext();\n\n        //when\n        boolean result = evaluator.evaluate(patternNode, valueNode, ctx);\n\n        //then\n        assertThat(result, is(equalTo(expectedResult)));\n    }\n\n    public static Stream<Arguments> testData() {\n        return Stream.of(\n                Arguments.arguments(\"/true|false/\", createStringNode(\"true\", true), true),\n                Arguments.arguments(\"/9.*9/\", createNumberNode(\"9979\"), true),\n                Arguments.arguments(\"/fa.*se/\", createBooleanNode(\"false\"), true),\n                Arguments.arguments(\"/Eval.*or/\", createClassNode(String.class), false),\n                Arguments.arguments(\"/JsonNode/\", createJsonNode(json()), false),\n                Arguments.arguments(\"/PathNode/\", createPathNode(path()), false),\n                Arguments.arguments(\"/Undefined/\", createUndefinedNode(), false),\n                Arguments.arguments(\"/NullNode/\", createNullNode(), false),\n                Arguments.arguments(\"/test/i\", createStringNode(\"tEsT\", true), true),\n                Arguments.arguments(\"/test/\", createStringNode(\"tEsT\", true), false),\n                Arguments.arguments(\"/\\u00de/ui\", createStringNode(\"\\u00fe\", true), true),\n                Arguments.arguments(\"/\\u00de/\", createStringNode(\"\\u00fe\", true), false),\n                Arguments.arguments(\"/\\u00de/i\", createStringNode(\"\\u00fe\", true), false),\n                Arguments.arguments(\"/test# code/\", createStringNode(\"test\", true), false),\n                Arguments.arguments(\"/test# code/x\", createStringNode(\"test\", true), true),\n                Arguments.arguments(\"/.*test.*/d\", createStringNode(\"my\\rtest\", true), true),\n                Arguments.arguments(\"/.*test.*/\", createStringNode(\"my\\rtest\", true), false),\n                Arguments.arguments(\"/.*tEst.*/is\", createStringNode(\"test\\ntest\", true), true),\n                Arguments.arguments(\"/.*tEst.*/i\", createStringNode(\"test\\ntest\", true), false),\n                Arguments.arguments(\"/^\\\\w+$/U\", createStringNode(\"\\u00fe\", true), true),\n                Arguments.arguments(\"/^\\\\w+$/\", createStringNode(\"\\u00fe\", true), false)\n        );\n    }\n\n    private static Path path() {\n        return new CompiledPath(PathTokenFactory.createRootPathToken('$'), true);\n    }\n\n    private static String json() {\n        return \"{ 'some': 'JsonNode' }\";\n    }\n\n    private Predicate.PredicateContext createPredicateContext() {\n        return createPredicateContext(new HashMap<>());\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/filter/RelationalOperatorTest.java",
    "content": "package com.jayway.jsonpath.internal.filter;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Locale;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class RelationalOperatorTest {\n\n    Locale locale;\n\n    @BeforeEach\n    public void saveDefaultLocale() {\n        locale = Locale.getDefault();\n    }\n\n    @AfterEach\n    public void restoreDefaultLocale() {\n        Locale.setDefault(locale);\n    }\n\n    @Test\n    public void testFromStringWithEnglishLocale() {\n        Locale.setDefault(Locale.ENGLISH);\n        assertEquals(RelationalOperator.IN, RelationalOperator.fromString(\"in\"));\n        assertEquals(RelationalOperator.IN, RelationalOperator.fromString(\"IN\"));\n    }\n\n    @Test\n    public void testFromStringWithTurkishLocale() {\n        Locale.setDefault(new Locale(\"tr\", \"TR\"));\n        assertEquals(RelationalOperator.IN, RelationalOperator.fromString(\"in\"));\n        assertEquals(RelationalOperator.IN, RelationalOperator.fromString(\"IN\"));\n    }\n\n}"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/function/BaseFunctionTest.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.Configuration;\n\nimport java.io.IOException;\nimport java.util.Scanner;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * Created by mattg on 6/27/15.\n */\npublic class BaseFunctionTest {\n    protected static final String NUMBER_SERIES = \"{\\\"empty\\\": [], \\\"numbers\\\" : [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}\";\n    protected static final String TEXT_SERIES = \"{\\\"urls\\\": [\\\"http://api.worldbank.org/countries/all/?format=json\\\", \\\"http://api.worldbank.org/countries/all/?format=json\\\"], \\\"text\\\" : [ \\\"a\\\", \\\"b\\\", \\\"c\\\", \\\"d\\\", \\\"e\\\", \\\"f\\\" ]}\";\n    protected static final String TEXT_AND_NUMBER_SERIES = \"{\\\"text\\\" : [ \\\"a\\\", \\\"b\\\", \\\"c\\\", \\\"d\\\", \\\"e\\\", \\\"f\\\" ], \\\"numbers\\\" : [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}\";\n\n    /**\n     * Verify the function returns the correct result based on the input expectedValue\n     *\n     * @param pathExpr\n     *      The path expression to execute\n     *\n     * @param json\n     *      The json document (actual content) to parse\n     *\n     * @param expectedValue\n     *      The expected value to be returned from the test\n     */\n    protected void verifyFunction(Configuration conf, String pathExpr, String json, Object expectedValue) {\n        Object result = using(conf).parse(json).read(pathExpr);\n        assertThat(conf.jsonProvider().unwrap(result)).isEqualTo(expectedValue);\n    }\n\n    protected void verifyMathFunction(Configuration conf, String pathExpr, Object expectedValue) {\n        verifyFunction(conf, pathExpr, NUMBER_SERIES, expectedValue);\n    }\n\n    protected void verifyTextFunction(Configuration conf, String pathExpr, Object expectedValue) {\n        verifyFunction(conf, pathExpr, TEXT_SERIES, expectedValue);\n    }\n\n    protected void verifyTextAndNumberFunction(Configuration conf, String pathExpr, Object expectedValue) {\n        verifyFunction(conf, pathExpr, TEXT_AND_NUMBER_SERIES, expectedValue);\n    }\n\n    protected String getResourceAsText(String resourceName) throws IOException {\n        return new Scanner(BaseFunctionTest.class.getResourceAsStream(resourceName), \"UTF-8\").useDelimiter(\"\\\\A\").next();\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/function/Issue191.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.Configurations;\nimport com.jayway.jsonpath.JsonPath;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.InputStream;\n\n\n/**\n * TDD for Issue 191\n * <p>\n * Shows aggregation across fields rather than within a single entity.\n */\npublic class Issue191 {\n\n    private Configuration conf = Configurations.GSON_CONFIGURATION;\n\n    @Test\n    public void testResultSetNumericComputation() {\n        InputStream stream = ClassLoader.getSystemResourceAsStream(\"issue_191.json\");\n        Long value = JsonPath.parse(stream).read(\"$.sum($..timestamp)\", Long.class);\n        Assertions.assertEquals(Long.valueOf(35679716813L), value, \"Expected the max function to consume the aggregation parameters and calculate the max over the result set\");\n    }\n\n    @Test\n    public void testResultSetNumericComputationTail() {\n        InputStream stream = ClassLoader.getSystemResourceAsStream(\"issue_191.json\");\n        Long value = JsonPath.parse(stream).read(\"$..timestamp.sum()\", Long.class);\n        Assertions.assertEquals(Long.valueOf(35679716813L), value, \"Expected the max function to consume the aggregation parameters and calculate the max over the result set\");\n    }\n\n    @Test\n    public void testResultSetNumericComputationRecursiveReplacement() {\n        InputStream stream = ClassLoader.getSystemResourceAsStream(\"issue_191.json\");\n        Long value = JsonPath.parse(stream).read(\"$.max($..timestamp.avg(), $..timestamp.stddev())\", Long.class);\n        Assertions.assertEquals(Long.valueOf(1427188672L), value, \"Expected the max function to consume the aggregation parameters and calculate the max over the result set\");\n    }\n\n    @Test\n    public void testMultipleResultSetSums() {\n        InputStream stream = ClassLoader.getSystemResourceAsStream(\"issue_191.json\");\n        Long value = JsonPath.parse(stream).read(\"$.sum($..timestamp, $..cpus)\", Long.class);\n        Assertions.assertEquals(Long.valueOf(35679716835L), value, \"Expected the max function to consume the aggregation parameters and calculate the max over the result set\");\n    }\n\n    @Test\n    public void testConcatResultSet() {\n        InputStream stream = ClassLoader.getSystemResourceAsStream(\"issue_191.json\");\n        String concatResult = JsonPath.parse(stream).read(\"$.concat($..state)\", String.class);\n        Assertions.assertEquals(concatResult.length(), 806, \"Expected a string length to be a concat of all of the states\");\n    }\n\n    @Test\n    public void testConcatWithNumericValueAsString() {\n        InputStream stream = ClassLoader.getSystemResourceAsStream(\"issue_191.json\");\n        String concatResult = JsonPath.parse(stream).read(\"$.concat($..cpus)\", String.class);\n        Assertions.assertEquals(concatResult.length(), 489, \"Expected a string length to be a concat of all of the cpus\");\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/function/Issue234.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.JsonPath;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * TDD for Issue #234\n *\n * Verifies the use-case where-in the function path expression is cached and re-used but the JsonPath includes a function\n * whose arguments are then dependent upon state that changes externally from the internal Cache.getCache state.  The\n * prior implementation had a bug where-in the parameter values were cached -- the present implementation (as of Issue #234)\n * now uses a late binding approach to eval the function parameters.  Cache invalidation isn't an option given the need\n * for nested function calls.\n *\n * Once this bug is fixed, most of the concern then centers around the need to ensure nested functions are processed\n * correctly.\n *\n * @see NestedFunctionTest for examples of where that is performed.\n *\n */\npublic class Issue234 {\n\n    @Test\n    public void testIssue234() {\n        Map<String, String> context = new HashMap<>();\n        context.put(\"key\", \"first\");\n        Object value = JsonPath.read(context, \"concat(\\\"/\\\", $.key)\");\n        assertThat(value).isEqualTo(\"/first\");\n        context.put(\"key\", \"second\");\n        value = JsonPath.read(context, \"concat(\\\"/\\\", $.key)\");\n        assertThat(value).isEqualTo(\"/second\");\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/function/Issue273.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.JsonPath;\nimport net.minidev.json.JSONArray;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\npublic class Issue273 {\n    @Test\n    public void testGetPropertyFromArray() {\n        String json = \"[\\n\" +\n                \"   [\\n\" +\n                \"      {\\n\" +\n                \"         \\\"category\\\" : \\\"reference\\\",\\n\" +\n                \"         \\\"author\\\" : \\\"Nigel Rees\\\",\\n\" +\n                \"         \\\"title\\\" : \\\"Sayings of the Century\\\",\\n\" +\n                \"         \\\"price\\\" : 8.95\\n\" +\n                \"      },\\n\" +\n                \"      {\\n\" +\n                \"         \\\"category\\\" : \\\"fiction\\\",\\n\" +\n                \"         \\\"author\\\" : \\\"Evelyn Waugh\\\",\\n\" +\n                \"         \\\"title\\\" : \\\"Sword of Honour\\\",\\n\" +\n                \"         \\\"price\\\" : 12.99\\n\" +\n                \"      },\\n\" +\n                \"      {\\n\" +\n                \"         \\\"category\\\" : \\\"fiction\\\",\\n\" +\n                \"         \\\"author\\\" : \\\"Herman Melville\\\",\\n\" +\n                \"         \\\"title\\\" : \\\"Moby Dick\\\",\\n\" +\n                \"         \\\"isbn\\\" : \\\"0-553-21311-3\\\",\\n\" +\n                \"         \\\"price\\\" : 8.99\\n\" +\n                \"      },\\n\" +\n                \"      {\\n\" +\n                \"         \\\"category\\\" : \\\"fiction\\\",\\n\" +\n                \"         \\\"author\\\" : \\\"J. R. R. Tolkien\\\",\\n\" +\n                \"         \\\"title\\\" : \\\"The Lord of the Rings\\\",\\n\" +\n                \"         \\\"isbn\\\" : \\\"0-395-19395-8\\\",\\n\" +\n                \"         \\\"price\\\" : 22.99\\n\" +\n                \"      }\\n\" +\n                \"   ],\\n\" +\n                \"   {\\n\" +\n                \"      \\\"color\\\" : \\\"red\\\",\\n\" +\n                \"      \\\"price\\\" : 19.95\\n\" +\n                \"   }\\n\" +\n                \"]\\n\";\n\n        JSONArray arr = JsonPath.read(json, \"$..[2].author\");\n        Assertions.assertEquals(arr.get(0), \"Herman Melville\");\n    }\n\n    @Test\n    public void testGetPropertyFromObject() {\n        String json = \"{\\n\" +\n                \"    \\\"store\\\": {\\n\" +\n                \"        \\\"book\\\": [\\n\" +\n                \"            {\\n\" +\n                \"                \\\"category\\\": \\\"reference\\\",\\n\" +\n                \"                \\\"author\\\": \\\"Nigel Rees\\\",\\n\" +\n                \"                \\\"title\\\": \\\"Sayings of the Century\\\",\\n\" +\n                \"                \\\"price\\\": 8.95\\n\" +\n                \"            },\\n\" +\n                \"            {\\n\" +\n                \"                \\\"category\\\": \\\"fiction\\\",\\n\" +\n                \"                \\\"author\\\": \\\"Evelyn Waugh\\\",\\n\" +\n                \"                \\\"title\\\": \\\"Sword of Honour\\\",\\n\" +\n                \"                \\\"price\\\": 12.99\\n\" +\n                \"            },\\n\" +\n                \"            {\\n\" +\n                \"                \\\"category\\\": \\\"fiction\\\",\\n\" +\n                \"                \\\"author\\\": \\\"Herman Melville\\\",\\n\" +\n                \"                \\\"title\\\": \\\"Moby Dick\\\",\\n\" +\n                \"                \\\"isbn\\\": \\\"0-553-21311-3\\\",\\n\" +\n                \"                \\\"price\\\": 8.99\\n\" +\n                \"            },\\n\" +\n                \"            {\\n\" +\n                \"                \\\"category\\\": \\\"fiction\\\",\\n\" +\n                \"                \\\"author\\\": \\\"J. R. R. Tolkien\\\",\\n\" +\n                \"                \\\"title\\\": \\\"The Lord of the Rings\\\",\\n\" +\n                \"                \\\"isbn\\\": \\\"0-395-19395-8\\\",\\n\" +\n                \"                \\\"price\\\": 22.99\\n\" +\n                \"            }\\n\" +\n                \"        ],\\n\" +\n                \"        \\\"bicycle\\\": {\\n\" +\n                \"            \\\"color\\\": \\\"red\\\",\\n\" +\n                \"            \\\"price\\\": 19.95\\n\" +\n                \"        }\\n\" +\n                \"    },\\n\" +\n                \"    \\\"expensive\\\": 10\\n\" +\n                \"}\\n\" +\n                \"                \";\n        JSONArray arr = JsonPath.read(json, \"$..[2].author\");\n        Assertions.assertEquals(arr.get(0), \"Herman Melville\");\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/function/Issue612.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.DocumentContext;\nimport com.jayway.jsonpath.JsonPath;\nimport com.jayway.jsonpath.Option;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\npublic class Issue612 {\n    @Test\n    public void test() {\n        Configuration config = Configuration.builder()\n                .options(Option.SUPPRESS_EXCEPTIONS)\n                .build();\n        String json = \"{\\\"1\\\":{\\\"2\\\":null}}\";\n        DocumentContext documentContext = JsonPath.using(config).parse(json);\n        JsonPath query = JsonPath.compile(\"$.1.2.a.b.c\");\n        Assertions.assertNull(documentContext.read(query));\n        Assertions.assertNull(documentContext.map(query, (object, configuration) -> object));\n    }\n\n    @Test\n    public void test2() {\n        Configuration config = Configuration.builder()\n                .build();\n        String json = \"{\\\"1\\\":{\\\"2\\\":null}}\";\n        DocumentContext documentContext = JsonPath.using(config).parse(json);\n        JsonPath query = JsonPath.compile(\"$.1.2.a.b.c\");\n\n        Assertions.assertThrows(Exception.class, () -> documentContext.map(query, (object, configuration) -> object));\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/function/Issue629.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.JsonPath;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\n\n\npublic class Issue629 {\n    @Test\n    public void testUncloseParenthesis() throws IOException {\n        try {\n            JsonPath jsonPath = JsonPath.compile(\"$.A.B.C.D(\");\n            fail(\"accepted jsonpath with unclosed parentheses\");\n        } catch (Exception e) {\n            assertTrue(e.getMessage().startsWith(\"Arguments to function:\"));\n        }\n    }\n\n    @Test\n    public void testUncloseParenthesisWithNestedCall() throws IOException {\n        try {\n            JsonPath jsonPath = JsonPath.compile(\"$.A.B.C.sum(D()\");\n            fail(\"accepted jsonpath with unclosed parentheses\");\n        } catch (Exception e) {\n            assertTrue(e.getMessage().startsWith(\"Arguments to function:\"));\n        }\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/function/Issue680.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.JsonPath;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class Issue680 {\n\n    @Test\n    public void testIssue680concat() {\n        String json = \"{ \\\"key\\\": \\\"first\\\"}\";\n        Object value = JsonPath.read(json, \"concat(\\\"/\\\", $.key)\");\n        assertThat(value).isEqualTo(\"/first\");\n        json = \"{ \\\"key\\\": \\\"second\\\"}\";\n        value = JsonPath.read(json, \"concat(\\\"/\\\", $.key)\");\n        assertThat(value).isEqualTo(\"/second\");\n    }\n\n    @Test\n    public void testIssue680min() {\n        String json = \"{ \\\"key\\\": 1}\";\n        double value = JsonPath.read(json, \"min($.key)\");\n        assertThat(value).isEqualTo(1d);\n        json = \"{ \\\"key\\\": 2}\";\n        value = JsonPath.read(json, \"min($.key)\");\n        assertThat(value).isEqualTo(2d);\n    }\n\n    @Test\n    public void testIssue680concat_2() {\n        Map<String, String> context = new HashMap<String, String>();\n        context.put(\"key\", \"first\");\n        Object value = JsonPath.read(context, \"concat(\\\"/\\\", $.key)\");\n        assertThat(value).isEqualTo(\"/first\");\n        Map<String, String> context2 = new HashMap<String, String>();\n        context2.put(\"key\", \"second\");\n        value = JsonPath.read(context2, \"concat(\\\"/\\\", $.key)\");\n        assertThat(value).isEqualTo(\"/second\");\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/function/JSONEntityPathFunctionTest.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.Configurations;\nimport net.minidev.json.JSONArray;\nimport org.junit.jupiter.api.Test;\n\n/**\n * Verifies methods that are helper implementations of functions for manipulating JSON entities, i.e.\n * length, etc.\n *\n * Created by mattg on 6/27/15.\n */\npublic class JSONEntityPathFunctionTest extends BaseFunctionTest {\n\n\n    private static final String BATCH_JSON = \"{\\n\" +\n            \"  \\\"batches\\\": {\\n\" +\n            \"    \\\"minBatchSize\\\": 10,\\n\" +\n            \"    \\\"results\\\": [\\n\" +\n            \"      {\\n\" +\n            \"        \\\"productId\\\": 23,\\n\" +\n            \"        \\\"values\\\": [\\n\" +\n            \"          2,\\n\" +\n            \"          45,\\n\" +\n            \"          34,\\n\" +\n            \"          23,\\n\" +\n            \"          3,\\n\" +\n            \"          5,\\n\" +\n            \"          4,\\n\" +\n            \"          3,\\n\" +\n            \"          2,\\n\" +\n            \"          1,\\n\" +\n            \"        ]\\n\" +\n            \"      },\\n\" +\n            \"      {\\n\" +\n            \"        \\\"productId\\\": 23,\\n\" +\n            \"        \\\"values\\\": [\\n\" +\n            \"          52,\\n\" +\n            \"          3,\\n\" +\n            \"          12,\\n\" +\n            \"          11,\\n\" +\n            \"          18,\\n\" +\n            \"          22,\\n\" +\n            \"          1\\n\" +\n            \"        ]\\n\" +\n            \"      }\\n\" +\n            \"    ]\\n\" +\n            \"  }\\n\" +\n            \"}\";\n\n\n\n\n    private Configuration conf = Configurations.JSON_SMART_CONFIGURATION;\n\n    @Test\n    public void testLengthOfTextArray() {\n        // The length of JSONArray is an integer\n        verifyFunction(conf, \"$['text'].length()\", TEXT_SERIES, 6);\n        verifyFunction(conf, \"$['text'].size()\", TEXT_SERIES, 6);\n    }\n    @Test\n    public void testLengthOfNumberArray() {\n        // The length of JSONArray is an integer\n        verifyFunction(conf, \"$.numbers.length()\", NUMBER_SERIES, 10);\n        verifyFunction(conf, \"$.numbers.size()\", NUMBER_SERIES, 10);\n    }\n\n\n    @Test\n    public void testLengthOfStructure() {\n        verifyFunction(conf, \"$.batches.length()\", BATCH_JSON, 2);\n    }\n\n    /**\n     * The fictitious use-case/story - is we have a collection of batches with values indicating some quality metric.\n     * We want to determine the average of the values for only the batch's values where the number of items in the batch\n     * is greater than the min batch size which is encoded in the JSON document.\n     *\n     * We use the length function in the predicate to determine the number of values in each batch and then for those\n     * batches where the count is greater than min we calculate the average batch value.\n     *\n     * Its completely contrived example, however, this test exercises functions within predicates.\n     */\n    @Test\n    public void testPredicateWithFunctionCallSingleMatch() {\n        String path = \"$.batches.results[?(@.values.length() >= $.batches.minBatchSize)].values.avg()\";\n\n        // Its an array because in some use-cases the min size might match more than one batch and thus we'll get\n        // the average out for each collection\n        JSONArray values = new JSONArray();\n        values.add(12.2d);\n        verifyFunction(conf, path, BATCH_JSON, values);\n    }\n\n    @Test\n    public void testPredicateWithFunctionCallTwoMatches() {\n        String path = \"$.batches.results[?(@.values.length() >= 3)].values.avg()\";\n\n        // Its an array because in some use-cases the min size might match more than one batch and thus we'll get\n        // the average out for each collection\n        JSONArray values = new JSONArray();\n        values.add(12.2d);\n        values.add(17d);\n        verifyFunction(conf, path, BATCH_JSON, values);\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/function/KeySetFunctionTest.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.Configurations;\nimport org.apache.commons.io.IOUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.HashSet;\n\n/**\n * Author: Sergey Saiyan sergey.sova42@gmail.com\n * Created at 21/02/2018.\n */\npublic class KeySetFunctionTest extends BaseFunctionTest {\n\n    private Configuration conf = Configurations.JACKSON_CONFIGURATION;\n\n    @Test\n    public void testKeySet() throws Exception {\n        String json = IOUtils.toString(getClass().getResourceAsStream(\"/keyset.json\"));\n        verifyFunction(conf, \"$.data.keys()\", json, new HashSet<String>(Arrays.asList(\"a\", \"b\")));\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/function/NestedFunctionTest.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.Configurations;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * Created by matt@mjgreenwood.net on 12/10/15.\n */\npublic class NestedFunctionTest extends BaseFunctionTest {\n    private static final Logger logger = LoggerFactory.getLogger(NumericPathFunctionTest.class);\n\n\n    public static Iterable<Configuration> configurations() {\n        return Configurations.configurations();\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testParameterAverageFunctionCall(Configuration conf) {\n        verifyMathFunction(conf, \"$.avg($.numbers.min(), $.numbers.max())\", 5.5);\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testArrayAverageFunctionCall(Configuration conf) {\n        verifyMathFunction(conf, \"$.numbers.avg()\", 5.5);\n    }\n\n    /**\n     * This test calculates the following:\n     * <p>\n     * For each number in $.numbers 1 -> 10 add each number up,\n     * then add 1 (min), 10 (max)\n     * <p>\n     * Alternatively 1+2+3+4+5+6+7+8+9+10+1+10 == 66\n     */\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testArrayAverageFunctionCallWithParameters(Configuration conf) {\n        verifyMathFunction(conf, \"$.numbers.sum($.numbers.min(), $.numbers.max())\", 66.0);\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testJsonInnerArgumentArray(Configuration conf) {\n        verifyMathFunction(conf, \"$.sum(5, 3, $.numbers.max(), 2)\", 20.0);\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testSimpleLiteralArgument(Configuration conf) {\n        verifyMathFunction(conf, \"$.sum(5)\", 5.0);\n        verifyMathFunction(conf, \"$.sum(50)\", 50.0);\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testStringConcat(Configuration conf) {\n        verifyTextFunction(conf, \"$.text.concat()\", \"abcdef\");\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testStringAndNumberConcat(Configuration conf) {\n        verifyTextAndNumberFunction(conf, \"$.concat($.text[0], $.numbers[0])\", \"a1\");\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testStringConcatWithJSONParameter(Configuration conf) {\n        verifyTextFunction(conf, \"$.text.concat(\\\"-\\\", \\\"ghijk\\\")\", \"abcdef-ghijk\");\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testAppendNumber(Configuration conf) {\n        verifyMathFunction(conf, \"$.numbers.append(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0).avg()\", 10.0);\n    }\n\n    /**\n     * Aggregation function should ignore text values\n     */\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testAppendTextAndNumberThenSum(Configuration conf) {\n        verifyMathFunction(conf, \"$.numbers.append(\\\"0\\\", \\\"11\\\").sum()\", 55.0);\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testErrantCloseBraceNegative(Configuration conf) {\n        try {\n            using(conf).parse(this.NUMBER_SERIES).read(\"$.numbers.append(0, 1, 2}).avg()\");\n            assert (false);\n        } catch (Exception e) {\n            assertTrue(e.getMessage().startsWith(\"Unexpected close brace\"));\n        }\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testErrantCloseBracketNegative(Configuration conf) {\n        try {\n            using(conf).parse(this.NUMBER_SERIES).read(\"$.numbers.append(0, 1, 2]).avg()\");\n            assert (false);\n        } catch (Exception e) {\n            assertTrue(e.getMessage().startsWith(\"Unexpected close bracket\"));\n        }\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testUnclosedFunctionCallNegative(Configuration conf) {\n        try {\n            using(conf).parse(this.NUMBER_SERIES).read(\"$.numbers.append(0, 1, 2\");\n            assert (false);\n        } catch (Exception e) {\n            assertTrue(e.getMessage().startsWith(\"Arguments to function: 'append'\"));\n        }\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/function/NumericPathFunctionTest.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.Configurations;\nimport com.jayway.jsonpath.JsonPathException;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n\n/**\n * Defines functional tests around executing:\n * <p>\n * - sum\n * - avg\n * - stddev\n * <p>\n * for each of the above, executes the test and verifies that the results are as expected based on a static input\n * and static output.\n * <p>\n * Created by mattg on 6/26/15.\n */\npublic class NumericPathFunctionTest extends BaseFunctionTest {\n\n    public static Iterable<Configuration> configurations() {\n        return Configurations.configurations();\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testAverageOfDoubles(Configuration conf) {\n        verifyMathFunction(conf, \"$.numbers.avg()\", 5.5);\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testAverageOfEmptyListNegative(Configuration conf) {\n        try {\n            verifyMathFunction(conf, \"$.empty.avg()\", null);\n        } catch (JsonPathException e) {\n            assertEquals(e.getMessage(), \"Aggregation function attempted to calculate value using empty array\");\n        }\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testSumOfDouble(Configuration conf) {\n        verifyMathFunction(conf, \"$.numbers.sum()\", (10d * (10d + 1d)) / 2d);\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testSumOfEmptyListNegative(Configuration conf) {\n        try {\n            verifyMathFunction(conf, \"$.empty.sum()\", null);\n        } catch (JsonPathException e) {\n            assertEquals(e.getMessage(), \"Aggregation function attempted to calculate value using empty array\");\n        }\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testMaxOfDouble(Configuration conf) {\n        verifyMathFunction(conf, \"$.numbers.max()\", 10d);\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testMaxOfEmptyListNegative(Configuration conf) {\n        try {\n            verifyMathFunction(conf, \"$.empty.max()\", null);\n        } catch (JsonPathException e) {\n            assertEquals(e.getMessage(), \"Aggregation function attempted to calculate value using empty array\");\n        }\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testMinOfDouble(Configuration conf) {\n        verifyMathFunction(conf, \"$.numbers.min()\", 1d);\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testMinOfEmptyListNegative(Configuration conf) {\n        try {\n            verifyMathFunction(conf, \"$.empty.min()\", null);\n        } catch (JsonPathException e) {\n            assertEquals(e.getMessage(), \"Aggregation function attempted to calculate value using empty array\");\n        }\n    }\n\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testStdDevOfDouble(Configuration conf) {\n        verifyMathFunction(conf, \"$.numbers.stddev()\", 2.8722813232690143d);\n    }\n\n    @ParameterizedTest\n    @MethodSource(\"configurations\")\n    public void testStddevOfEmptyListNegative(Configuration conf) {\n        try {\n            verifyMathFunction(conf, \"$.empty.stddev()\", null);\n        } catch (JsonPathException e) {\n            assertEquals(e.getMessage(), \"Aggregation function attempted to calculate value using empty array\");\n        }\n    }\n\n    /**\n     * Expect that for an invalid function name we'll get back the original input to the function\n     */\n//    @Test\n//    @Ignore\n//    public void testInvalidFunctionNameNegative() {\n//        JSONArray numberSeries = new JSONArray();\n//        numberSeries.addAll(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));\n//        assertThat(using(conf).parse(NUMBER_SERIES).read(\"$.numbers.foo()\")).isEqualTo(numberSeries);\n//    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/function/SequentialPathFunctionTest.java",
    "content": "package com.jayway.jsonpath.internal.function;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.Configurations;\nimport org.junit.jupiter.api.Test;\n\n/**\n * Test cases for functions\n * \n * -first\n * -last\n * -index(X)\n *\n * Created by git9527 on 6/11/22.\n */\npublic class SequentialPathFunctionTest extends BaseFunctionTest {\n\n    private Configuration conf = Configurations.JACKSON_CONFIGURATION;\n\n    @Test\n    public void testFirstOfNumbers() throws Exception {\n        verifyFunction(conf, \"$.numbers.first()\", NUMBER_SERIES, 1);\n    }\n    \n    @Test\n    public void testLastOfNumbers() throws Exception {\n        verifyFunction(conf, \"$.numbers.last()\", NUMBER_SERIES, 10);\n    }\n    \n    @Test\n    public void testIndexOfNumbers() throws Exception {\n        verifyFunction(conf, \"$.numbers.index(0)\", NUMBER_SERIES, 1);\n        verifyFunction(conf, \"$.numbers.index(-1)\", NUMBER_SERIES, 10);\n        verifyFunction(conf, \"$.numbers.index(1)\", NUMBER_SERIES, 2);\n    }\n\n    @Test\n    public void testFirstOfText() throws Exception {\n        verifyFunction(conf, \"$.text.first()\", TEXT_SERIES, \"a\");\n    }\n\n    @Test\n    public void testLastOfText() throws Exception {\n        verifyFunction(conf, \"$.text.last()\", TEXT_SERIES, \"f\");\n    }\n\n    @Test\n    public void testIndexOfText() throws Exception {\n        verifyFunction(conf, \"$.text.index(0)\", TEXT_SERIES, \"a\");\n        verifyFunction(conf, \"$.text.index(-1)\", TEXT_SERIES, \"f\");\n        verifyFunction(conf, \"$.text.index(1)\", TEXT_SERIES, \"b\");\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/internal/path/PathTokenTest.java",
    "content": "package com.jayway.jsonpath.internal.path;\n\nimport com.jayway.jsonpath.BaseTest;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class PathTokenTest extends BaseTest {\n\n    @Test\n    public void is_upstream_definite_in_simple_case() {\n        assertThat(makePathReturningTail(makePPT(\"foo\")).isUpstreamDefinite()).isTrue();\n\n        assertThat(makePathReturningTail(makePPT(\"foo\"), makePPT(\"bar\")).isUpstreamDefinite()).isTrue();\n\n        assertThat(makePathReturningTail(makePPT(\"foo\", \"foo2\"), makePPT(\"bar\")).isUpstreamDefinite()).isFalse();\n\n        assertThat(makePathReturningTail(new WildcardPathToken(), makePPT(\"bar\")).isUpstreamDefinite()).isFalse();\n\n        assertThat(makePathReturningTail(new ScanPathToken(), makePPT(\"bar\")).isUpstreamDefinite()).isFalse();\n    }\n\n    @Test\n    public void is_upstream_definite_in_complex_case() {\n        assertThat(makePathReturningTail(makePPT(\"foo\"), makePPT(\"bar\"), makePPT(\"baz\")).isUpstreamDefinite()).isTrue();\n\n        assertThat(makePathReturningTail(makePPT(\"foo\"), new WildcardPathToken()).isUpstreamDefinite()).isTrue();\n\n        assertThat(makePathReturningTail(new WildcardPathToken(), makePPT(\"bar\"), makePPT(\"baz\")).isUpstreamDefinite()).isFalse();\n    }\n\n\n    private PathToken makePPT(final String ... properties) {\n        return new PropertyPathToken(Arrays.asList(properties), '\\'');\n    }\n\n    private PathToken makePathReturningTail(final PathToken ... tokens) {\n        PathToken last = null;\n        for (final PathToken token : tokens) {\n            if (last != null) {\n                last.appendTailToken(token);\n            }\n            last = token;\n        }\n        return last;\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/issue_613.java",
    "content": "package com.jayway.jsonpath;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.time.OffsetDateTime;\nimport java.time.ZoneOffset;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\nimport static com.jayway.jsonpath.Criteria.where;\nimport static com.jayway.jsonpath.Filter.filter;\nimport static org.assertj.core.api.Assertions.assertThat;\n\n//test for issue: https://github.com/json-path/JsonPath/issues/613\npublic class issue_613 extends BaseTest{\n    final OffsetDateTime ofdt_small = OffsetDateTime.of(1999,2,1,1,1,1,1, ZoneOffset.UTC);\n    final OffsetDateTime ofdt_middle = OffsetDateTime.of(2000,2,1,1,1,1,1, ZoneOffset.UTC);\n    final OffsetDateTime ofdt_big = OffsetDateTime.of(2001,3,1,1,1,1,1, ZoneOffset.MAX);\n\n    Map<String,OffsetDateTime> map_middle = new LinkedHashMap<String, OffsetDateTime>(){\n        {\n            put(\"time\",ofdt_middle);\n        }};\n\n    @Test\n    public void issue_613_eq_ne_test() {\n        assertThat(filter(where(\"time\").eq(ofdt_middle)).apply(createPredicateContext(map_middle))).isEqualTo(true);\n        assertThat(filter(where(\"time\").ne(ofdt_big)).apply(createPredicateContext(map_middle))).isEqualTo(true);\n    }\n    @Test\n    public void issue_613_lt_lte_test() {\n        assertThat(filter(where(\"time\").lt(ofdt_big)).apply(createPredicateContext(map_middle))).isEqualTo(true);\n        assertThat(filter(where(\"time\").lte(ofdt_small)).apply(createPredicateContext(map_middle))).isEqualTo(false);\n    }\n    @Test\n    public void issue_613_gt_gte_test() {\n        assertThat(filter(where(\"time\").gt(ofdt_big)).apply(createPredicateContext(map_middle))).isEqualTo(false);\n        assertThat(filter(where(\"time\").gte(ofdt_small)).apply(createPredicateContext(map_middle))).isEqualTo(true);\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/ArraySlicingTest.java",
    "content": "package com.jayway.jsonpath.old;\n\nimport com.jayway.jsonpath.JsonPath;\nimport org.hamcrest.Matchers;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * If you have a list\n * nums = [1, 3, 5, 7, 8, 13, 20]\n * then it is possible to slice by using a notation similar to element retrieval:\n * <p>\n * nums[3]   #equals 7, no slicing\n * nums[:3]  #equals [1, 3, 5], from index 0 (inclusive) until index 3 (exclusive)\n * nums[1:5] #equals [3, 5, 7, 8]\n * nums[-3:] #equals [8, 13, 20]\n * nums[3:] #equals [8, 13, 20]\n * <p>\n * Note that Python allows negative list indices. The index -1 represents the last element, -2 the penultimate element, etc.\n * Python also allows a step property by appending an extra colon and a value. For example:\n * <p>\n * nums[3::]  #equals [7, 8, 13, 20], same as nums[3:]\n * nums[::3]  #equals [1, 7, 20] (starting at index 0 and getting every third element)\n * nums[1:5:2] #equals [3, 7] (from index 1 until index 5 and getting every second element)\n */\npublic class ArraySlicingTest {\n\n    public static final String JSON_ARRAY = \"[1, 3, 5, 7, 8, 13, 20]\";\n\n    @Test\n    public void get_by_position() {\n        Integer result = JsonPath.read(JSON_ARRAY, \"$[3]\");\n        assertEquals(7, result.intValue());\n    }\n\n    @Test\n    public void get_from_index() {\n        List<Integer> result = JsonPath.read(JSON_ARRAY, \"$[:3]\");\n        assertThat(result, Matchers.contains(1, 3, 5));\n    }\n\n    @Test\n    public void get_between_index() {\n        List<Integer> result = JsonPath.read(JSON_ARRAY, \"$[1:5]\");\n        assertThat(result, Matchers.contains(3, 5, 7, 8));\n    }\n\n\n    @Test\n    public void get_between_index_2() {\n        List<Integer> result = JsonPath.read(JSON_ARRAY, \"$[0:1]\");\n        assertThat(result, Matchers.contains(1));\n    }\n\n    @Test\n    public void get_between_index_3() {\n        List<Integer> result = JsonPath.read(JSON_ARRAY, \"$[0:2]\");\n        assertThat(result, Matchers.contains(1, 3));\n    }\n\n    @Test\n    public void get_between_index_out_of_bounds() {\n        List<Integer> result = JsonPath.read(JSON_ARRAY, \"$[1:15]\");\n        assertThat(result, Matchers.contains(3, 5, 7, 8, 13, 20));\n    }\n\n    @Test\n    public void get_from_tail_index() {\n        List<Integer> result = JsonPath.read(JSON_ARRAY, \"$[-3:]\");\n        assertThat(result, Matchers.contains(8, 13, 20));\n    }\n\n    @Test\n    public void get_from_tail() {\n        List<Integer> result = JsonPath.read(JSON_ARRAY, \"$[3:]\");\n        assertThat(result, Matchers.contains(7, 8, 13, 20));\n    }\n\n    @Test\n    public void get_indexes() {\n        List<Integer> result = JsonPath.read(JSON_ARRAY, \"$[0,1,2]\");\n        assertThat(result, Matchers.contains(1, 3, 5));\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/ComplianceTest.java",
    "content": "package com.jayway.jsonpath.old;\n\nimport com.jayway.jsonpath.JsonPath;\nimport org.hamcrest.Matchers;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.*;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * test defined in http://jsonpath.googlecode.com/svn/trunk/tests/jsonpath-test-js.html\n */\npublic class ComplianceTest {\n\n    @Test\n    public void test_one() throws Exception {\n\n        String json = \"{ \\\"a\\\": \\\"a\\\",\\n\" +\n                \"           \\\"b\\\": \\\"b\\\",\\n\" +\n                \"           \\\"c d\\\": \\\"e\\\" \\n\" +\n                \"         }\";\n\n        assertThat(JsonPath.<String>read(json, \"$.a\"), equalTo(\"a\"));\n        assertThat(JsonPath.<List<String>>read(json, \"$.*\"), hasItems(\"a\", \"b\", \"e\"));\n        assertThat(JsonPath.<List<String>>read(json, \"$[*]\"), hasItems(\"a\", \"b\", \"e\"));\n        assertThat(JsonPath.<String>read(json, \"$['a']\"), equalTo(\"a\"));\n        assertThat(JsonPath.<String>read(json, \"$.['c d']\"), is(equalTo(\"e\")));\n        assertThat(JsonPath.<List<String>>read(json, \"$[*]\"), hasItems(\"a\", \"b\", \"e\"));\n    }\n\n    @Test\n    public void test_two() throws Exception {\n        String json = \"[ 1, \\\"2\\\", 3.14, true, null ]\";\n\n        assertThat(JsonPath.<Integer>read(json, \"$[0]\"), is(equalTo(1)));\n        assertThat(JsonPath.<Integer>read(json, \"$[4]\"), is(equalTo(null)));\n        assertThat(JsonPath.<List<Comparable>>read(json, \"$[*]\"), hasItems(\n                new Integer(1),\n                new String(\"2\"),\n                new Double(3.14),\n                new Boolean(true),\n                (Comparable) null));\n\n        List<Object> res = JsonPath.read(json, \"$[-1:]\");\n\n        assertTrue(res.get(0) == null);\n    }\n\n    @Test\n    public void test_three() throws Exception {\n        String json = \"{ \\\"points\\\": [\\n\" +\n                \"             { \\\"id\\\": \\\"i1\\\", \\\"x\\\":  4, \\\"y\\\": -5 },\\n\" +\n                \"             { \\\"id\\\": \\\"i2\\\", \\\"x\\\": -2, \\\"y\\\":  2, \\\"z\\\": 1 },\\n\" +\n                \"             { \\\"id\\\": \\\"i3\\\", \\\"x\\\":  8, \\\"y\\\":  3 },\\n\" +\n                \"             { \\\"id\\\": \\\"i4\\\", \\\"x\\\": -6, \\\"y\\\": -1 },\\n\" +\n                \"             { \\\"id\\\": \\\"i5\\\", \\\"x\\\":  0, \\\"y\\\":  2, \\\"z\\\": 1 },\\n\" +\n                \"             { \\\"id\\\": \\\"i6\\\", \\\"x\\\":  1, \\\"y\\\":  4 }\\n\" +\n                \"           ]\\n\" +\n                \"         }\";\n\n        assertThat(JsonPath.<Map<String, Comparable>>read(json, \"$.points[1]\"), allOf(\n                Matchers.<String, Comparable>hasEntry(\"id\", \"i2\"),\n                Matchers.<String, Comparable>hasEntry(\"x\", -2),\n                Matchers.<String, Comparable>hasEntry(\"y\", 2),\n                Matchers.<String, Comparable>hasEntry(\"z\", 1)\n        ));\n\n        assertThat(JsonPath.<Integer>read(json, \"$.points[4].x\"), equalTo(0));\n        assertThat(JsonPath.<List<Integer>>read(json, \"$.points[?(@.id == 'i4')].x\"), hasItem(-6));\n        assertThat(JsonPath.<List<Integer>>read(json, \"$.points[*].x\"), hasItems(4, -2, 8, -6, 0, 1));\n        assertThat(JsonPath.<List<String>>read(json, \"$.points[?(@.z)].id\"), hasItems(\"i2\", \"i5\"));\n    }\n\n    @Test\n    public void test_four() throws Exception {\n        String json = \"{ \\\"menu\\\": {\\n\" +\n                \"                 \\\"header\\\": \\\"SVG Viewer\\\",\\n\" +\n                \"                 \\\"items\\\": [\\n\" +\n                \"                     {\\\"id\\\": \\\"Open\\\"},\\n\" +\n                \"                     {\\\"id\\\": \\\"OpenNew\\\", \\\"label\\\": \\\"Open New\\\"},\\n\" +\n                \"                     null,\\n\" +\n                \"                     {\\\"id\\\": \\\"ZoomIn\\\", \\\"label\\\": \\\"Zoom In\\\"},\\n\" +\n                \"                     {\\\"id\\\": \\\"ZoomOut\\\", \\\"label\\\": \\\"Zoom Out\\\"},\\n\" +\n                \"                     {\\\"id\\\": \\\"OriginalView\\\", \\\"label\\\": \\\"Original View\\\"},\\n\" +\n                \"                     null,\\n\" +\n                \"                     {\\\"id\\\": \\\"Quality\\\"},\\n\" +\n                \"                     {\\\"id\\\": \\\"Pause\\\"},\\n\" +\n                \"                     {\\\"id\\\": \\\"Mute\\\"},\\n\" +\n                \"                     null,\\n\" +\n                \"                     {\\\"id\\\": \\\"Find\\\", \\\"label\\\": \\\"Find...\\\"},\\n\" +\n                \"                     {\\\"id\\\": \\\"FindAgain\\\", \\\"label\\\": \\\"Find Again\\\"},\\n\" +\n                \"                     {\\\"id\\\": \\\"Copy\\\"},\\n\" +\n                \"                     {\\\"id\\\": \\\"CopyAgain\\\", \\\"label\\\": \\\"Copy Again\\\"},\\n\" +\n                \"                     {\\\"id\\\": \\\"CopySVG\\\", \\\"label\\\": \\\"Copy SVG\\\"},\\n\" +\n                \"                     {\\\"id\\\": \\\"ViewSVG\\\", \\\"label\\\": \\\"View SVG\\\"},\\n\" +\n                \"                     {\\\"id\\\": \\\"ViewSource\\\", \\\"label\\\": \\\"View Source\\\"},\\n\" +\n                \"                     {\\\"id\\\": \\\"SaveAs\\\", \\\"label\\\": \\\"Save As\\\"},\\n\" +\n                \"                     null,\\n\" +\n                \"                     {\\\"id\\\": \\\"Help\\\"},\\n\" +\n                \"                     {\\\"id\\\": \\\"About\\\", \\\"label\\\": \\\"About Adobe CVG Viewer...\\\"}\\n\" +\n                \"                 ]\\n\" +\n                \"               }\\n\" +\n                \"             }\";\n\n        assertThat(JsonPath.<List<String>>read(json, \"$.menu.items[?(@)]\"), Matchers.is(notNullValue()));\n        assertThat(JsonPath.<List<String>>read(json, \"$.menu.items[?(@.id == 'ViewSVG')].id\"), hasItems(\"ViewSVG\"));\n        assertThat(JsonPath.<List<String>>read(json, \"$.menu.items[?(@ && @.id == 'ViewSVG')].id\"), hasItems(\"ViewSVG\"));\n\n        assertThat(JsonPath.<List<String>>read(json, \"$.menu.items[?(@ && @.id && !@.label)].id\"), hasItems(\"Open\", \"Quality\", \"Pause\", \"Mute\", \"Copy\", \"Help\")); //low\n\n\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/FilterTest.java",
    "content": "package com.jayway.jsonpath.old;\n\nimport com.jayway.jsonpath.*;\nimport com.jayway.jsonpath.spi.json.JsonProvider;\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.regex.Pattern;\n\nimport static com.jayway.jsonpath.Criteria.where;\nimport static com.jayway.jsonpath.Filter.filter;\nimport static java.util.Arrays.asList;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FilterTest extends BaseTest {\n\n    public final static String DOCUMENT =\n            \"{ \\\"store\\\": {\\n\" +\n                    \"    \\\"book\\\": [ \\n\" +\n                    \"      { \\\"category\\\": \\\"reference\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Nigel Rees\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Sayings of the Century\\\",\\n\" +\n                    \"        \\\"price\\\": 8.95\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Evelyn Waugh\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Sword of Honour\\\",\\n\" +\n                    \"        \\\"price\\\": 12.99\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Herman Melville\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Moby Dick\\\",\\n\" +\n                    \"        \\\"isbn\\\": \\\"0-553-21311-3\\\",\\n\" +\n                    \"        \\\"price\\\": 8.99\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"J. R. R. Tolkien\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"The Lord of the Rings\\\",\\n\" +\n                    \"        \\\"isbn\\\": \\\"0-395-19395-8\\\",\\n\" +\n                    \"        \\\"price\\\": 22.99\\n\" +\n                    \"      }\\n\" +\n                    \"    ],\\n\" +\n                    \"    \\\"bicycle\\\": {\\n\" +\n                    \"      \\\"color\\\": \\\"red\\\",\\n\" +\n                    \"      \\\"price\\\": 19.95,\\n\" +\n                    \"      \\\"foo:bar\\\": \\\"fooBar\\\",\\n\" +\n                    \"      \\\"dot.notation\\\": \\\"new\\\"\\n\" +\n                    \"    }\\n\" +\n                    \"  }\\n\" +\n                    \"}\";\n\n    private static final Configuration conf = Configuration.defaultConfiguration();\n\n    private static final JsonProvider jp = conf.jsonProvider();\n\n    public void is_filters_evaluates() throws Exception {\n        final Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"foo\", \"foo\");\n        check.put(\"bar\", null);\n\n        assertTrue(filter(where(\"bar\").is(null)).apply(createPredicateContext(check)));\n        assertTrue(filter(where(\"foo\").is(\"foo\")).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo\").is(\"xxx\")).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"bar\").is(\"xxx\")).apply(createPredicateContext(check)));\n    }\n\n\n    @Test\n    public void ne_filters_evaluates() throws Exception {\n        final Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"foo\", \"foo\");\n        check.put(\"bar\", null);\n\n        assertTrue(filter(where(\"foo\").ne(null)).apply(createPredicateContext(check)));\n        assertTrue(filter(where(\"foo\").ne(\"not foo\")).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo\").ne(\"foo\")).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"bar\").ne(null)).apply(createPredicateContext(check)));\n    }\n\n    @Test\n    public void gt_filters_evaluates() throws Exception {\n        final Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"foo\", 12.5D);\n        check.put(\"foo_null\", null);\n\n        assertTrue(filter(where(\"foo\").gt(12D)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo\").gt(null)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo\").gt(20D)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo_null\").gt(20D)).apply(createPredicateContext(check)));\n    }\n\n    @Test\n    public void gte_filters_evaluates() throws Exception {\n        Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"foo\", 12.5D);\n        check.put(\"foo_null\", null);\n\n        assertTrue(filter(where(\"foo\").gte(12D)).apply(createPredicateContext(check)));\n        assertTrue(filter(where(\"foo\").gte(12.5D)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo\").gte(null)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo\").gte(20D)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo_null\").gte(20D)).apply(createPredicateContext(check)));\n    }\n\n    @Test\n    public void lt_filters_evaluates() throws Exception {\n        Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"foo\", 10.5D);\n        check.put(\"foo_null\", null);\n\n        //assertTrue(filter(where(\"foo\").lt(12D)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo\").lt(null)).apply(createPredicateContext(check)));\n        //assertFalse(filter(where(\"foo\").lt(5D)).apply(createPredicateContext(check)));\n        //assertFalse(filter(where(\"foo_null\").lt(5D)).apply(createPredicateContext(check)));\n    }\n\n    @Test\n    public void lte_filters_evaluates() throws Exception {\n        Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"foo\", 12.5D);\n        check.put(\"foo_null\", null);\n\n        assertTrue(filter(where(\"foo\").lte(13D)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo\").lte(null)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo\").lte(5D)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo_null\").lte(5D)).apply(createPredicateContext(check)));\n    }\n\n    @Test\n    public void in_filters_evaluates() throws Exception {\n        Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"item\", 3);\n        check.put(\"null_item\", null);\n\n        assertTrue(filter(where(\"item\").in(1, 2, 3)).apply(createPredicateContext(check)));\n        assertTrue(filter(where(\"item\").in(asList(1, 2, 3))).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"item\").in(4, 5, 6)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"item\").in(asList(4, 5, 6))).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"item\").in(asList('A'))).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"item\").in(asList((Object) null))).apply(createPredicateContext(check)));\n\n        assertTrue(filter(where(\"null_item\").in((Object) null)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"null_item\").in(1, 2, 3)).apply(createPredicateContext(check)));\n    }\n\n    @Test\n    public void nin_filters_evaluates() throws Exception {\n        Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"item\", 3);\n        check.put(\"null_item\", null);\n\n        assertTrue(filter(where(\"item\").nin(4, 5)).apply(createPredicateContext(check)));\n        assertTrue(filter(where(\"item\").nin(asList(4, 5))).apply(createPredicateContext(check)));\n        assertTrue(filter(where(\"item\").nin(asList('A'))).apply(createPredicateContext(check)));\n        assertTrue(filter(where(\"null_item\").nin(1, 2, 3)).apply(createPredicateContext(check)));\n        assertTrue(filter(where(\"item\").nin(asList((Object) null))).apply(createPredicateContext(check)));\n\n        assertFalse(filter(where(\"item\").nin(3)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"item\").nin(asList(3))).apply(createPredicateContext(check)));\n    }\n\n    @Test\n    public void all_filters_evaluates() throws Exception {\n        Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"items\", asList(1, 2, 3));\n\n        assertTrue(filter(where(\"items\").all(1, 2, 3)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"items\").all(1, 2, 3, 4)).apply(createPredicateContext(check)));\n    }\n\n    @Test\n    public void size_filters_evaluates() throws Exception {\n        Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"items\", asList(1, 2, 3));\n        check.put(\"items_empty\", Collections.emptyList());\n\n        assertTrue(filter(where(\"items\").size(3)).apply(createPredicateContext(check)));\n        assertTrue(filter(where(\"items_empty\").size(0)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"items\").size(2)).apply(createPredicateContext(check)));\n    }\n\n    @Test\n    public void exists_filters_evaluates() throws Exception {\n        Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"foo\", \"foo\");\n        check.put(\"foo_null\", null);\n\n        assertTrue(filter(where(\"foo\").exists(true)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo\").exists(false)).apply(createPredicateContext(check)));\n\n        assertTrue(filter(where(\"foo_null\").exists(true)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"foo_null\").exists(false)).apply(createPredicateContext(check)));\n\n        assertTrue(filter(where(\"bar\").exists(false)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"bar\").exists(true)).apply(createPredicateContext(check)));\n    }\n\n    @Test\n    public void type_filters_evaluates() throws Exception {\n        Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"string\", \"foo\");\n        check.put(\"string_null\", null);\n        check.put(\"int\", 1);\n        check.put(\"long\", 1L);\n        check.put(\"double\", 1.12D);\n        check.put(\"boolean\", true);\n\n        assertFalse(filter(where(\"string_null\").type(String.class)).apply(createPredicateContext(check)));\n        assertTrue(filter(where(\"string\").type(String.class)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"string\").type(Number.class)).apply(createPredicateContext(check)));\n\n        assertTrue(filter(where(\"int\").type(Number.class)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"int\").type(String.class)).apply(createPredicateContext(check)));\n\n        assertTrue(filter(where(\"long\").type(Number.class)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"long\").type(String.class)).apply(createPredicateContext(check)));\n\n        assertTrue(filter(where(\"double\").type(Number.class)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"double\").type(String.class)).apply(createPredicateContext(check)));\n\n        assertTrue(filter(where(\"boolean\").type(Boolean.class)).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"boolean\").type(String.class)).apply(createPredicateContext(check)));\n    }\n\n    @Test\n    public void pattern_filters_evaluates() throws Exception {\n        Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"name\", \"kalle\");\n        check.put(\"name_null\", null);\n\n        assertFalse(filter(where(\"name_null\").regex(Pattern.compile(\".alle\"))).apply(createPredicateContext(check)));\n        assertTrue(filter(where(\"name\").regex(Pattern.compile(\".alle\"))).apply(createPredicateContext(check)));\n        assertFalse(filter(where(\"name\").regex(Pattern.compile(\"KALLE\"))).apply(createPredicateContext(check)));\n        assertTrue(filter(where(\"name\").regex(Pattern.compile(\"KALLE\", Pattern.CASE_INSENSITIVE))).apply(createPredicateContext(check)));\n\n    }\n\n    @Test\n    public void combine_filter_deep_criteria() {\n\n        String json = \"[\\n\" +\n                \"   {\\n\" +\n                \"      \\\"first-name\\\" : \\\"John\\\",\\n\" +\n                \"      \\\"last-name\\\" : \\\"Irving\\\",\\n\" +\n                \"      \\\"address\\\" : {\\\"state\\\" : \\\"Texas\\\"}\\n\" +\n                \"   },\\n\" +\n                \"   {\\n\" +\n                \"      \\\"first-name\\\" : \\\"Jock\\\",\\n\" +\n                \"      \\\"last-name\\\" : \\\"Ewing\\\",\\n\" +\n                \"      \\\"address\\\" : {\\\"state\\\" : \\\"Texas\\\"}\\n\" +\n                \"   },\\n\" +\n                \"   {\\n\" +\n                \"      \\\"first-name\\\" : \\\"Jock\\\",\\n\" +\n                \"      \\\"last-name\\\" : \\\"Barnes\\\",\\n\" +\n                \"      \\\"address\\\" : {\\\"state\\\" : \\\"Nevada\\\"}\\n\" +\n                \"   } \\n\" +\n                \"]\";\n\n\n        Filter filter = filter(\n                where(\"first-name\").is(\"Jock\")\n                        .and(\"address.state\").is(\"Texas\"));\n\n        List<Map<String, Object>> jocksInTexas1 = JsonPath.read(json, \"$[?]\", filter);\n        List<Map<String, Object>> jocksInTexas2 = JsonPath.read(json, \"$[?(@.first-name == 'Jock' && @.address.state == 'Texas')]\");\n\n\n        JsonPath.parse(json).json();\n\n        assertThat((String) JsonPath.read(jocksInTexas1, \"$[0].address.state\"), is(\"Texas\"));\n        assertThat((String) JsonPath.read(jocksInTexas1, \"$[0].first-name\"), is(\"Jock\"));\n        assertThat((String) JsonPath.read(jocksInTexas1, \"$[0].last-name\"), is(\"Ewing\"));\n\n    }\n\n    //-------------------------------------------------\n    //\n    // Single filter tests\n    //\n    //-------------------------------------------------\n\n    @Test\n    public void filters_can_be_combined() throws Exception {\n\n        Map<String, Object> check = new HashMap<String, Object>();\n        check.put(\"string\", \"foo\");\n        check.put(\"string_null\", null);\n        check.put(\"int\", 10);\n        check.put(\"long\", 1L);\n        check.put(\"double\", 1.12D);\n\n        Filter shouldMarch = filter(where(\"string\").is(\"foo\").and(\"int\").lt(11));\n        Filter shouldNotMarch = filter(where(\"string\").is(\"foo\").and(\"int\").gt(11));\n\n        assertTrue(shouldMarch.apply(createPredicateContext(check)));\n        assertFalse(shouldNotMarch.apply(createPredicateContext(check)));\n    }\n\n\n    @Test\n    public void arrays_of_maps_can_be_filtered() throws Exception {\n\n\n        Map<String, Object> rootGrandChild_A = new HashMap<String, Object>();\n        rootGrandChild_A.put(\"name\", \"rootGrandChild_A\");\n\n        Map<String, Object> rootGrandChild_B = new HashMap<String, Object>();\n        rootGrandChild_B.put(\"name\", \"rootGrandChild_B\");\n\n        Map<String, Object> rootGrandChild_C = new HashMap<String, Object>();\n        rootGrandChild_C.put(\"name\", \"rootGrandChild_C\");\n\n\n        Map<String, Object> rootChild_A = new HashMap<String, Object>();\n        rootChild_A.put(\"name\", \"rootChild_A\");\n        rootChild_A.put(\"children\", asList(rootGrandChild_A, rootGrandChild_B, rootGrandChild_C));\n\n        Map<String, Object> rootChild_B = new HashMap<String, Object>();\n        rootChild_B.put(\"name\", \"rootChild_B\");\n        rootChild_B.put(\"children\", asList(rootGrandChild_A, rootGrandChild_B, rootGrandChild_C));\n\n        Map<String, Object> rootChild_C = new HashMap<String, Object>();\n        rootChild_C.put(\"name\", \"rootChild_C\");\n        rootChild_C.put(\"children\", asList(rootGrandChild_A, rootGrandChild_B, rootGrandChild_C));\n\n        Map<String, Object> root = new HashMap<String, Object>();\n        root.put(\"children\", asList(rootChild_A, rootChild_B, rootChild_C));\n\n\n        Predicate customFilter = new Predicate() {\n            @Override\n            public boolean apply(PredicateContext ctx) {\n                if (ctx.configuration().jsonProvider().getMapValue(ctx.item(), \"name\").equals(\"rootGrandChild_A\")) {\n                    return true;\n                }\n                return false;\n            }\n        };\n\n        Filter rootChildFilter = filter(where(\"name\").regex(Pattern.compile(\"rootChild_[A|B]\")));\n        Filter rootGrandChildFilter = filter(where(\"name\").regex(Pattern.compile(\"rootGrandChild_[A|B]\")));\n\n        List read = JsonPath.read(root, \"children[?].children[?, ?]\", rootChildFilter, rootGrandChildFilter, customFilter);\n\n    }\n\n\n    @Test\n    public void arrays_of_objects_can_be_filtered() throws Exception {\n        Map<String, Object> doc = new HashMap<String, Object>();\n        doc.put(\"items\", asList(1, 2, 3));\n\n        Predicate customFilter = new Predicate() {\n            @Override\n            public boolean apply(PredicateContext ctx) {\n                return 1 == (Integer) ctx.item();\n            }\n        };\n\n        List<Integer> res = JsonPath.read(doc, \"$.items[?]\", customFilter);\n\n        assertEquals(1, res.get(0).intValue());\n    }\n\n    @Test\n    public void filters_can_contain_json_path_expressions() throws Exception {\n        Object doc = Configuration.defaultConfiguration().jsonProvider().parse(DOCUMENT);\n\n        assertFalse(filter(where(\"$.store.bicycle.color\").ne(\"red\")).apply(createPredicateContext(doc)));\n    }\n\n    @Test\n    public void not_empty_filter_evaluates() {\n\n        String json = \"{\\n\" +\n                \"    \\\"fields\\\": [\\n\" +\n                \"        {\\n\" +\n                \"            \\\"errors\\\": [], \\n\" +\n                \"            \\\"name\\\": \\\"\\\", \\n\" +\n                \"            \\\"empty\\\": true \\n\" +\n                \"        }, \\n\" +\n                \"        {\\n\" +\n                \"            \\\"errors\\\": [], \\n\" +\n                \"            \\\"name\\\": \\\"foo\\\"\\n\" +\n                \"        }, \\n\" +\n                \"        {\\n\" +\n                \"            \\\"errors\\\": [\\n\" +\n                \"                \\\"first\\\", \\n\" +\n                \"                \\\"second\\\"\\n\" +\n                \"            ], \\n\" +\n                \"            \\\"name\\\": \\\"invalid\\\"\\n\" +\n                \"        }\\n\" +\n                \"    ]\\n\" +\n                \"}\\n\";\n\n\n        Object doc = Configuration.defaultConfiguration().jsonProvider().parse(json);\n\n        List<Map<String, Object>> result = JsonPath.read(doc, \"$.fields[?]\", filter(where(\"errors\").empty(false)));\n        assertEquals(1, result.size());\n\n        List<Map<String, Object>> result2 = JsonPath.read(doc, \"$.fields[?]\", filter(where(\"name\").empty(false)));\n        assertEquals(2, result2.size());\n    }\n\n    @Test\n    public void contains_filter_evaluates_on_array() {\n\n\n        String json = \"{\\n\" +\n                \"\\\"store\\\": {\\n\" +\n                \"    \\\"book\\\": [\\n\" +\n                \"        {\\n\" +\n                \"            \\\"category\\\": \\\"reference\\\",\\n\" +\n                \"            \\\"authors\\\" : [\\n\" +\n                \"                 {\\n\" +\n                \"                     \\\"firstName\\\" : \\\"Nigel\\\",\\n\" +\n                \"                     \\\"lastName\\\" :  \\\"Rees\\\"\\n\" +\n                \"                  }\\n\" +\n                \"            ],\\n\" +\n                \"            \\\"title\\\": \\\"Sayings of the Century\\\",\\n\" +\n                \"            \\\"price\\\": 8.95\\n\" +\n                \"        },\\n\" +\n                \"        {\\n\" +\n                \"            \\\"category\\\": \\\"fiction\\\",\\n\" +\n                \"            \\\"authors\\\": [\\n\" +\n                \"                 {\\n\" +\n                \"                     \\\"firstName\\\" : \\\"Evelyn\\\",\\n\" +\n                \"                     \\\"lastName\\\" :  \\\"Waugh\\\"\\n\" +\n                \"                  },\\n\" +\n                \"                 {\\n\" +\n                \"                     \\\"firstName\\\" : \\\"Another\\\",\\n\" +\n                \"                     \\\"lastName\\\" :  \\\"Author\\\"\\n\" +\n                \"                  }\\n\" +\n                \"            ],\\n\" +\n                \"            \\\"title\\\": \\\"Sword of Honour\\\",\\n\" +\n                \"            \\\"price\\\": 12.99\\n\" +\n                \"        }\\n\" +\n                \"    ]\\n\" +\n                \"  }\\n\" +\n                \"}\";\n\n\n        Filter filter = filter(where(\"authors[*].lastName\").contains(\"Waugh\"));\n\n        List<String> result = JsonPath.parse(json).read(\"$.store.book[?].title\", filter);\n\n        Assertions.assertThat(result).containsExactly(\"Sword of Honour\");\n    }\n\n\n    @Test\n    public void contains_filter_evaluates_on_string() {\n\n\n        String json = \"{\\n\" +\n                \"\\\"store\\\": {\\n\" +\n                \"    \\\"book\\\": [\\n\" +\n                \"        {\\n\" +\n                \"            \\\"category\\\": \\\"reference\\\",\\n\" +\n                \"            \\\"title\\\": \\\"Sayings of the Century\\\",\\n\" +\n                \"            \\\"price\\\": 8.95\\n\" +\n                \"        },\\n\" +\n                \"        {\\n\" +\n                \"            \\\"category\\\": \\\"fiction\\\",\\n\" +\n                \"            \\\"title\\\": \\\"Sword of Honour\\\",\\n\" +\n                \"            \\\"price\\\": 12.99\\n\" +\n                \"        }\\n\" +\n                \"    ]\\n\" +\n                \"  }\\n\" +\n                \"}\";\n\n\n        Filter filter = filter(where(\"category\").contains(\"fic\"));\n\n        List<String> result = JsonPath.parse(json).read(\"$.store.book[?].title\", filter);\n\n        Assertions.assertThat(result).containsExactly(\"Sword of Honour\");\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/IssuesTest.java",
    "content": "package com.jayway.jsonpath.old;\n\nimport com.fasterxml.jackson.databind.node.ObjectNode;\nimport com.google.gson.JsonObject;\nimport com.jayway.jsonpath.*;\nimport com.jayway.jsonpath.internal.Utils;\nimport com.jayway.jsonpath.spi.cache.LRUCache;\nimport com.jayway.jsonpath.spi.json.GsonJsonProvider;\nimport com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider;\nimport com.jayway.jsonpath.spi.json.JsonProvider;\nimport com.jayway.jsonpath.spi.mapper.GsonMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.MappingException;\nimport net.minidev.json.JSONAware;\nimport net.minidev.json.parser.JSONParser;\nimport org.assertj.core.api.Assertions;\nimport org.hamcrest.Matchers;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.InputStream;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.jayway.jsonpath.Criteria.PredicateContext;\nimport static com.jayway.jsonpath.Criteria.where;\nimport static com.jayway.jsonpath.Filter.filter;\nimport static com.jayway.jsonpath.JsonPath.read;\nimport static com.jayway.jsonpath.JsonPath.using;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.is;\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class IssuesTest extends BaseTest {\n\n    private static final JsonProvider jp = Configuration.defaultConfiguration().jsonProvider();\n\n    @Test\n    public void issue_143() {\n        String json = \"{ \\\"foo\\\": { \\\"bar\\\" : \\\"val\\\" }, \\\"moo\\\": { \\\"cow\\\" : \\\"val\\\" } }\";\n\n        Configuration configuration = Configuration.builder().options(Option.AS_PATH_LIST).build();\n\n        List<String> pathList = JsonPath.using(configuration).parse(json).read(JsonPath.compile(\"$.*.bar\"));\n\n        assertThat(pathList).containsExactly(\"$['foo']['bar']\");\n    }\n\n\n    @Test\n    public void issue_114_a() {\n        String json = \"{ \\\"p\\\":{\\n\" +\n                \"\\\"s\\\": { \\\"u\\\": \\\"su\\\" }, \\n\" +\n                \"\\\"t\\\": { \\\"u\\\": \\\"tu\\\" }\\n\" +\n                \"}}\";\n\n        List<String> result = read(json, \"$.p.['s', 't'].u\");\n        assertThat(result).containsExactly(\"su\", \"tu\");\n    }\n\n    @Test\n    public void issue_114_b() {\n        String json = \"{ \\\"p\\\": [\\\"valp\\\", \\\"valq\\\", \\\"valr\\\"] }\";\n\n        List<String> result = read(json, \"$.p[?(@ == 'valp')]\");\n        assertThat(result).containsExactly(\"valp\");\n    }\n\n    @Test\n    public void issue_114_c() {\n        String json = \"{ \\\"p\\\": [\\\"valp\\\", \\\"valq\\\", \\\"valr\\\"] }\";\n\n        List<String> result = read(json, \"$.p[?(@[0] == 'valp')]\");\n        assertThat(result).isEmpty();\n    }\n\n    @Test\n    public void issue_114_d() {\n        assertThrows(InvalidPathException.class, () -> read(JSON_BOOK_DOCUMENT, \"$..book[(@.length-1)] \"));\n    }\n\n\n    @Test\n    public void issue_151() {\n        String json = \"{\\n\" +\n                \"\\\"datas\\\": {\\n\" +\n                \"    \\\"selling\\\": {\\n\" +\n                \"        \\\"3\\\": [\\n\" +\n                \"            26452067,\\n\" +\n                \"            31625950\\n\" +\n                \"        ],\\n\" +\n                \"        \\\"206\\\": [\\n\" +\n                \"            32381852,\\n\" +\n                \"            32489262\\n\" +\n                \"        ],\\n\" +\n                \"        \\\"208\\\": [\\n\" +\n                \"            458\\n\" +\n                \"        ],\\n\" +\n                \"        \\\"217\\\": [\\n\" +\n                \"            27364892\\n\" +\n                \"        ],\\n\" +\n                \"        \\\"226\\\": [\\n\" +\n                \"            30474109\\n\" +\n                \"        ]\\n\" +\n                \"    }\\n\" +\n                \"},\\n\" +\n                \"\\\"status\\\": 0\\n\" +\n                \"}\";\n\n        List<Integer> result = read(json, \"$.datas.selling['3','206'].*\");\n\n        assertThat(result).containsExactly(26452067, 31625950, 32381852, 32489262);\n    }\n\n    @Test\n    public void full_ones_can_be_filtered() {\n        String json = \"[\\n\" +\n                \" {\\\"kind\\\" : \\\"full\\\"},\\n\" +\n                \" {\\\"kind\\\" : \\\"empty\\\"}\\n\" +\n                \"]\";\n\n        List<Map<String, String>> fullOnes = read(json, \"$[?(@.kind == 'full')]\");\n\n        assertEquals(1, fullOnes.size());\n        assertEquals(\"full\", fullOnes.get(0).get(\"kind\"));\n    }\n\n    @Test\n    public void issue_36() {\n        String json = \"{\\n\" +\n                \"\\n\" +\n                \" \\\"arrayOfObjectsAndArrays\\\" : [ { \\\"k\\\" : [\\\"json\\\"] }, { \\\"k\\\":[\\\"path\\\"] }, { \\\"k\\\" : [\\\"is\\\"] }, { \\\"k\\\" : [\\\"cool\\\"] } ],\\n\" +\n                \"\\n\" +\n                \"  \\\"arrayOfObjects\\\" : [{\\\"k\\\" : \\\"json\\\"}, {\\\"k\\\":\\\"path\\\"}, {\\\"k\\\" : \\\"is\\\"}, {\\\"k\\\" : \\\"cool\\\"}]\\n\" +\n                \"\\n\" +\n                \" }\";\n\n        Object o1 = read(json, \"$.arrayOfObjectsAndArrays..k \");\n        Object o2 = read(json, \"$.arrayOfObjects..k \");\n\n        assertEquals(\"[[\\\"json\\\"],[\\\"path\\\"],[\\\"is\\\"],[\\\"cool\\\"]]\", jp.toJson(o1));\n        assertEquals(\"[\\\"json\\\",\\\"path\\\",\\\"is\\\",\\\"cool\\\"]\", jp.toJson(o2));\n    }\n\n    @Test\n    public void issue_11() throws Exception {\n        String json = \"{ \\\"foo\\\" : [] }\";\n        List<String> result = read(json, \"$.foo[?(@.rel == 'item')][0].uri\");\n        assertTrue(result.isEmpty());\n    }\n\n    @Test\n    public void issue_11b() throws Exception {\n        String json = \"{ \\\"foo\\\" : [] }\";\n        assertThrows(PathNotFoundException.class, () -> read(json, \"$.foo[0].uri\"));\n    }\n\n    @Test\n    public void issue_15() throws Exception {\n        String json = \"{ \\\"store\\\": {\\n\" +\n                \"    \\\"book\\\": [ \\n\" +\n                \"      { \\\"category\\\": \\\"reference\\\",\\n\" +\n                \"        \\\"author\\\": \\\"Nigel Rees\\\",\\n\" +\n                \"        \\\"title\\\": \\\"Sayings of the Century\\\",\\n\" +\n                \"        \\\"price\\\": 8.95\\n\" +\n                \"      },\\n\" +\n                \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                \"        \\\"author\\\": \\\"Herman Melville\\\",\\n\" +\n                \"        \\\"title\\\": \\\"Moby Dick\\\",\\n\" +\n                \"        \\\"isbn\\\": \\\"0-553-21311-3\\\",\\n\" +\n                \"        \\\"price\\\": 8.99,\\n\" +\n                \"        \\\"retailer\\\": null, \\n\" +\n                \"        \\\"children\\\": true,\\n\" +\n                \"        \\\"number\\\": -2.99\\n\" +\n                \"      },\\n\" +\n                \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                \"        \\\"author\\\": \\\"J. R. R. Tolkien\\\",\\n\" +\n                \"        \\\"title\\\": \\\"The Lord of the Rings\\\",\\n\" +\n                \"        \\\"isbn\\\": \\\"0-395-19395-8\\\",\\n\" +\n                \"        \\\"price\\\": 22.99,\\n\" +\n                \"        \\\"number\\\":0,\\n\" +\n                \"        \\\"children\\\": false\\n\" +\n                \"      }\\n\" +\n                \"    ]\\n\" +\n                \"  }\\n\" +\n                \"}\";\n\n        List<String> titles = read(json, \"$.store.book[?(@.children==true)].title\");\n\n        assertThat(titles, Matchers.contains(\"Moby Dick\"));\n        assertEquals(1, titles.size());\n    }\n\n\n    @Test\n    public void issue_24() {\n\n        InputStream is = null;\n        try {\n            is = this.getClass().getResourceAsStream(\"/issue_24.json\");\n\n\n            //Object o = JsonPath.read(is, \"$.project[?(@.template.@key == 'foo')].field[*].@key\");\n            Object o = read(is, \"$.project.field[*].@key\");\n            //Object o = JsonPath.read(is, \"$.project.template[?(@.@key == 'foo')].field[*].@key\");\n\n\n            is.close();\n        } catch (Exception e) {\n            //e.printStackTrace();\n            Utils.closeQuietly(is);\n        }\n\n    }\n\n    @Test\n    public void issue_28_string() {\n        String json = \"{\\\"contents\\\": [\\\"one\\\",\\\"two\\\",\\\"three\\\"]}\";\n\n        List<String> result = read(json, \"$.contents[?(@  == 'two')]\");\n\n        assertThat(result, Matchers.contains(\"two\"));\n        assertEquals(1, result.size());\n    }\n\n    @Test\n    public void issue_37() {\n        String json = \"[\\n\" +\n                \"    {\\n\" +\n                \"        \\\"id\\\": \\\"9\\\",\\n\" +\n                \"        \\\"sku\\\": \\\"SKU-001\\\",\\n\" +\n                \"        \\\"compatible\\\": false\\n\" +\n                \"    },\\n\" +\n                \"    {\\n\" +\n                \"        \\\"id\\\": \\\"13\\\",\\n\" +\n                \"        \\\"sku\\\": \\\"SKU-005\\\",\\n\" +\n                \"        \\\"compatible\\\": true\\n\" +\n                \"    },\\n\" +\n                \"    {\\n\" +\n                \"        \\\"id\\\": \\\"11\\\",\\n\" +\n                \"        \\\"sku\\\": \\\"SKU-003\\\",\\n\" +\n                \"        \\\"compatible\\\": true\\n\" +\n                \"    }\\n\" +\n                \"]\";\n\n        List<String> result = read(json, \"$[?(@.compatible == true)].sku\");\n\n        assertThat(result).containsExactly(\"SKU-005\", \"SKU-003\");\n    }\n\n\n    @Test\n    public void issue_38() {\n        String json = \"{\\n\" +\n                \"   \\\"datapoints\\\":[\\n\" +\n                \"      [\\n\" +\n                \"         10.1,\\n\" +\n                \"         13.0\\n\" +\n                \"      ],\\n\" +\n                \"      [\\n\" +\n                \"         21.0,\\n\" +\n                \"         22.0\\n\" +\n                \"      ]\\n\" +\n                \"   ]\\n\" +\n                \"}\";\n\n        List<Double> result = read(json, \"$.datapoints.[*].[0]\");\n\n        assertThat(result.get(0), is(new Double(10.1)));\n        assertThat(result.get(1), is(new Double(21.0)));\n    }\n\n    @Test\n    public void issue_39() {\n        String json = \"{\\n\" +\n                \"    \\\"obj1\\\": {\\n\" +\n                \"        \\\"arr\\\": [\\\"1\\\", \\\"2\\\"]\\n\" +\n                \"    },\\n\" +\n                \"    \\\"obj2\\\": {\\n\" +\n                \"       \\\"arr\\\": [\\\"3\\\", \\\"4\\\"]\\n\" +\n                \"    }\\n\" +\n                \"}\\n\";\n\n        List<String> result = read(json, \"$..arr\");\n        assertThat(result.size(), is(2));\n    }\n\n    @Test\n    public void issue_28_int() {\n        String json = \"{\\\"contents\\\": [1,2,3]}\";\n\n        List<Integer> result = read(json, \"$.contents[?(@ == 2)]\");\n\n        assertThat(result, Matchers.contains(2));\n        assertEquals(1, result.size());\n    }\n\n    @Test\n    public void issue_28_boolean() {\n        String json = \"{\\\"contents\\\": [true, true, false]}\";\n\n        List<Boolean> result = read(json, \"$.contents[?(@  == true)]\");\n\n        assertThat(result, Matchers.contains(true, true));\n        assertEquals(2, result.size());\n    }\n\n\n    @Test\n    public void issue_22() throws Exception {\n\n        Configuration configuration = Configuration.defaultConfiguration();\n\n        String json = \"{\\\"a\\\":{\\\"b\\\":1,\\\"c\\\":2}}\";\n        assertThrows(PathNotFoundException.class, () -> JsonPath.parse(json, configuration).read(\"a.d\"));\n    }\n\n    @Test\n    public void issue_22c() throws Exception {\n        //Configuration configuration = Configuration.builder().build();\n        Configuration configuration = Configuration.builder().options(Option.SUPPRESS_EXCEPTIONS).build();\n\n        String json = \"{\\\"a\\\":{\\\"b\\\":1,\\\"c\\\":2}}\";\n        assertNull(JsonPath.parse(json, configuration).read(\"a.d\"));\n    }\n\n\n    @Test\n    public void issue_22b() throws Exception {\n        String json = \"{\\\"a\\\":[{\\\"b\\\":1,\\\"c\\\":2},{\\\"b\\\":5,\\\"c\\\":2}]}\";\n        List<Object> res = JsonPath.using(Configuration.defaultConfiguration().setOptions(Option.DEFAULT_PATH_LEAF_TO_NULL)).parse(json).read(\"a[?(@.b==5)].d\");\n        assertThat(res).hasSize(1).containsNull();\n    }\n\n    @Test\n    public void issue_26() throws Exception {\n        String json = \"[{\\\"a\\\":[{\\\"b\\\":1,\\\"c\\\":2}]}]\";\n        assertThrows(PathNotFoundException.class, () -> read(json, \"$.a\"));\n    }\n\n    @Test\n    public void issue_29_a() throws Exception {\n        String json = \"{\\\"list\\\": [ { \\\"a\\\":\\\"atext\\\", \\\"b.b-a\\\":\\\"batext2\\\", \\\"b\\\":{ \\\"b-a\\\":\\\"batext\\\", \\\"b-b\\\":\\\"bbtext\\\" } }, { \\\"a\\\":\\\"atext2\\\", \\\"b\\\":{ \\\"b-a\\\":\\\"batext2\\\", \\\"b-b\\\":\\\"bbtext2\\\" } } ] }\";\n\n        List<Map<String, Object>> result = read(json, \"$.list[?(@['b.b-a']=='batext2')]\");\n        assertEquals(1, result.size());\n        Object a = result.get(0).get(\"a\");\n        assertEquals(\"atext\", a);\n\n        result = read(json, \"$.list[?(@.b.b-a=='batext2')]\");\n        assertEquals(1, result.size());\n        assertEquals(\"atext2\", result.get(0).get(\"a\"));\n\n\n    }\n\n    @Test\n    public void issue_29_b() throws Exception {\n        String json = \"{\\\"list\\\": [ { \\\"a\\\":\\\"atext\\\", \\\"b\\\":{ \\\"b-a\\\":\\\"batext\\\", \\\"b-b\\\":\\\"bbtext\\\" } }, { \\\"a\\\":\\\"atext2\\\", \\\"b\\\":{ \\\"b-a\\\":\\\"batext2\\\", \\\"b-b\\\":\\\"bbtext2\\\" } } ] }\";\n        List<String> result = read(json, \"$.list[?]\", filter(where(\"b.b-a\").eq(\"batext2\")));\n\n        assertTrue(result.size() == 1);\n    }\n\n    @Test\n    public void issue_30() throws Exception {\n        String json = \"{\\\"foo\\\" : {\\\"@id\\\" : \\\"123\\\", \\\"$\\\" : \\\"hello\\\"}}\";\n\n        assertEquals(\"123\", read(json, \"foo.@id\"));\n        assertEquals(\"hello\", read(json, \"foo.$\"));\n    }\n\n    @Test\n    public void issue_32() {\n        String json = \"{\\\"text\\\" : \\\"skill: \\\\\\\"Heuristic Evaluation\\\\\\\"\\\", \\\"country\\\" : \\\"\\\"}\";\n        assertEquals(\"skill: \\\"Heuristic Evaluation\\\"\", read(json, \"$.text\"));\n    }\n\n    @Test\n    public void issue_33() {\n        String json = \"{ \\\"store\\\": {\\n\" +\n                \"    \\\"book\\\": [ \\n\" +\n                \"      { \\\"category\\\": \\\"reference\\\",\\n\" +\n                \"        \\\"author\\\": {\\n\" +\n                \"          \\\"name\\\": \\\"Author Name\\\",\\n\" +\n                \"          \\\"age\\\": 36\\n\" +\n                \"        },\\n\" +\n                \"        \\\"title\\\": \\\"Sayings of the Century\\\",\\n\" +\n                \"        \\\"price\\\": 8.95\\n\" +\n                \"      },\\n\" +\n                \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                \"        \\\"author\\\": \\\"Evelyn Waugh\\\",\\n\" +\n                \"        \\\"title\\\": \\\"Sword of Honour\\\",\\n\" +\n                \"        \\\"price\\\": 12.99,\\n\" +\n                \"        \\\"isbn\\\": \\\"0-553-21311-3\\\"\\n\" +\n                \"      }\\n\" +\n                \"    ],\\n\" +\n                \"    \\\"bicycle\\\": {\\n\" +\n                \"      \\\"color\\\": \\\"red\\\",\\n\" +\n                \"      \\\"price\\\": 19.95\\n\" +\n                \"    }\\n\" +\n                \"  }\\n\" +\n                \"}\";\n\n        List<Map<String, Object>> result = read(json, \"$.store.book[?(@.author.age == 36)]\");\n\n        assertThat(result).hasSize(1);\n        assertThat(result.get(0)).containsEntry(\"title\", \"Sayings of the Century\");\n    }\n\n    @Test\n    public void array_root() {\n        String json = \"[\\n\" +\n                \"    {\\n\" +\n                \"        \\\"a\\\": 1,\\n\" +\n                \"        \\\"b\\\": 2,\\n\" +\n                \"        \\\"c\\\": 3\\n\" +\n                \"    }\\n\" +\n                \"]\";\n\n\n        assertEquals(Integer.valueOf(1), read(json, \"$[0].a\"));\n    }\n\n    @Test\n    public void a_test() {\n\n        String json = \"{\\n\" +\n                \"  \\\"success\\\": true,\\n\" +\n                \"  \\\"data\\\": {\\n\" +\n                \"    \\\"user\\\": 3,\\n\" +\n                \"    \\\"own\\\": null,\\n\" +\n                \"    \\\"passes\\\": null,\\n\" +\n                \"    \\\"completed\\\": null\\n\" +\n                \"  },\\n\" +\n                \"  \\\"version\\\": 1371160528774\\n\" +\n                \"}\";\n\n        assertThrows(PathNotFoundException.class, () -> read(json, \"$.data.passes[0].id\"));\n    }\n\n\n    @Test\n    public void issue_42() {\n\n        String json = \"{\" +\n                \"        \\\"list\\\": [{\" +\n                \"            \\\"name\\\": \\\"My (String)\\\" \" +\n                \"        }] \" +\n                \"    }\";\n\n        List<Map<String, String>> result = read(json, \"$.list[?(@.name == 'My (String)')]\");\n\n        assertThat(result).containsExactly(Collections.singletonMap(\"name\", \"My (String)\"));\n    }\n\n    @Test\n    public void issue_43() {\n\n        String json = \"{\\\"test\\\":null}\";\n\n        assertThat((String) read(json, \"test\")).isNull();\n\n        assertThat((String) JsonPath.using(Configuration.defaultConfiguration().setOptions(Option.SUPPRESS_EXCEPTIONS)).parse(json).read(\"nonExistingProperty\")).isNull();\n\n        try {\n            read(json, \"nonExistingProperty\");\n\n            failBecauseExceptionWasNotThrown(PathNotFoundException.class);\n        } catch (PathNotFoundException e) {\n\n        }\n\n\n        try {\n            read(json, \"nonExisting.property\");\n\n            failBecauseExceptionWasNotThrown(PathNotFoundException.class);\n        } catch (PathNotFoundException e) {\n        }\n\n    }\n\n\n    @Test\n    public void issue_45() {\n        String json = \"{\\\"rootkey\\\":{\\\"sub.key\\\":\\\"value\\\"}}\";\n\n        assertThat((String) read(json, \"rootkey['sub.key']\")).isEqualTo(\"value\");\n    }\n\n    @Test\n    public void issue_46() {\n\n\n        String json = \"{\\\"a\\\": {}}\";\n\n        Configuration configuration = Configuration.defaultConfiguration().setOptions(Option.SUPPRESS_EXCEPTIONS);\n        assertThat((String) JsonPath.using(configuration).parse(json).read(\"a.x\")).isNull();\n\n        try {\n            read(json, \"a.x\");\n\n            failBecauseExceptionWasNotThrown(PathNotFoundException.class);\n        } catch (PathNotFoundException e) {\n            assertThat(e).hasMessage(\"No results for path: $['a']['x']\");\n        }\n    }\n\n    @Test\n    public void issue_x() {\n\n        String json = \"{\\n\" +\n                \" \\\"a\\\" : [\\n\" +\n                \"   {},\\n\" +\n                \"   { \\\"b\\\" : [ { \\\"c\\\" : \\\"foo\\\"} ] }\\n\" +\n                \" ]\\n\" +\n                \"}\\n\";\n\n        List<String> result = read(json, \"$.a.*.b.*.c\");\n\n        assertThat(result).containsExactly(\"foo\");\n\n    }\n\n    @Test\n    public void issue_60() {\n\n\n        String json = \"[\\n\" +\n                \"{\\n\" +\n                \"  \\\"mpTransactionId\\\": \\\"542986eae4b001fd500fdc5b-coreDisc_50-title\\\",\\n\" +\n                \"  \\\"resultType\\\": \\\"FAIL\\\",\\n\" +\n                \"  \\\"narratives\\\": [\\n\" +\n                \"    {\\n\" +\n                \"      \\\"ruleProcessingDate\\\": \\\"Nov 2, 2014 7:30:20 AM\\\",\\n\" +\n                \"      \\\"area\\\": \\\"Discovery\\\",\\n\" +\n                \"      \\\"phase\\\": \\\"Validation\\\",\\n\" +\n                \"      \\\"message\\\": \\\"Chain does not have a discovery event. Possible it was cut by the date that was picked\\\",\\n\" +\n                \"      \\\"ruleName\\\": \\\"Validate chain\\\\u0027s discovery event existence\\\",\\n\" +\n                \"      \\\"lastRule\\\": true\\n\" +\n                \"    }\\n\" +\n                \"  ]\\n\" +\n                \"},\\n\" +\n                \"{\\n\" +\n                \"  \\\"mpTransactionId\\\": \\\"54298649e4b001fd500fda3e-fixCoreDiscovery_3-title\\\",\\n\" +\n                \"  \\\"resultType\\\": \\\"FAIL\\\",\\n\" +\n                \"  \\\"narratives\\\": [\\n\" +\n                \"    {\\n\" +\n                \"      \\\"ruleProcessingDate\\\": \\\"Nov 2, 2014 7:30:20 AM\\\",\\n\" +\n                \"      \\\"area\\\": \\\"Discovery\\\",\\n\" +\n                \"      \\\"phase\\\": \\\"Validation\\\",\\n\" +\n                \"      \\\"message\\\": \\\"There is one and only discovery event ContentDiscoveredEvent(230) found.\\\",\\n\" +\n                \"      \\\"ruleName\\\": \\\"Marks existence of discovery event (230)\\\",\\n\" +\n                \"      \\\"lastRule\\\": false\\n\" +\n                \"    },\\n\" +\n                \"    {\\n\" +\n                \"      \\\"ruleProcessingDate\\\": \\\"Nov 2, 2014 7:30:20 AM\\\",\\n\" +\n                \"      \\\"area\\\": \\\"Discovery/Processing\\\",\\n\" +\n                \"      \\\"phase\\\": \\\"Validation\\\",\\n\" +\n                \"      \\\"message\\\": \\\"Chain does not have SLA start event (204) in Discovery or Processing. \\\",\\n\" +\n                \"      \\\"ruleName\\\": \\\"Check if SLA start event is not present (204). \\\",\\n\" +\n                \"      \\\"lastRule\\\": false\\n\" +\n                \"    },\\n\" +\n                \"    {\\n\" +\n                \"      \\\"ruleProcessingDate\\\": \\\"Nov 2, 2014 7:30:20 AM\\\",\\n\" +\n                \"      \\\"area\\\": \\\"Processing\\\",\\n\" +\n                \"      \\\"phase\\\": \\\"Transcode\\\",\\n\" +\n                \"      \\\"message\\\": \\\"No start transcoding events found\\\",\\n\" +\n                \"      \\\"ruleName\\\": \\\"Start transcoding events missing (240)\\\",\\n\" +\n                \"      \\\"lastRule\\\": true\\n\" +\n                \"    }\\n\" +\n                \"  ]\\n\" +\n                \"}]\";\n\n        List<String> problems = read(json, \"$..narratives[?(@.lastRule==true)].message\");\n\n        assertThat(problems).containsExactly(\"Chain does not have a discovery event. Possible it was cut by the date that was picked\", \"No start transcoding events found\");\n    }\n\n    //http://stackoverflow.com/questions/28596324/jsonpath-filtering-api\n    @Test\n    public void stack_overflow_question_1() {\n\n\n        String json = \"{\\n\" +\n                \"\\\"store\\\": {\\n\" +\n                \"    \\\"book\\\": [\\n\" +\n                \"        {\\n\" +\n                \"            \\\"category\\\": \\\"reference\\\",\\n\" +\n                \"            \\\"authors\\\" : [\\n\" +\n                \"                 {\\n\" +\n                \"                     \\\"firstName\\\" : \\\"Nigel\\\",\\n\" +\n                \"                     \\\"lastName\\\" :  \\\"Rees\\\"\\n\" +\n                \"                  }\\n\" +\n                \"            ],\\n\" +\n                \"            \\\"title\\\": \\\"Sayings of the Century\\\",\\n\" +\n                \"            \\\"price\\\": 8.95\\n\" +\n                \"        },\\n\" +\n                \"        {\\n\" +\n                \"            \\\"category\\\": \\\"fiction\\\",\\n\" +\n                \"            \\\"authors\\\": [\\n\" +\n                \"                 {\\n\" +\n                \"                     \\\"firstName\\\" : \\\"Evelyn\\\",\\n\" +\n                \"                     \\\"lastName\\\" :  \\\"Waugh\\\"\\n\" +\n                \"                  },\\n\" +\n                \"                 {\\n\" +\n                \"                     \\\"firstName\\\" : \\\"Another\\\",\\n\" +\n                \"                     \\\"lastName\\\" :  \\\"Author\\\"\\n\" +\n                \"                  }\\n\" +\n                \"            ],\\n\" +\n                \"            \\\"title\\\": \\\"Sword of Honour\\\",\\n\" +\n                \"            \\\"price\\\": 12.99\\n\" +\n                \"        }\\n\" +\n                \"    ]\\n\" +\n                \"  }\\n\" +\n                \"}\";\n\n\n        Filter filter = filter(where(\"authors[*].lastName\").contains(\"Waugh\"));\n\n        Object read = JsonPath.parse(json).read(\"$.store.book[?]\", filter);\n    }\n\n    @Test\n    public void issue_71() {\n        String json = \"{\\n\"\n                + \"    \\\"logs\\\": [\\n\"\n                + \"        {\\n\"\n                + \"            \\\"message\\\": \\\"it's here\\\",\\n\"\n                + \"            \\\"id\\\": 2\\n\"\n                + \"        }\\n\"\n                + \"    ]\\n\"\n                + \"}\";\n\n        List<String> result = read(json, \"$.logs[?(@.message == 'it\\\\'s here')].message\");\n\n        assertThat(result).containsExactly(\"it's here\");\n    }\n\n    @Test\n    public void issue_76() throws Exception {\n\n        String json = \"{\\n\" +\n                \"    \\\"cpus\\\": -8.88178419700125e-16,\\n\" +\n                \"    \\\"disk\\\": 0,\\n\" +\n                \"    \\\"mem\\\": 0\\n\" +\n                \"}\";\n\n        JSONParser parser = new JSONParser(JSONParser.MODE_PERMISSIVE);\n        JSONAware jsonModel = (JSONAware) parser.parse(json);\n\n        jsonModel.toJSONString();\n    }\n\n    @Test\n    public void issue_79() throws Exception {\n        String json = \"{ \\n\" +\n                \"  \\\"c\\\": {\\n\" +\n                \"    \\\"d1\\\": {\\n\" +\n                \"      \\\"url\\\": [ \\\"url1\\\", \\\"url2\\\" ]\\n\" +\n                \"    },\\n\" +\n                \"    \\\"d2\\\": {\\n\" +\n                \"      \\\"url\\\": [ \\\"url3\\\", \\\"url4\\\",\\\"url5\\\" ]\\n\" +\n                \"    }\\n\" +\n                \"  }\\n\" +\n                \"}\";\n\n        List<String> res = read(json, \"$.c.*.url[2]\");\n\n        assertThat(res).containsExactly(\"url5\");\n    }\n\n    @Test\n    public void issue_94_1() throws Exception {\n        LRUCache cache = new LRUCache(200);\n        JsonPath dummy = JsonPath.compile(\"$\");\n        for (int i = 0; i < 1000; ++i) {\n            String key = String.valueOf(i);\n            cache.get(key);\n            cache.put(key, dummy);\n        }\n        assertThat(cache.size()).isEqualTo(200);\n    }\n\n    @Test\n    public void issue_94_2() throws Exception {\n        LRUCache cache = new LRUCache(5);\n\n        JsonPath dummy = JsonPath.compile(\"$\");\n\n        cache.put(\"1\", dummy);\n        cache.put(\"2\", dummy);\n        cache.put(\"3\", dummy);\n        cache.put(\"4\", dummy);\n        cache.put(\"5\", dummy);\n        cache.put(\"6\", dummy);\n\n        cache.get(\"1\");\n        cache.get(\"2\");\n        cache.get(\"3\");\n        cache.get(\"4\");\n        cache.get(\"5\");\n        cache.get(\"6\");\n\n        cache.get(\"2\");\n        cache.get(\"3\");\n        cache.get(\"4\");\n        cache.get(\"5\");\n        cache.get(\"6\");\n\n        cache.get(\"3\");\n        cache.get(\"4\");\n        cache.get(\"5\");\n        cache.get(\"6\");\n\n        cache.get(\"4\");\n        cache.get(\"5\");\n        cache.get(\"6\");\n\n        cache.get(\"5\");\n        cache.get(\"6\");\n\n        cache.get(\"6\");\n\n        assertThat(cache.getSilent(\"6\")).isNotNull();\n        assertThat(cache.getSilent(\"5\")).isNotNull();\n        assertThat(cache.getSilent(\"4\")).isNotNull();\n        assertThat(cache.getSilent(\"3\")).isNotNull();\n        assertThat(cache.getSilent(\"2\")).isNotNull();\n        assertThat(cache.getSilent(\"1\")).isNull();\n    }\n\n    @Test\n    public void issue_97() throws Exception {\n        String json = \"{ \\\"books\\\": [ \" +\n                \"{ \\\"category\\\": \\\"fiction\\\" }, \" +\n                \"{ \\\"category\\\": \\\"reference\\\" }, \" +\n                \"{ \\\"category\\\": \\\"fiction\\\" }, \" +\n                \"{ \\\"category\\\": \\\"fiction\\\" }, \" +\n                \"{ \\\"category\\\": \\\"reference\\\" }, \" +\n                \"{ \\\"category\\\": \\\"fiction\\\" }, \" +\n                \"{ \\\"category\\\": \\\"reference\\\" }, \" +\n                \"{ \\\"category\\\": \\\"reference\\\" }, \" +\n                \"{ \\\"category\\\": \\\"reference\\\" }, \" +\n                \"{ \\\"category\\\": \\\"reference\\\" }, \" +\n                \"{ \\\"category\\\": \\\"reference\\\" } ]  }\";\n\n        Configuration conf = Configuration.builder()\n                .jsonProvider(new GsonJsonProvider())\n                .mappingProvider(new GsonMappingProvider())\n                .build();\n\n        DocumentContext context = JsonPath.using(conf).parse(json);\n        context.delete(\"$.books[?(@.category == 'reference')]\");\n\n        List<String> categories = context.read(\"$..category\", List.class);\n\n        assertThat(categories).containsOnly(\"fiction\");\n    }\n\n\n    @Test\n    public void issue_99() throws Exception {\n        String json = \"{\\n\" +\n                \"    \\\"array1\\\": [\\n\" +\n                \"        {\\n\" +\n                \"            \\\"array2\\\": []\\n\" +\n                \"        },\\n\" +\n                \"        {\\n\" +\n                \"            \\\"array2\\\": [\\n\" +\n                \"                {\\n\" +\n                \"                    \\\"key\\\": \\\"test_key\\\"\\n\" +\n                \"                }\\n\" +\n                \"            ]\\n\" +\n                \"        }\\n\" +\n                \"    ]\\n\" +\n                \"}\";\n\n        Configuration configuration = Configuration.defaultConfiguration().addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL);\n\n        List<String> keys = JsonPath.using(configuration).parse(json).read(\"$.array1[*].array2[0].key\");\n    }\n\n\n    @Test\n    public void issue_129() throws Exception {\n\n        final Map<String, Integer> match = new HashMap<String, Integer>();\n        match.put(\"a\", 1);\n        match.put(\"b\", 2);\n\n        Map<String, Integer> noMatch = new HashMap<String, Integer>();\n        noMatch.put(\"a\", -1);\n        noMatch.put(\"b\", -2);\n\n        Filter orig = filter(where(\"a\").eq(1).and(\"b\").eq(2));\n\n        String filterAsString = orig.toString();\n\n        Filter parsed = Filter.parse(filterAsString);\n\n        assertThat(orig.apply(createPredicateContext(match))).isTrue();\n        assertThat(parsed.apply(createPredicateContext(match))).isTrue();\n        assertThat(orig.apply(createPredicateContext(noMatch))).isFalse();\n        assertThat(parsed.apply(createPredicateContext(noMatch))).isFalse();\n    }\n\n    private PredicateContext createPredicateContext(final Map<String, Integer> map) {\n        return new PredicateContext() {\n            @Override\n            public Object item() {\n                return map;\n            }\n\n            @Override\n            public <T> T item(Class<T> clazz) throws MappingException {\n                return (T) map;\n            }\n\n            @Override\n            public Object root() {\n                return map;\n            }\n\n            @Override\n            public Configuration configuration() {\n                return Configuration.defaultConfiguration();\n            }\n        };\n    }\n\n    @Test\n    public void issue_131() {\n\n        String json = \"[\\n\" +\n                \"    {\\n\" +\n                \"        \\\"foo\\\": \\\"1\\\"\\n\" +\n                \"    },\\n\" +\n                \"    {\\n\" +\n                \"        \\\"foo\\\": null\\n\" +\n                \"    },\\n\" +\n                \"    {\\n\" +\n                \"        \\\"xxx\\\": null\\n\" +\n                \"    }\\n\" +\n                \"]\";\n\n        List<Map<String, String>> result = read(json, \"$[?(@.foo)]\");\n\n        assertThat(result).extracting(\"foo\").containsExactly(\"1\", null);\n    }\n\n\n    @Test\n    public void issue_131_2() {\n\n        String json = \"[\\n\" +\n                \"    {\\n\" +\n                \"        \\\"foo\\\": { \\\"bar\\\" : \\\"0\\\"}\\n\" +\n                \"    },\\n\" +\n                \"    {\\n\" +\n                \"        \\\"foo\\\": null\\n\" +\n                \"    },\\n\" +\n                \"    {\\n\" +\n                \"        \\\"xxx\\\": null\\n\" +\n                \"    }\\n\" +\n                \"]\";\n\n        List<String> result = read(json, \"$[?(@.foo != null)].foo.bar\");\n\n        assertThat(result).containsExactly(\"0\");\n\n\n        result = read(json, \"$[?(@.foo.bar)].foo.bar\");\n\n        assertThat(result).containsExactly(\"0\");\n    }\n\n\n    @Test\n    public void issue_131_3() {\n        String json = \"[\\n\" +\n                \"    1,\\n\" +\n                \"    2,\\n\" +\n                \"    {\\n\" +\n                \"        \\\"d\\\": {\\n\" +\n                \"            \\\"random\\\": null,\\n\" +\n                \"            \\\"date\\\": 1234\\n\" +\n                \"        },\\n\" +\n                \"        \\\"l\\\": \\\"filler\\\"\\n\" +\n                \"    }\\n\" +\n                \"]\";\n\n        List<Integer> result = read(json, \"$[2]['d'][?(@.random)]['date']\");\n\n        assertThat(result).containsExactly(1234);\n    }\n\n\n    //https://groups.google.com/forum/#!topic/jsonpath/Ojv8XF6LgqM\n    @Test\n    public void using_square_bracket_literal_path() {\n\n        String json = \"{ \\\"valid key[@num = 2]\\\" : \\\"value\\\" }\";\n\n        String result = read(json, \"$['valid key[@num = 2]']\");\n\n        Assertions.assertThat(result).isEqualTo(\"value\");\n    }\n\n    @Test\n    public void issue_90() {\n\n        String json = \"{\\n\" +\n                \"    \\\"store\\\": {\\n\" +\n                \"        \\\"book\\\": [\\n\" +\n                \"            {\\n\" +\n                \"                \\\"price\\\": \\\"120\\\"\\n\" +\n                \"            },\\n\" +\n                \"            {\\n\" +\n                \"                \\\"price\\\": 8.95\\n\" +\n                \"            },\\n\" +\n                \"            {\\n\" +\n                \"                \\\"price\\\": 12.99\\n\" +\n                \"            },\\n\" +\n                \"            {\\n\" +\n                \"                \\\"price\\\": 8.99\\n\" +\n                \"            },\\n\" +\n                \"            {\\n\" +\n                \"                \\\"price\\\": 22.99\\n\" +\n                \"            }\\n\" +\n                \"        ]\\n\" +\n                \"    },\\n\" +\n                \"    \\\"expensive\\\": 10\\n\" +\n                \"}\";\n\n        List<Double> numbers = read(json, \"$.store.book[?(@.price <= 90)].price\");\n\n        assertThat(numbers).containsExactly(8.95D, 12.99D, 8.99D, 22.99D);\n    }\n\n    @Test\n    public void github_89() {\n\n        com.google.gson.JsonObject json = new JsonObject();\n        json.addProperty(\"foo\", \"bar\");\n\n        JsonPath path = JsonPath.compile(\"$.foo\");\n        assertThrows(PathNotFoundException.class, () -> path.read(json));\n\n    }\n\n    @Test\n    public void issue_170() {\n\n        String json = \"{\\n\" +\n                \"  \\\"array\\\": [\\n\" +\n                \"    0,\\n\" +\n                \"    1,\\n\" +\n                \"    2\\n\" +\n                \"  ]\\n\" +\n                \"}\";\n\n\n        DocumentContext context = using(JACKSON_JSON_NODE_CONFIGURATION).parse(json);\n        context = context.set(\"$.array[0]\", null);\n        context = context.set(\"$.array[2]\", null);\n\n        List<Integer> list = context.read(\"$.array\", List.class);\n\n        assertThat(list).containsExactly(null, 1, null);\n    }\n\n    @Test\n    public void issue_170_jackson3() {\n\n        String json = \"{\\n\" +\n                      \"  \\\"array\\\": [\\n\" +\n                      \"    0,\\n\" +\n                      \"    1,\\n\" +\n                      \"    2\\n\" +\n                      \"  ]\\n\" +\n                      \"}\";\n\n\n        DocumentContext context = using(JACKSON3_JSON_NODE_CONFIGURATION).parse(json);\n        context = context.set(\"$.array[0]\", null);\n        context = context.set(\"$.array[2]\", null);\n\n        List<Integer> list = context.read(\"$.array\", List.class);\n\n        assertThat(list).containsExactly(null, 1, null);\n    }\n\n    @Test\n    public void issue_171() {\n\n        String json = \"{\\n\" +\n                \"  \\\"can delete\\\": \\\"this\\\",\\n\" +\n                \"  \\\"can't delete\\\": \\\"this\\\"\\n\" +\n                \"}\";\n\n        DocumentContext context = using(JACKSON_JSON_NODE_CONFIGURATION).parse(json);\n        context.set(\"$.['can delete']\", null);\n        context.set(\"$.['can\\\\'t delete']\", null);\n\n        ObjectNode objectNode = context.read(\"$\");\n\n        assertThat(objectNode.get(\"can delete\").isNull());\n        assertThat(objectNode.get(\"can't delete\").isNull());\n    }\n\n    @Test\n    public void issue_171_jackson3() {\n\n        String json = \"{\\n\" +\n                      \"  \\\"can delete\\\": \\\"this\\\",\\n\" +\n                      \"  \\\"can't delete\\\": \\\"this\\\"\\n\" +\n                      \"}\";\n\n        DocumentContext context = using(JACKSON3_JSON_NODE_CONFIGURATION).parse(json);\n        context.set(\"$.['can delete']\", null);\n        context.set(\"$.['can\\\\'t delete']\", null);\n\n        tools.jackson.databind.node.ObjectNode objectNode = context.read(\"$\");\n\n        assertThat(objectNode.get(\"can delete\").isNull());\n        assertThat(objectNode.get(\"can't delete\").isNull());\n    }\n\n    @Test\n    public void issue_309() {\n\n        String json = \"{\\n\" +\n                \"\\\"jsonArr\\\": [\\n\" +\n                \"   {\\n\" +\n                \"       \\\"name\\\":\\\"nOne\\\"\\n\" +\n                \"   },\\n\" +\n                \"   {\\n\" +\n                \"       \\\"name\\\":\\\"nTwo\\\"\\n\" +\n                \"   }\\n\" +\n                \"   ]\\n\" +\n                \"}\";\n\n        DocumentContext doc = JsonPath.parse(json).set(\"$.jsonArr[1].name\", \"Jayway\");\n\n        assertThat((String) doc.read(\"$.jsonArr[0].name\")).isEqualTo(\"nOne\");\n        assertThat((String) doc.read(\"$.jsonArr[1].name\")).isEqualTo(\"Jayway\");\n    }\n\n    @Test\n    public void issue_378() {\n\n        String json = \"{\\n\" +\n                \"    \\\"nodes\\\": {\\n\" +\n                \"        \\\"unnamed1\\\": {\\n\" +\n                \"            \\\"ntpServers\\\": [\\n\" +\n                \"                \\\"1.2.3.4\\\"\\n\" +\n                \"            ]\\n\" +\n                \"        }\\n\" +\n                \"    }\\n\" +\n                \"}\";\n\n        Configuration configuration = Configuration.builder()\n                .jsonProvider(new JacksonJsonNodeJsonProvider())\n                .mappingProvider(new JacksonMappingProvider())\n                .build();\n\n        DocumentContext ctx = JsonPath.using(configuration).parse(json);\n\n        String path = \"$.nodes[*][?(!([\\\"1.2.3.4\\\"] subsetof @.ntpServers))].ntpServers\";\n        JsonPath jsonPath = JsonPath.compile(path);\n\n        ctx.read(jsonPath);\n    }\n\n    //CS304 (manually written) Issue link: https://github.com/json-path/JsonPath/issues/620\n    @Test\n    public void issue_620_1() {\n        String json = \"{\\n\" +\n                \"  \\\"complexText\\\": {\\n\" +\n                \"    \\\"nestedFields\\\": [\\n\" +\n                \"      {\\n\" +\n                \"        \\\"index\\\": \\\"0\\\",\\n\" +\n                \"        \\\"name\\\": \\\"A\\\"\\n\" +\n                \"      },\\n\" +\n                \"      {\\n\" +\n                \"        \\\"index\\\": \\\"1\\\",\\n\" +\n                \"        \\\"name\\\": \\\"B\\\"\\n\" +\n                \"      },\\n\" +\n                \"      {\\n\" +\n                \"        \\\"index\\\": \\\"2\\\",\\n\" +\n                \"        \\\"name\\\": \\\"C\\\"\\n\" +\n                \"      }\\n\" +\n                \"    ]\\n\" +\n                \"  }\\n\" +\n                \"}\";\n\n        String path1 = \"$.concat($.complexText.nestedFields[?(@.index == '2')].name,\" +\n                \"$.complexText.nestedFields[?(@.index == '1')].name,\" +\n                \"$.complexText.nestedFields[?(@.index == '0')].name)\";\n        String path2 = \"$.concat($.complexText.nestedFields[2].name,\" +\n                \"$.complexText.nestedFields[1].name,\" +\n                \"$.complexText.nestedFields[0].name)\";\n\n        assertThat((String) JsonPath.read(json, path1)).isEqualTo(\"CBA\");\n        assertThat((String) JsonPath.read(json, path2)).isEqualTo(\"CBA\");\n    }\n\n    //CS304 (manually written) Issue link: https://github.com/json-path/JsonPath/issues/620\n    @Test\n    public void issue_620_2() {\n        String json = \"{\\n\" +\n                \"  \\\"complexText\\\": {\\n\" +\n                \"    \\\"nestedFields\\\": [\\n\" +\n                \"      {\\n\" +\n                \"        \\\"index\\\": \\\"0\\\",\\n\" +\n                \"        \\\"name\\\": \\\"A\\\"\\n\" +\n                \"      },\\n\" +\n                \"      {\\n\" +\n                \"        \\\"index\\\": \\\"1\\\",\\n\" +\n                \"        \\\"name\\\": \\\"B\\\"\\n\" +\n                \"      },\\n\" +\n                \"      {\\n\" +\n                \"        \\\"index\\\": \\\"2\\\",\\n\" +\n                \"        \\\"name\\\": \\\"C\\\"\\n\" +\n                \"      }\\n\" +\n                \"    ]\\n\" +\n                \"  }\\n\" +\n                \"}\";\n\n        String path1 = \"$.concat($.complexText.nestedFields[?(@.index == '2')].name,\" +\n                \"$.complexText.nestedFields[?((@.index == '1')].name,\" +\n                \"$.complexText.nestedFields[?(@.index == '0')].name)\";\n\n        boolean thrown = false;\n\n        try {\n            Object result = (Object) JsonPath.read(json, path1);\n        } catch (Exception e) {\n            thrown = true;\n        }\n\n        assertTrue(thrown);\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/JsonPathTest.java",
    "content": "package com.jayway.jsonpath.old;\n\nimport com.jayway.jsonpath.*;\nimport com.jayway.jsonpath.internal.path.PathCompiler;\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.hasItems;\nimport static org.hamcrest.Matchers.hasSize;\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class JsonPathTest extends BaseTest {\n\n\n    static {\n        //JsonProviderFactory.setDefaultProvider(JacksonProvider.class);\n    }\n\n    public final static String ARRAY = \"[{\\\"value\\\": 1},{\\\"value\\\": 2}, {\\\"value\\\": 3},{\\\"value\\\": 4}]\";\n\n    public final static String DOCUMENT =\n            \"{ \\\"store\\\": {\\n\" +\n                    \"    \\\"book\\\": [ \\n\" +\n                    \"      { \\\"category\\\": \\\"reference\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Nigel Rees\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Sayings of the Century\\\",\\n\" +\n                    \"        \\\"display-price\\\": 8.95\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Evelyn Waugh\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Sword of Honour\\\",\\n\" +\n                    \"        \\\"display-price\\\": 12.99\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Herman Melville\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Moby Dick\\\",\\n\" +\n                    \"        \\\"isbn\\\": \\\"0-553-21311-3\\\",\\n\" +\n                    \"        \\\"display-price\\\": 8.99\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"J. R. R. Tolkien\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"The Lord of the Rings\\\",\\n\" +\n                    \"        \\\"isbn\\\": \\\"0-395-19395-8\\\",\\n\" +\n                    \"        \\\"display-price\\\": 22.99\\n\" +\n                    \"      }\\n\" +\n                    \"    ],\\n\" +\n                    \"    \\\"bicycle\\\": {\\n\" +\n                    \"      \\\"color\\\": \\\"red\\\",\\n\" +\n                    \"      \\\"display-price\\\": 19.95,\\n\" +\n                    \"      \\\"foo:bar\\\": \\\"fooBar\\\",\\n\" +\n                    \"      \\\"dot.notation\\\": \\\"new\\\",\\n\" +\n                    \"      \\\"dash-notation\\\": \\\"dashes\\\"\\n\" +\n                    \"    }\\n\" +\n                    \"  }\\n\" +\n                    \"}\";\n\n    public final static Object OBJ_DOCUMENT = JsonPath.parse(DOCUMENT).json();\n\n\n    private final static String PRODUCT_JSON = \"{\\n\" +\n            \"\\t\\\"product\\\": [ {\\n\" +\n            \"\\t    \\\"version\\\": \\\"A\\\", \\n\" +\n            \"\\t    \\\"codename\\\": \\\"Seattle\\\", \\n\" +\n            \"\\t    \\\"attr.with.dot\\\": \\\"A\\\"\\n\" +\n            \"\\t},\\n\" +\n            \"\\t{\\n\" +\n            \"\\t    \\\"version\\\": \\\"4.0\\\", \\n\" +\n            \"\\t    \\\"codename\\\": \\\"Montreal\\\", \\n\" +\n            \"\\t    \\\"attr.with.dot\\\": \\\"B\\\"\\n\" +\n            \"\\t}]\\n\" +\n            \"}\";\n\n    private final static String ARRAY_EXPAND = \"[{\\\"parent\\\": \\\"ONE\\\", \\\"child\\\": {\\\"name\\\": \\\"NAME_ONE\\\"}}, [{\\\"parent\\\": \\\"TWO\\\", \\\"child\\\": {\\\"name\\\": \\\"NAME_TWO\\\"}}]]\";\n\n\n    @Test\n    public void missing_prop() {\n\n        assertThrows(PathNotFoundException.class, () -> JsonPath.using(Configuration.defaultConfiguration().addOptions(Option.REQUIRE_PROPERTIES)).parse(DOCUMENT).read(\"$.store.book[*].fooBar.not\"));\n\n\n    }\n\n    @Test\n    public void bracket_notation_with_dots() {\n        String json = \"{\\n\" +\n                \"    \\\"store\\\": {\\n\" +\n                \"        \\\"book\\\": [\\n\" +\n                \"            {\\n\" +\n                \"                \\\"author.name\\\": \\\"Nigel Rees\\\", \\n\" +\n                \"                \\\"category\\\": \\\"reference\\\", \\n\" +\n                \"                \\\"price\\\": 8.95, \\n\" +\n                \"                \\\"title\\\": \\\"Sayings of the Century\\\"\\n\" +\n                \"            }\\n\" +\n                \"        ]\\n\" +\n                \"    }\\n\" +\n                \"}\";\n\n        assertEquals(\"Nigel Rees\", JsonPath.read(json, \"$.store.book[0]['author.name']\"));\n    }\n\n    @Test\n    public void null_object_in_path() {\n\n        String json = \"{\\n\" +\n                \"  \\\"success\\\": true,\\n\" +\n                \"  \\\"data\\\": {\\n\" +\n                \"    \\\"user\\\": 3,\\n\" +\n                \"    \\\"own\\\": null,\\n\" +\n                \"    \\\"passes\\\": null,\\n\" +\n                \"    \\\"completed\\\": null\\n\" +\n                \"  },\\n\" +\n                \"  \\\"data2\\\": {\\n\" +\n                \"    \\\"user\\\": 3,\\n\" +\n                \"    \\\"own\\\": null,\\n\" +\n                \"    \\\"passes\\\": [{\\\"id\\\":\\\"1\\\"}],\\n\" +\n                \"    \\\"completed\\\": null\\n\" +\n                \"  },\\n\" +\n                \"  \\\"version\\\": 1371160528774\\n\" +\n                \"}\";\n        try {\n            JsonPath.read(json, \"$.data.passes[0].id\");\n            Assertions.fail(\"Expected PathNotFoundException\");\n        } catch (PathNotFoundException e) {\n        }\n        Assertions.assertThat((String) JsonPath.read(json, \"$.data2.passes[0].id\")).isEqualTo(\"1\");\n    }\n\n    @Test\n    public void array_start_expands() throws Exception {\n        //assertThat(JsonPath.<List<String>>read(ARRAY_EXPAND, \"$[?(@.parent = 'ONE')].child.name\"), hasItems(\"NAME_ONE\"));\n        assertThat(JsonPath.<List<String>>read(ARRAY_EXPAND, \"$[?(@['parent'] == 'ONE')].child.name\"), hasItems(\"NAME_ONE\"));\n    }\n\n    @Test\n    public void bracket_notation_can_be_used_in_path() throws Exception {\n\n        assertEquals(\"new\", JsonPath.read(DOCUMENT, \"$.['store'].bicycle.['dot.notation']\"));\n        assertEquals(\"new\", JsonPath.read(DOCUMENT, \"$['store']['bicycle']['dot.notation']\"));\n        assertEquals(\"new\", JsonPath.read(DOCUMENT, \"$.['store']['bicycle']['dot.notation']\"));\n        assertEquals(\"new\", JsonPath.read(DOCUMENT, \"$.['store'].['bicycle'].['dot.notation']\"));\n\n\n        assertEquals(\"dashes\", JsonPath.read(DOCUMENT, \"$.['store'].bicycle.['dash-notation']\"));\n        assertEquals(\"dashes\", JsonPath.read(DOCUMENT, \"$['store']['bicycle']['dash-notation']\"));\n        assertEquals(\"dashes\", JsonPath.read(DOCUMENT, \"$.['store']['bicycle']['dash-notation']\"));\n        assertEquals(\"dashes\", JsonPath.read(DOCUMENT, \"$.['store'].['bicycle'].['dash-notation']\"));\n    }\n\n    @Test\n    public void filter_an_array() throws Exception {\n        List<Object> matches = JsonPath.read(ARRAY, \"$.[?(@.value == 1)]\");\n\n        assertEquals(1, matches.size());\n    }\n\n    @Test\n    public void filter_an_array_on_index() throws Exception {\n        Integer matches = JsonPath.read(ARRAY, \"$.[1].value\");\n\n        assertEquals(new Integer(2), matches);\n    }\n\n    @Test\n    public void read_path_with_colon() throws Exception {\n        assertEquals(JsonPath.read(DOCUMENT, \"$['store']['bicycle']['foo:bar']\"), \"fooBar\");\n    }\n\n    @Test\n    public void read_document_from_root() throws Exception {\n\n        Map result = JsonPath.read(DOCUMENT, \"$.store\");\n\n        assertEquals(2, result.values().size());\n    }\n\n    @Test\n    public void read_store_book_1() throws Exception {\n\n        JsonPath path = JsonPath.compile(\"$.store.book[1]\");\n\n        Map map = path.read(DOCUMENT);\n\n        assertEquals(\"Evelyn Waugh\", map.get(\"author\"));\n    }\n\n    @Test\n    public void read_store_book_wildcard() throws Exception {\n        JsonPath path = JsonPath.compile(\"$.store.book[*]\");\n\n        List<Object> list = path.read(DOCUMENT);\n        Assertions.assertThat(list.size()).isEqualTo(4);\n\n    }\n\n    @Test\n    public void read_store_book_author() throws Exception {\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$.store.book[0,1].author\"), hasItems(\"Nigel Rees\", \"Evelyn Waugh\"));\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$.store.book[*].author\"), hasItems(\"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\"));\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$.['store'].['book'][*].['author']\"), hasItems(\"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\"));\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$['store']['book'][*]['author']\"), hasItems(\"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\"));\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$['store'].book[*]['author']\"), hasItems(\"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\"));\n    }\n\n    @Test\n    public void all_authors() throws Exception {\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$..author\"), hasItems(\"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\"));\n    }\n\n\n    @Test\n    public void all_store_properties() throws Exception {\n        /*\n        List<Object> itemsInStore = JsonPath.read(DOCUMENT, \"$.store.*\");\n\n        assertEquals(JsonPath.read(itemsInStore, \"$.[0].[0].author\"), \"Nigel Rees\");\n        assertEquals(JsonPath.read(itemsInStore, \"$.[0][0].author\"), \"Nigel Rees\");\n        */\n        List<String> result = PathCompiler.compile(\"$.store.*\").evaluate(OBJ_DOCUMENT, OBJ_DOCUMENT, Configuration.defaultConfiguration()).getPathList();\n\n        Assertions.assertThat(result).containsOnly(\n                \"$['store']['bicycle']\",\n                \"$['store']['book']\");\n    }\n\n    @Test\n    public void all_prices_in_store() throws Exception {\n        assertThat(JsonPath.<List<Double>>read(DOCUMENT, \"$.store..['display-price']\"), hasItems(8.95D, 12.99D, 8.99D, 19.95D));\n\n    }\n\n    @Test\n    public void access_array_by_index_from_tail() throws Exception {\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$..book[1:].author\"), hasItems(\"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\"));\n    }\n\n    @Test\n    public void read_store_book_index_0_and_1() throws Exception {\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$.store.book[0,1].author\"), hasItems(\"Nigel Rees\", \"Evelyn Waugh\"));\n        assertTrue(JsonPath.<List>read(DOCUMENT, \"$.store.book[0,1].author\").size() == 2);\n    }\n\n    @Test\n    public void read_store_book_pull_first_2() throws Exception {\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$.store.book[:2].author\"), hasItems(\"Nigel Rees\", \"Evelyn Waugh\"));\n        assertTrue(JsonPath.<List>read(DOCUMENT, \"$.store.book[:2].author\").size() == 2);\n    }\n\n\n    @Test\n    public void read_store_book_filter_by_isbn() throws Exception {\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$.store.book[?(@.isbn)].isbn\"), hasItems(\"0-553-21311-3\", \"0-395-19395-8\"));\n        assertTrue(JsonPath.<List>read(DOCUMENT, \"$.store.book[?(@.isbn)].isbn\").size() == 2);\n        assertTrue(JsonPath.<List>read(DOCUMENT, \"$.store.book[?(@['isbn'])].isbn\").size() == 2);\n    }\n\n    @Test\n    public void all_books_cheaper_than_10() throws Exception {\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$..book[?(@['display-price'] < 10)].title\"), hasItems(\"Sayings of the Century\", \"Moby Dick\"));\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$..book[?(@.display-price < 10)].title\"), hasItems(\"Sayings of the Century\", \"Moby Dick\"));\n    }\n\n    @Test\n    public void all_books() throws Exception {\n        Assertions.assertThat(JsonPath.<List<Object>>read(DOCUMENT, \"$..book\")).hasSize(1);\n    }\n\n    @Test\n    public void dot_in_predicate_works() throws Exception {\n        assertThat(JsonPath.<List<String>>read(PRODUCT_JSON, \"$.product[?(@.version=='4.0')].codename\"), hasItems(\"Montreal\"));\n    }\n\n    @Test\n    public void dots_in_predicate_works() throws Exception {\n        assertThat(JsonPath.<List<String>>read(PRODUCT_JSON, \"$.product[?(@.['attr.with.dot']=='A')].codename\"), hasItems(\"Seattle\"));\n    }\n\n    @Test\n    public void all_books_with_category_reference() throws Exception {\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$..book[?(@.category=='reference')].title\"), hasItems(\"Sayings of the Century\"));\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$.store.book[?(@.category=='reference')].title\"), hasItems(\"Sayings of the Century\"));\n    }\n\n    @Test\n    public void all_members_of_all_documents() throws Exception {\n        List<String> all = JsonPath.read(DOCUMENT, \"$..*\");\n    }\n\n    @Test\n    public void access_index_out_of_bounds_does_not_throw_exception() throws Exception {\n        assertThrows(PathNotFoundException.class, () -> JsonPath.read(DOCUMENT, \"$.store.book[100].author\"));\n    }\n\n    @Test\n    public void exists_filter_with_nested_path() throws Exception {\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$..[?(@.bicycle.color)]\"), hasSize(1));\n        assertThat(JsonPath.<List<String>>read(DOCUMENT, \"$..[?(@.bicycle.numberOfGears)]\"), hasSize(0));\n\n    }\n\n    @Test\n    // see https://code.google.com/p/json-path/issues/detail?id=58\n    public void invalid_paths_throw_invalid_path_exception() throws Exception {\n        for (String path : new String[]{\"$.\", \"$.results[?\"}) {\n            try {\n                JsonPath.compile(path);\n            } catch (InvalidPathException e) {\n                // that's expected\n            } catch (Exception e) {\n                fail(\"Expected an InvalidPathException trying to compile '\" + path + \"', but got a \" + e.getClass().getName());\n            }\n        }\n    }\n\n    @Test\n    //see https://github.com/json-path/JsonPath/issues/428\n    public void prevent_stack_overflow_error_when_unclosed_property() {\n        assertThrows(InvalidPathException.class, () -> JsonPath.compile(\"$['boo','foo][?(@ =~ /bar/)]\"));\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/JsonProviderTest.java",
    "content": "package com.jayway.jsonpath.old;\n\nimport com.jayway.jsonpath.spi.json.JacksonJsonProvider;\nimport org.junit.jupiter.api.Test;\n\npublic class JsonProviderTest {\n\n    public final static String ARRAY = \"[{\\\"value\\\": 1},{\\\"value\\\": 2}, {\\\"value\\\": 3},{\\\"value\\\": 4}]\";\n\n    public final static String DOCUMENT =\n            \"{ \\\"store\\\": {\\n\" +\n                    \"    \\\"book\\\": [ \\n\" +\n                    \"      { \\\"category\\\": \\\"reference\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Nigel Rees\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Sayings of the Century\\\",\\n\" +\n                    \"        \\\"price\\\": 8.95\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Evelyn Waugh\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Sword of Honour\\\",\\n\" +\n                    \"        \\\"price\\\": 12.99\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Herman Melville\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Moby Dick\\\",\\n\" +\n                    \"        \\\"isbn\\\": \\\"0-553-21311-3\\\",\\n\" +\n                    \"        \\\"price\\\": 8.99\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"J. R. R. Tolkien\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"The Lord of the Rings\\\",\\n\" +\n                    \"        \\\"isbn\\\": \\\"0-395-19395-8\\\",\\n\" +\n                    \"        \\\"price\\\": 22.99\\n\" +\n                    \"      }\\n\" +\n                    \"    ],\\n\" +\n                    \"    \\\"bicycle\\\": {\\n\" +\n                    \"      \\\"color\\\": \\\"red\\\",\\n\" +\n                    \"      \\\"price\\\": 19.95,\\n\" +\n                    \"      \\\"foo:bar\\\": \\\"fooBar\\\",\\n\" +\n                    \"      \\\"dot.notation\\\": \\\"new\\\"\\n\" +\n                    \"    }\\n\" +\n                    \"  }\\n\" +\n                    \"}\";\n\n\n\n\n\n\n    @Test\n    public void parse_document() throws Exception {\n\n        JacksonJsonProvider provider = new JacksonJsonProvider();\n\n        Object o = provider.parse(DOCUMENT);\n\n\n    }\n\n    @Test\n    public void parse_array() throws Exception {\n        JacksonJsonProvider provider = new JacksonJsonProvider();\n\n        Object o = provider.parse(ARRAY);\n\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/NullHandlingTest.java",
    "content": "package com.jayway.jsonpath.old;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.JsonPath;\nimport com.jayway.jsonpath.Option;\nimport com.jayway.jsonpath.PathNotFoundException;\nimport org.assertj.core.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\npublic class NullHandlingTest {\n\n    public static final String DOCUMENT = \"{\\n\" +\n            \"   \\\"root-property\\\": \\\"root-property-value\\\",\\n\" +\n            \"   \\\"root-property-null\\\": null,\\n\" +\n            \"   \\\"children\\\": [\\n\" +\n            \"      {\\n\" +\n            \"         \\\"id\\\": 0,\\n\" +\n            \"         \\\"name\\\": \\\"name-0\\\",\\n\" +\n            \"         \\\"age\\\": 0\\n\" +\n            \"      },\\n\" +\n            \"      {\\n\" +\n            \"         \\\"id\\\": 1,\\n\" +\n            \"         \\\"name\\\": \\\"name-1\\\",\\n\" +\n            \"         \\\"age\\\": null\" +\n            \"      },\\n\" +\n            \"      {\\n\" +\n            \"         \\\"id\\\": 3,\\n\" +\n            \"         \\\"name\\\": \\\"name-3\\\"\\n\" +\n            \"      }\\n\" +\n            \"   ]\\n\" +\n            \"}\";\n\n\n    @Test\n    public void not_defined_property_throws_PathNotFoundException() {\n        assertThrows(PathNotFoundException.class, () -> JsonPath.read(DOCUMENT, \"$.children[0].child.age\"));\n    }\n\n\n    @Test\n    public void last_token_defaults_to_null() {\n        Configuration configuration = Configuration.builder().options(Option.DEFAULT_PATH_LEAF_TO_NULL).build();\n\n        assertNull(JsonPath.parse(DOCUMENT, configuration).read(\"$.children[2].age\"));\n    }\n\n\n    @Test\n    public void null_property_returns_null() {\n        Integer age = JsonPath.read(DOCUMENT, \"$.children[1].age\");\n        assertNull(age);\n    }\n\n    @Test\n    public void the_age_of_all_with_age_defined() {\n        //List<Integer> result = JsonPath.read(DOCUMENT, \"$.children[*].age\");\n        List<Integer> result = JsonPath.using(Configuration.defaultConfiguration().setOptions(Option.SUPPRESS_EXCEPTIONS)).parse(DOCUMENT).read(\"$.children[*].age\");\n\n        Assertions.assertThat(result).containsSequence(0, null);\n\n    }\n\n    @Test\n    public void path2() {\n        List<Object> result = JsonPath.read(\"{\\\"a\\\":[{\\\"b\\\":1,\\\"c\\\":2},{\\\"b\\\":5,\\\"c\\\":2}]}\", \"a[?(@.b==4)].c\");\n        Assertions.assertThat(result).isEmpty();\n    }\n\n    @Test\n    public void path() {\n        String json = \"{\\\"a\\\":[{\\\"b\\\":1,\\\"c\\\":2},{\\\"b\\\":5,\\\"c\\\":2}]}\";\n\n        List<Object> result = JsonPath.using(Configuration.defaultConfiguration().setOptions(Option.DEFAULT_PATH_LEAF_TO_NULL)).parse(json).read(\"a[?(@.b==5)].d\");\n\n        Assertions.assertThat(result).hasSize(1);\n        Assertions.assertThat(result.get(0)).isNull();\n\n    }\n\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/internal/ArrayIndexFilterTest.java",
    "content": "package com.jayway.jsonpath.old.internal;\n\nimport com.jayway.jsonpath.JsonPath;\nimport org.hamcrest.Matchers;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class ArrayIndexFilterTest {\n\n    private static final String JSON = \"[1, 3, 5, 7, 8, 13, 20]\";\n\n    @Test\n    public void tail_does_not_throw_when_index_out_of_bounds() {\n        List<Integer> result = JsonPath.parse(JSON).read(\"$[-10:]\");\n        assertThat(result, Matchers.contains(1, 3, 5, 7, 8, 13, 20));\n    }\n\n    @Test\n    public void head_does_not_throw_when_index_out_of_bounds() {\n        List<Integer> result = JsonPath.parse(JSON).read(\"$[:10]\");\n        assertThat(result, Matchers.contains(1, 3, 5, 7, 8, 13, 20));\n    }\n\n    @Test\n    public void head_grabs_correct() {\n        List<Integer> result = JsonPath.parse(JSON).read(\"$[:3]\");\n        assertThat(result, Matchers.contains(1, 3, 5));\n    }\n\n\n    @Test\n    public void tail_grabs_correct() {\n        List<Integer> result = JsonPath.parse(JSON).read(\"$[-3:]\");\n        assertThat(result, Matchers.contains(8, 13, 20));\n    }\n\n    @Test\n    public void head_tail_grabs_correct() {\n        List<Integer> result = JsonPath.parse(JSON).read(\"$[0:3]\");\n        assertThat(result, Matchers.contains(1, 3, 5));\n    }\n\n    @Test\n    public void can_access_items_from_end_with_negative_index() {\n        int result = JsonPath.parse(JSON).read(\"$[-3]\");\n        assertEquals(8, result);\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/internal/ArrayPathTokenTest.java",
    "content": "package com.jayway.jsonpath.old.internal;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.jayway.jsonpath.JsonPath.read;\nimport static java.util.Collections.singletonMap;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class ArrayPathTokenTest extends TestBase {\n\n\n\n    @Test\n    public void array_can_select_multiple_indexes() {\n\n        List<Map> result = read(ARRAY, \"$[0,1]\");\n\n        assertThat(result).containsOnly(\n                singletonMap(\"foo\", \"foo-val-0\"),\n                singletonMap(\"foo\", \"foo-val-1\"));\n    }\n\n    @Test\n    public void array_can_be_sliced_to_2() {\n\n        List<Map> result = read(ARRAY, \"$[:2]\");\n\n        assertThat(result).containsOnly(\n                singletonMap(\"foo\", \"foo-val-0\"),\n                singletonMap(\"foo\", \"foo-val-1\"));\n\n    }\n\n    @Test\n    public void array_can_be_sliced_to_2_from_tail() {\n\n        List<Map> result = read(ARRAY, \"$[:-5]\");\n\n        assertThat(result).containsOnly(\n                singletonMap(\"foo\", \"foo-val-0\"),\n                singletonMap(\"foo\", \"foo-val-1\"));\n\n    }\n\n    @Test\n    public void array_can_be_sliced_from_2() {\n\n        List<Map> result = read(ARRAY, \"$[5:]\");\n\n        assertThat(result).containsOnly(\n                singletonMap(\"foo\", \"foo-val-5\"),\n                singletonMap(\"foo\", \"foo-val-6\"));\n\n    }\n\n    @Test\n    public void array_can_be_sliced_from_2_from_tail() {\n\n        List<Map> result = read(ARRAY, \"$[-2:]\");\n\n        assertThat(result).containsOnly(\n                singletonMap(\"foo\", \"foo-val-5\"),\n                singletonMap(\"foo\", \"foo-val-6\"));\n\n    }\n\n    @Test\n    public void array_can_be_sliced_between() {\n\n        List<Map> result = read(ARRAY, \"$[2:4]\");\n\n        assertThat(result).containsOnly(\n                singletonMap(\"foo\", \"foo-val-2\"),\n                singletonMap(\"foo\", \"foo-val-3\"));\n\n    }\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/internal/PredicatePathTokenTest.java",
    "content": "package com.jayway.jsonpath.old.internal;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.JsonPath;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static java.util.Collections.singletonMap;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.entry;\n\npublic class PredicatePathTokenTest {\n\n    private static final Object ARRAY = Configuration.defaultConfiguration().jsonProvider().parse(\n            \"[\" +\n                    \"{\\n\" +\n                    \"   \\\"foo\\\" : \\\"foo-val-0\\\"\\n\" +\n                    \"},\" +\n                    \"{\\n\" +\n                    \"   \\\"foo\\\" : \\\"foo-val-1\\\"\\n\" +\n                    \"},\" +\n                    \"{\\n\" +\n                    \"   \\\"foo\\\" : \\\"foo-val-2\\\"\\n\" +\n                    \"},\" +\n                    \"{\\n\" +\n                    \"   \\\"foo\\\" : \\\"foo-val-3\\\"\\n\" +\n                    \"},\" +\n                    \"{\\n\" +\n                    \"   \\\"foo\\\" : \\\"foo-val-4\\\"\\n\" +\n                    \"},\" +\n                    \"{\\n\" +\n                    \"   \\\"foo\\\" : \\\"foo-val-5\\\"\\n\" +\n                    \"},\" +\n                    \"{\\n\" +\n                    \"   \\\"foo\\\" : \\\"foo-val-6\\\"\\n\" +\n                    \"}\" +\n                    \"]\");\n\n    private static Object  ARRAY2 = Configuration.defaultConfiguration().jsonProvider().parse(\n            \"[\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-0\\\",\\n\" +\n            \"   \\\"int\\\" : 0\\n,\" +\n            \"   \\\"decimal\\\" : 0.0\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-1\\\",\\n\" +\n            \"   \\\"int\\\" : 1,\\n\" +\n            \"   \\\"decimal\\\" : 0.1\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-2\\\",\\n\" +\n            \"   \\\"int\\\" : 2,\\n\" +\n            \"   \\\"decimal\\\" : 0.2\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-3\\\",\\n\" +\n            \"   \\\"int\\\" : 3,\\n\" +\n            \"   \\\"decimal\\\" : 0.3\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-4\\\",\\n\" +\n            \"   \\\"int\\\" : 4,\\n\" +\n            \"   \\\"decimal\\\" : 0.4\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-5\\\",\\n\" +\n            \"   \\\"int\\\" : 5,\\n\" +\n            \"   \\\"decimal\\\" : 0.5\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-6\\\",\\n\" +\n            \"   \\\"int\\\" : 6,\\n\" +\n            \"   \\\"decimal\\\" : 0.6\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-7\\\",\\n\" +\n            \"   \\\"int\\\" : 7,\\n\" +\n            \"   \\\"decimal\\\" : 0.7,\\n\" +\n            \"   \\\"bool\\\" : true\\n\" +\n            \"}\" +\n            \"]\");\n\n\n    @Test\n    public void a_filter_predicate_can_be_evaluated_on_string_criteria() {\n\n        List<Map> result = JsonPath.read (ARRAY, \"$[?(@.foo == 'foo-val-1')]\");\n\n        assertThat(result).containsOnly(singletonMap(\"foo\", \"foo-val-1\"));\n    }\n\n    @Test\n    public void a_filter_predicate_can_be_evaluated_on_int_criteria() {\n\n        List<Map> result = JsonPath.read (ARRAY2, \"$[?(@.int == 1)]\");\n\n        assertThat(result).hasSize(1);\n        assertThat(result.get(0)).contains(entry(\"int\", 1));\n    }\n\n    @Test\n    public void a_filter_predicate_can_be_evaluated_on_decimal_criteria() {\n\n        List<Map> result = JsonPath.read (ARRAY2, \"$[?(@.decimal == 0.1)]\");\n\n        assertThat(result).hasSize(1);\n        assertThat(result.get(0)).contains(entry(\"decimal\", 0.1));\n    }\n\n    @Test\n    public void multiple_criteria_can_be_used() {\n\n        List<Map> result = JsonPath.read (ARRAY2, \"$[?(@.decimal == 0.1 && @.int == 1)]\");\n\n        assertThat(result).hasSize(1);\n        assertThat(result.get(0)).contains(entry(\"foo\", \"foo-val-1\"));\n    }\n\n    @Test\n    public void field_existence_can_be_checked() {\n\n        List<Map> result = JsonPath.read (ARRAY2, \"$[?(@.bool)]\");\n\n        assertThat(result).hasSize(1);\n        assertThat(result.get(0)).contains(entry(\"foo\", \"foo-val-7\"));\n    }\n\n    @Test\n    public void boolean_criteria_evaluates() {\n\n        List<Map> result = JsonPath.read (ARRAY2, \"$[?(@.bool == true)]\");\n\n        assertThat(result).hasSize(1);\n        assertThat(result.get(0)).contains(entry(\"foo\", \"foo-val-7\"));\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/internal/PropertyPathTokenTest.java",
    "content": "package com.jayway.jsonpath.old.internal;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.JsonPath;\nimport com.jayway.jsonpath.Option;\nimport com.jayway.jsonpath.PathNotFoundException;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.List;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\npublic class PropertyPathTokenTest {\n\n    private static final Logger logger = LoggerFactory.getLogger(PropertyPathTokenTest.class);\n\n    private String SIMPLE_MAP = \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val\\\",\\n\" +\n            \"   \\\"bar\\\" : \\\"bar-val\\\",\\n\" +\n            \"   \\\"baz\\\" : {\\\"baz-child\\\" : \\\"baz-child-val\\\"}\\n\" +\n            \"}\";\n\n    private String SIMPLE_ARRAY = \"[\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-0\\\",\\n\" +\n            \"   \\\"bar\\\" : \\\"bar-val-0\\\",\\n\" +\n            \"   \\\"baz\\\" : {\\\"baz-child\\\" : \\\"baz-child-val\\\"}\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-1\\\",\\n\" +\n            \"   \\\"bar\\\" : \\\"bar-val-1\\\",\\n\" +\n            \"   \\\"baz\\\" : {\\\"baz-child\\\" : \\\"baz-child-val\\\"}\\n\" +\n            \"}\" +\n            \"]\";\n\n\n    @Test\n    public void property_not_found() {\n\n        //String result = JsonPath.read(SIMPLE_MAP, \"$.not-found\");\n\n        //assertThat(result).isNull();\n\n        Configuration configuration = Configuration.builder().options(Option.SUPPRESS_EXCEPTIONS).build();\n\n        String json = \"{\\\"a\\\":{\\\"b\\\":1,\\\"c\\\":2}}\";\n        assertNull(JsonPath.parse(SIMPLE_MAP, configuration).read(\"$.not-found\"));\n\n\n    }\n\n    @Test\n    public void property_not_found_deep() {\n        assertThrows(PathNotFoundException.class, () -> JsonPath.read(SIMPLE_MAP, \"$.foo.not-found\"));\n    }\n\n    @Test\n    public void property_not_found_option_throw() {\n        assertThrows(PathNotFoundException.class, () -> JsonPath.using(Configuration.defaultConfiguration()).parse(SIMPLE_MAP).read(\"$.not-found\"));\n    }\n\n    @Test\n    public void map_value_can_be_read_from_map() {\n\n        String result = JsonPath.read(SIMPLE_MAP, \"$.foo\");\n\n        assertThat(result).isEqualTo(\"foo-val\");\n    }\n\n    @Test\n    public void map_value_can_be_read_from_array() {\n\n        List<String> result = JsonPath.read(SIMPLE_ARRAY, \"$[*].foo\");\n\n        assertThat(result).containsOnly(\"foo-val-0\", \"foo-val-1\");\n    }\n\n    @Test\n    public void map_value_can_be_read_from_child_map() {\n\n        String result = JsonPath.read(SIMPLE_MAP, \"$.baz.baz-child\");\n\n        assertThat(result).isEqualTo(\"baz-child-val\");\n\n    }\n\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/internal/ScanPathTokenTest.java",
    "content": "package com.jayway.jsonpath.old.internal;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.internal.path.PathCompiler;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static com.jayway.jsonpath.JsonPath.read;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class ScanPathTokenTest {\n\n\n    public final static Object DOCUMENT = Configuration.defaultConfiguration().jsonProvider().parse(\n            \"{\\n\" +\n                    \" \\\"store\\\":{\\n\" +\n                    \"  \\\"book\\\":[\\n\" +\n                    \"   {\\n\" +\n                    \"    \\\"category\\\":\\\"reference\\\",\\n\" +\n                    \"    \\\"author\\\":\\\"Nigel Rees\\\",\\n\" +\n                    \"    \\\"title\\\":\\\"Sayings of the Century\\\",\\n\" +\n                    \"    \\\"price\\\":8.95,\\n\" +\n                    \"    \\\"address\\\":{ \" +\n                    \"        \\\"street\\\":\\\"fleet street\\\",\\n\" +\n                    \"        \\\"city\\\":\\\"London\\\"\\n\" +\n                    \"      }\\n\" +\n                    \"   },\\n\" +\n                    \"   {\\n\" +\n                    \"    \\\"category\\\":\\\"fiction\\\",\\n\" +\n                    \"    \\\"author\\\":\\\"Evelyn Waugh\\\",\\n\" +\n                    \"    \\\"title\\\":\\\"Sword of Honour\\\",\\n\" +\n                    \"    \\\"price\\\":12.9,\\n\" +\n                    \"    \\\"address\\\":{ \\n\" +\n                    \"        \\\"street\\\":\\\"Baker street\\\",\\n\" +\n                    \"        \\\"city\\\":\\\"London\\\"\\n\" +\n                    \"      }\\n\" +\n                    \"   },\\n\" +\n                    \"   {\\n\" +\n                    \"    \\\"category\\\":\\\"fiction\\\",\\n\" +\n                    \"    \\\"author\\\":\\\"J. R. R. Tolkien\\\",\\n\" +\n                    \"    \\\"title\\\":\\\"The Lord of the Rings\\\",\\n\" +\n                    \"    \\\"isbn\\\":\\\"0-395-19395-8\\\",\\n\" +\n                    \"    \\\"price\\\":22.99,\" +\n                    \"    \\\"address\\\":{ \" +\n                    \"        \\\"street\\\":\\\"Svea gatan\\\",\\n\" +\n                    \"        \\\"city\\\":\\\"Stockholm\\\"\\n\" +\n                    \"      }\\n\" +\n                    \"   }\\n\" +\n                    \"  ],\\n\" +\n                    \"  \\\"bicycle\\\":{\\n\" +\n                    \"   \\\"color\\\":\\\"red\\\",\\n\" +\n                    \"   \\\"price\\\":19.95,\" +\n                    \"   \\\"address\\\":{ \" +\n                    \"        \\\"street\\\":\\\"Söder gatan\\\",\\n\" +\n                    \"        \\\"city\\\":\\\"Stockholm\\\"\\n\" +\n                    \"      },\\n\" +\n                    \"   \\\"items\\\": [[\\\"A\\\",\\\"B\\\",\\\"C\\\"],1,2,3,4,5]\\n\" +\n                    \"  }\\n\" +\n                    \" }\\n\" +\n                    \"}\"\n    );\n\n    public final static Object DOCUMENT2 = Configuration.defaultConfiguration().jsonProvider().parse(\n            \"{\\n\" +\n                    \"     \\\"firstName\\\": \\\"John\\\",\\n\" +\n                    \"     \\\"lastName\\\" : \\\"doe\\\",\\n\" +\n                    \"     \\\"age\\\"      : 26,\\n\" +\n                    \"     \\\"address\\\"  :\\n\" +\n                    \"     {\\n\" +\n                    \"         \\\"streetAddress\\\": \\\"naist street\\\",\\n\" +\n                    \"         \\\"city\\\"         : \\\"Nara\\\",\\n\" +\n                    \"         \\\"postalCode\\\"   : \\\"630-0192\\\"\\n\" +\n                    \"     },\\n\" +\n                    \"     \\\"phoneNumbers\\\":\\n\" +\n                    \"     [\\n\" +\n                    \"         {\\n\" +\n                    \"           \\\"type\\\"  : \\\"iPhone\\\",\\n\" +\n                    \"           \\\"number\\\": \\\"0123-4567-8888\\\"\\n\" +\n                    \"         },\\n\" +\n                    \"         {\\n\" +\n                    \"           \\\"type\\\"  : \\\"home\\\",\\n\" +\n                    \"           \\\"number\\\": \\\"0123-4567-8910\\\"\\n\" +\n                    \"         }\\n\" +\n                    \"     ]\\n\" +\n                    \" }\"\n    );\n\n    @Test\n    public void a_document_can_be_scanned_for_property() {\n\n        List<String> result = read(DOCUMENT, \"$..author\");\n\n        assertThat(result).containsOnly(\"Nigel Rees\", \"Evelyn Waugh\", \"J. R. R. Tolkien\");\n    }\n\n    @Test\n    public void a_document_can_be_scanned_for_property_path() {\n\n        List<String> result = read(DOCUMENT, \"$..address.street\");\n\n        assertThat(result).containsOnly(\"fleet street\", \"Baker street\", \"Svea gatan\", \"Söder gatan\");\n    }\n\n    @Test\n    public void a_document_can_be_scanned_for_wildcard() {\n\n        List<String> result = PathCompiler.compile(\"$..[*]\").evaluate(DOCUMENT, DOCUMENT, Configuration.defaultConfiguration()).getPathList();\n\n        assertThat(result).containsOnly(\n                \"$['store']\",\n                \"$['store']['bicycle']\",\n                \"$['store']['book']\",\n                \"$['store']['bicycle']['address']\",\n                \"$['store']['bicycle']['color']\",\n                \"$['store']['bicycle']['price']\",\n                \"$['store']['bicycle']['items']\",\n                \"$['store']['bicycle']['address']['city']\",\n                \"$['store']['bicycle']['address']['street']\",\n                \"$['store']['bicycle']['items'][0]\",\n                \"$['store']['bicycle']['items'][1]\",\n                \"$['store']['bicycle']['items'][2]\",\n                \"$['store']['bicycle']['items'][3]\",\n                \"$['store']['bicycle']['items'][4]\",\n                \"$['store']['bicycle']['items'][5]\",\n                \"$['store']['bicycle']['items'][0][0]\",\n                \"$['store']['bicycle']['items'][0][1]\",\n                \"$['store']['bicycle']['items'][0][2]\",\n                \"$['store']['book'][0]\",\n                \"$['store']['book'][1]\",\n                \"$['store']['book'][2]\",\n                \"$['store']['book'][0]['address']\",\n                \"$['store']['book'][0]['author']\",\n                \"$['store']['book'][0]['price']\",\n                \"$['store']['book'][0]['category']\",\n                \"$['store']['book'][0]['title']\",\n                \"$['store']['book'][0]['address']['city']\",\n                \"$['store']['book'][0]['address']['street']\",\n                \"$['store']['book'][1]['address']\",\n                \"$['store']['book'][1]['author']\",\n                \"$['store']['book'][1]['price']\",\n                \"$['store']['book'][1]['category']\",\n                \"$['store']['book'][1]['title']\",\n                \"$['store']['book'][1]['address']['city']\",\n                \"$['store']['book'][1]['address']['street']\",\n                \"$['store']['book'][2]['address']\",\n                \"$['store']['book'][2]['author']\",\n                \"$['store']['book'][2]['price']\",\n                \"$['store']['book'][2]['isbn']\",\n                \"$['store']['book'][2]['category']\",\n                \"$['store']['book'][2]['title']\",\n                \"$['store']['book'][2]['address']['city']\",\n                \"$['store']['book'][2]['address']['street']\");\n    }\n\n    @Test\n    public void a_document_can_be_scanned_for_wildcard2() {\n\n        List<String> result = PathCompiler.compile(\"$.store.book[0]..*\").evaluate(DOCUMENT, DOCUMENT, Configuration.defaultConfiguration()).getPathList();\n\n        assertThat(result).containsOnly(\n                \"$['store']['book'][0]['address']\",\n                \"$['store']['book'][0]['author']\",\n                \"$['store']['book'][0]['price']\",\n                \"$['store']['book'][0]['category']\",\n                \"$['store']['book'][0]['title']\",\n                \"$['store']['book'][0]['address']['city']\",\n                \"$['store']['book'][0]['address']['street']\");\n\n    }\n\n    @Test\n    public void a_document_can_be_scanned_for_wildcard3() {\n\n        List<String> result = PathCompiler.compile(\"$.phoneNumbers[0]..*\").evaluate(DOCUMENT2, DOCUMENT, Configuration.defaultConfiguration()).getPathList();\n\n        assertThat(result).containsOnly(\n                \"$['phoneNumbers'][0]['number']\",\n                \"$['phoneNumbers'][0]['type']\");\n\n    }\n\n    @Test\n    public void a_document_can_be_scanned_for_predicate_match() {\n\n        List<String> result = PathCompiler.compile(\"$..[?(@.address.city == 'Stockholm')]\").evaluate(DOCUMENT, DOCUMENT, Configuration.defaultConfiguration()).getPathList();\n\n        assertThat(result).containsOnly(\n                \"$['store']['bicycle']\",\n                \"$['store']['book'][2]\");\n\n    }\n\n    @Test\n    public void a_document_can_be_scanned_for_existence() {\n\n        List<String> result = PathCompiler.compile(\"$..[?(@.isbn)]\").evaluate(DOCUMENT, DOCUMENT, Configuration.defaultConfiguration()).getPathList();\n\n        assertThat(result).containsOnly(\n                \"$['store']['book'][2]\");\n    }\n\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/internal/TestBase.java",
    "content": "package com.jayway.jsonpath.old.internal;\n\nimport com.jayway.jsonpath.Configuration;\n\n/**\n *\n */\npublic class TestBase {\n\n\n    public final static Object ARRAY = Configuration.defaultConfiguration().jsonProvider().parse(\"[\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-0\\\"\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-1\\\"\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-2\\\"\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-3\\\"\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-4\\\"\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-5\\\"\\n\" +\n            \"},\" +\n            \"{\\n\" +\n            \"   \\\"foo\\\" : \\\"foo-val-6\\\"\\n\" +\n            \"}\" +\n            \"]\");\n\n    public final static Object DOC = Configuration.defaultConfiguration().jsonProvider().parse(\n            \"{ \\\"store\\\": {\\n\" +\n                    \"    \\\"book\\\": [ \\n\" +\n                    \"      { \\\"category\\\": \\\"reference\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Nigel Rees\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Sayings of the Century\\\",\\n\" +\n                    \"        \\\"display-price\\\": 8.95\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Evelyn Waugh\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Sword of Honour\\\",\\n\" +\n                    \"        \\\"display-price\\\": 12.99\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Herman Melville\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Moby Dick\\\",\\n\" +\n                    \"        \\\"isbn\\\": \\\"0-553-21311-3\\\",\\n\" +\n                    \"        \\\"display-price\\\": 8.99\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"J. R. R. Tolkien\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"The Lord of the Rings\\\",\\n\" +\n                    \"        \\\"isbn\\\": \\\"0-395-19395-8\\\",\\n\" +\n                    \"        \\\"display-price\\\": 22.99\\n\" +\n                    \"      }\\n\" +\n                    \"    ],\\n\" +\n                    \"    \\\"bicycle\\\": {\\n\" +\n                    \"      \\\"color\\\": \\\"red\\\",\\n\" +\n                    \"      \\\"display-price\\\": 19.95,\\n\" +\n                    \"      \\\"foo:bar\\\": \\\"fooBar\\\",\\n\" +\n                    \"      \\\"dot.notation\\\": \\\"new\\\",\\n\" +\n                    \"      \\\"dash-notation\\\": \\\"dashes\\\"\\n\" +\n                    \"    }\\n\" +\n                    \"  }\\n\" +\n                    \"}\");\n\n\n\n    public final static Configuration CONF = Configuration.defaultConfiguration();\n\n}\n"
  },
  {
    "path": "json-path/src/test/java/com/jayway/jsonpath/old/internal/TestInternal3.java",
    "content": "package com.jayway.jsonpath.old.internal;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.jayway.jsonpath.internal.path.PathCompiler.compile;\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n *\n */\npublic class TestInternal3 extends TestBase {\n\n    /*\n            RootPathToken rootToken = new RootPathToken();\n        //rootToken.append(new PropertyPathToken(\"stores\"));\n        //rootToken.append(new ArrayPathToken(asList(0, 1), ArrayPathToken.Operation.INDEX_SEQUENCE));\n        //rootToken.append(new ArrayPathToken(asList(0, 2), ArrayPathToken.Operation.SLICE_BETWEEN));\n        //rootToken.append(new FilterPathToken(Filter.filter(Criteria.where(\"name\").is(\"store_1\"))));\n        //rootToken.append(new WildcardPathToken());\n        rootToken.append(new ScanPathToken());\n        rootToken.append(new ArrayPathToken(asList(0), ArrayPathToken.Operation.INDEX_SEQUENCE));\n        rootToken.append(new PropertyPathToken(\"name\"));\n     */\n\n\n\n    @Test\n    public void a_root_object_can_be_evaluated() {\n        Map<String, Object> result = compile(\"$\").evaluate(DOC, DOC, CONF).getValue();\n\n        assertThat(result)\n                .containsKey(\"store\")\n                .hasSize(1);\n    }\n\n    @Test\n    public void a_definite_array_item_property_can_be_evaluated() {\n\n        String result = compile(\"$.store.book[0].author\").evaluate(DOC, DOC, CONF).getValue();\n\n        assertThat(result).isEqualTo(\"Nigel Rees\");\n    }\n\n    @Test\n    public void a_wildcard_array_item_property_can_be_evaluated() {\n\n        List result = compile(\"$.store.book[*].author\").evaluate(DOC, DOC, CONF).getValue();\n\n        assertThat(result).containsOnly(\n                \"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\");\n    }\n\n}\n"
  },
  {
    "path": "json-path/src/test/resources/issue_191.json",
    "content": "{\n    \"activated_slaves\": 5,\n    \"build_date\": \"2015-01-09 02:25:21\",\n    \"build_time\": 1420770321,\n    \"build_user\": \"root\",\n    \"completed_frameworks\": [\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172738-2049997834-5050-23289-0433\",\n                    \"id\": \"mesos-jenkins-172c6f74-12bc-44fe-849a-ad902ddc2b64\",\n                    \"name\": \"task mesos-jenkins-172c6f74-12bc-44fe-849a-ad902ddc2b64\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427206149.38254\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427207981.47819\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172738-2049997834-5050-23289-0433\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": -2.22044604925031e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427207787.01579,\n            \"reregistered_time\": 1427207787.0158,\n            \"resources\": {\n                \"cpus\": -2.22044604925031e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427207981.47898,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0000\",\n                    \"id\": \"mesos-jenkins-cd18b433-e2ee-4a4e-875b-6ea82d90a53a\",\n                    \"name\": \"task mesos-jenkins-cd18b433-e2ee-4a4e-875b-6ea82d90a53a\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172748-1513192458-5050-6647-S0\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427209005.01389\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427209961.51519\n                        }\n                    ]\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0000\",\n                    \"id\": \"mesos-jenkins-66fca7c0-88f7-4a1a-9796-a6de2e337b0a\",\n                    \"name\": \"task mesos-jenkins-66fca7c0-88f7-4a1a-9796-a6de2e337b0a\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427209025.84128\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427211101.4792\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-0000\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427208985.06716,\n            \"resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427211101.48013,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0001\",\n                    \"id\": \"mesos-jenkins-258ad47c-85bf-4fe0-b7c4-4f0cc70f2998\",\n                    \"name\": \"task mesos-jenkins-258ad47c-85bf-4fe0-b7c4-4f0cc70f2998\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427211139.85003\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427212121.47896\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-0001\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": 2.22044604925031e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427211125.06385,\n            \"resources\": {\n                \"cpus\": 2.22044604925031e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427212121.4797,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0002\",\n                    \"id\": \"mesos-jenkins-f30e5e34-2ef6-4993-9260-73ee3520c0a5\",\n                    \"name\": \"task mesos-jenkins-f30e5e34-2ef6-4993-9260-73ee3520c0a5\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427213316.78467\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427214401.47958\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-0002\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427213305.0687,\n            \"resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427214401.48033,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0003\",\n                    \"id\": \"mesos-jenkins-1fc0bbd8-f0ff-48cd-a7f7-24a9436ba6bc\",\n                    \"name\": \"task mesos-jenkins-1fc0bbd8-f0ff-48cd-a7f7-24a9436ba6bc\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427215879.15661\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427217701.47961\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-0003\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427215868.06173,\n            \"resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427217701.48035,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0004\",\n                    \"id\": \"mesos-jenkins-62b44026-843d-4813-a6a8-e95215250bb1\",\n                    \"name\": \"task mesos-jenkins-62b44026-843d-4813-a6a8-e95215250bb1\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427222969.79605\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427223941.48583\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-0004\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427222958.07464,\n            \"resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427223941.48665,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0005\",\n                    \"id\": \"mesos-jenkins-807b9b8a-3283-4e78-94e1-9dc17df4df77\",\n                    \"name\": \"task mesos-jenkins-807b9b8a-3283-4e78-94e1-9dc17df4df77\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427309356.80847\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427310341.47914\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-0005\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": -2.22044604925031e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427309345.18029,\n            \"resources\": {\n                \"cpus\": -2.22044604925031e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427310341.47995,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        }\n    ],\n    \"deactivated_slaves\": 0,\n    \"elected_time\": 1427207786.0144,\n    \"failed_tasks\": 0,\n    \"finished_tasks\": 0,\n    \"flags\": {\n        \"allocation_interval\": \"1secs\",\n        \"authenticate\": \"false\",\n        \"authenticate_slaves\": \"false\",\n        \"authenticators\": \"crammd5\",\n        \"framework_sorter\": \"drf\",\n        \"help\": \"false\",\n        \"hostname\": \"10.124.49.90\",\n        \"initialize_driver_logging\": \"true\",\n        \"log_auto_initialize\": \"true\",\n        \"log_dir\": \"/var/log/mesos\",\n        \"logbufsecs\": \"0\",\n        \"logging_level\": \"INFO\",\n        \"port\": \"5050\",\n        \"quiet\": \"false\",\n        \"quorum\": \"2\",\n        \"recovery_slave_removal_limit\": \"100%\",\n        \"registry\": \"replicated_log\",\n        \"registry_fetch_timeout\": \"1mins\",\n        \"registry_store_timeout\": \"5secs\",\n        \"registry_strict\": \"false\",\n        \"root_submissions\": \"true\",\n        \"slave_reregister_timeout\": \"10mins\",\n        \"user_sorter\": \"drf\",\n        \"version\": \"false\",\n        \"webui_dir\": \"/usr/share/mesos/webui\",\n        \"whitelist\": \"*\",\n        \"work_dir\": \"/var/lib/mesos\",\n        \"zk\": \"zk://10.124.48.221:2181,10.124.49.12:2181,10.124.50.67:2181/mesos\",\n        \"zk_session_timeout\": \"10secs\"\n    },\n    \"frameworks\": [\n        {\n            \"active\": true,\n            \"checkpoint\": false,\n            \"completed_tasks\": [],\n            \"failover_timeout\": 1200,\n            \"hostname\": \"ip-10-124-50-210.us-east-1.aws.cloud.in.here.com\",\n            \"id\": \"20150203-224144-2049997834-5050-8713-0000\",\n            \"name\": \"chronos-2.2.0_mesos-0.20.0-SNAPSHOT\",\n            \"offered_resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427207787.01469,\n            \"reregistered_time\": 1427207787.0147,\n            \"resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 0,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"root\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.95f49d05-c9bf-11e4-a1fc-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.a40abda6-ca02-11e4-a1fc-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.3946a287-ca67-11e4-a1fc-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.fec0c74c-ce11-11e4-a1fc-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.33d4007e-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31561-31561]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.359deb0f-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31939-31939]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.50773d6a-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31908-31908]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.638fd9ce-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31658-31658]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.81fd2852-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31160-31160]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.afedb77b-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31185-31185]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.0243c011-cf38-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31554-31554]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.4bdb1099-d1de-11e4-a1fc-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"sdp_shared_jenkins-master.eb8f2863-c9a2-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.shared.sdp\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31458-31458]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.c7865efb-cd05-11e4-a1fc-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.37684ad0-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31223-31223]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.3c2e3752-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31703-31703]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.405b3f34-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31996-31996]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.44886e26-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31141-31141]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.54a4936b-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31109-31109]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.58d1e96c-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31110-31110]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.5d97fcfd-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31167-31167]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.6986f34f-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31158-31158]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.790a33f1-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31696-31696]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.8c2149b3-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31258-31258]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.9c3d47e4-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31308-31308]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.a06a01a6-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31252-31252]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.fa821fbd-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31111-31111]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.fbb39ade-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31658-31658]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.ffe0f0e0-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31022-31022]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.04a68f42-cf38-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31583-31583]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.4ce2cc09-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31449-31449]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.a792e469-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31299-31299]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.fe166a0f-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31383-31383]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.0670c7f3-cf38-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31607-31607]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dev_frontend.3950b432-d234-11e4-bc5e-56847afe9799\",\n                    \"name\": \"frontend.dev.test\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 1024,\n                        \"ports\": \"[31980-31980, 31000-31002]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S21\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427208248.01184\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427208510.81702\n                        }\n                    ]\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.c3a7d253-d241-11e4-bc5e-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31584-31584]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S21\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427214063.25571\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427214249.31952\n                        }\n                    ]\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.d7c6b3c4-d244-11e4-bc5e-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427215390.066\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427215571.78983\n                        }\n                    ]\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dev_frontend.a0f3f185-d2e6-11e4-bc5e-56847afe9799\",\n                    \"name\": \"frontend.dev.test\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 1024,\n                        \"ports\": \"[31980-31980, 31000-31002]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427285021.3087\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427285124.9842\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 604800,\n            \"hostname\": \"ip-10-124-49-90.ec2.internal\",\n            \"id\": \"20150127-110351-1513192458-5050-8587-0000\",\n            \"name\": \"marathon\",\n            \"offered_resources\": {\n                \"cpus\": -2.44249065417534e-15,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427207786.075,\n            \"reregistered_time\": 1427289460.06666,\n            \"resources\": {\n                \"cpus\": 0.299999999999998,\n                \"disk\": 0,\n                \"mem\": 768,\n                \"ports\": \"[31583-31583]\"\n            },\n            \"role\": \"*\",\n            \"tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"sdp_shared_jenkins-master.ed596114-c9a2-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.shared.sdp\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31583-31583]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S21\",\n                    \"state\": \"TASK_RUNNING\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1426266239.30745\n                        }\n                    ]\n                }\n            ],\n            \"unregistered_time\": 0,\n            \"used_resources\": {\n                \"cpus\": 0.3,\n                \"disk\": 0,\n                \"mem\": 768,\n                \"ports\": \"[31583-31583]\"\n            },\n            \"user\": \"root\",\n            \"webui_url\": \"\"\n        }\n    ],\n    \"git_sha\": \"2ae1ba91e64f92ec71d327e10e6ba9e8ad5477e8\",\n    \"git_tag\": \"0.21.1\",\n    \"hostname\": \"10.124.49.90\",\n    \"id\": \"20150225-172748-1513192458-5050-6647\",\n    \"killed_tasks\": 12,\n    \"leader\": \"master@10.124.49.90:5050\",\n    \"log_dir\": \"/var/log/mesos\",\n    \"lost_tasks\": 0,\n    \"orphan_tasks\": [],\n    \"pid\": \"master@10.124.49.90:5050\",\n    \"slaves\": [\n        {\n            \"attributes\": {\n                \"az\": \"us-east-1b\",\n                \"instance_id\": \"i-496a92b3\",\n                \"instance_type\": \"c3.large\"\n            },\n            \"hostname\": \"10.124.49.190\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-S0\",\n            \"pid\": \"slave(1)@10.124.49.190:5051\",\n            \"registered_time\": 1427207786.83581,\n            \"resources\": {\n                \"cpus\": 2,\n                \"disk\": 3966,\n                \"mem\": 2744,\n                \"ports\": \"[31000-32000]\"\n            }\n        },\n        {\n            \"attributes\": {\n                \"az\": \"us-east-1c\",\n                \"instance_id\": \"i-b57fe25a\",\n                \"instance_type\": \"c3.large\"\n            },\n            \"hostname\": \"10.124.50.153\",\n            \"id\": \"20150225-172738-2049997834-5050-23289-S27\",\n            \"pid\": \"slave(1)@10.124.50.153:5051\",\n            \"registered_time\": 1427207786.63308,\n            \"reregistered_time\": 1427207786.63309,\n            \"resources\": {\n                \"cpus\": 2,\n                \"disk\": 3966,\n                \"mem\": 2744,\n                \"ports\": \"[31000-32000]\"\n            }\n        },\n        {\n            \"attributes\": {\n                \"az\": \"us-east-1c\",\n                \"instance_id\": \"i-2467dccb\",\n                \"instance_type\": \"c3.large\"\n            },\n            \"hostname\": \"10.124.50.12\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-S2\",\n            \"pid\": \"slave(1)@10.124.50.12:5051\",\n            \"registered_time\": 1427399742.96888,\n            \"resources\": {\n                \"cpus\": 2,\n                \"disk\": 3966,\n                \"mem\": 2744,\n                \"ports\": \"[31000-32000]\"\n            }\n        },\n        {\n            \"attributes\": {\n                \"az\": \"us-east-1a\",\n                \"instance_id\": \"i-b33a5842\",\n                \"instance_type\": \"c3.large\"\n            },\n            \"hostname\": \"10.124.48.198\",\n            \"id\": \"20150225-172738-2049997834-5050-23289-S25\",\n            \"pid\": \"slave(1)@10.124.48.198:5051\",\n            \"registered_time\": 1427207786.94212,\n            \"reregistered_time\": 1427207786.94213,\n            \"resources\": {\n                \"cpus\": 2,\n                \"disk\": 3966,\n                \"mem\": 2744,\n                \"ports\": \"[31000-32000]\"\n            }\n        },\n        {\n            \"attributes\": {\n                \"az\": \"us-east-1a\",\n                \"instance_id\": \"i-9bdcde6a\",\n                \"instance_type\": \"c3.large\"\n            },\n            \"hostname\": \"10.124.48.147\",\n            \"id\": \"20150225-172738-2049997834-5050-23289-S21\",\n            \"pid\": \"slave(1)@10.124.48.147:5051\",\n            \"registered_time\": 1427207786.33104,\n            \"reregistered_time\": 1427207786.33115,\n            \"resources\": {\n                \"cpus\": 2,\n                \"disk\": 3966,\n                \"mem\": 2744,\n                \"ports\": \"[31000-32000]\"\n            }\n        }\n    ],\n    \"staged_tasks\": 11,\n    \"start_time\": 1424885268.34093,\n    \"started_tasks\": 0,\n    \"unregistered_frameworks\": [\n        \"20150225-172738-2049997834-5050-23289-0433\",\n        \"20150225-172738-2049997834-5050-23289-0433\",\n        \"20150225-172738-2049997834-5050-23289-0433\",\n        \"20150225-172738-2049997834-5050-23289-0433\"\n    ],\n    \"version\": \"0.21.1\"\n}"
  },
  {
    "path": "json-path/src/test/resources/issue_24.json",
    "content": "{\n    \"project\": {\n        \"@key\": \"Signaturengruppe ars.hydr.\",\n        \"template\": [\n            {\n                \"@key\": \"foo\",\n                \"collection\": [\n                    \"Autobiographica\",\n                    \"DigiWunschbuch\",\n                    \"Itineraria\",\n                    \"Manuscriptae\",\n                    \"Maps\",\n                    \"Mathematica\",\n                    \"Nordamericana\",\n                    \"Wissenschaftsgeschichte\",\n                    \"Sibirica\",\n                    \"Varia\",\n                    \"Zoologica\"\n                ]\n            },\n            {\n                \"@key\": \"Digitalisierungsprojekt_ars_hydr\",\n                \"collection\": [\n                    \"Autobiographica\",\n                    \"DigiWunschbuch\",\n                    \"Itineraria\",\n                    \"Manuscriptae\",\n                    \"Maps\",\n                    \"Mathematica\",\n                    \"Nordamericana\",\n                    \"Wissenschaftsgeschichte\",\n                    \"Sibirica\",\n                    \"Varia\",\n                    \"Zoologica\"\n                ]\n            }\n        ],\n        \"field\": [\n            {\n                \"@key\": \"Artist\",\n                \"required\": \"false\",\n                \"source\": \"werk\",\n                \"option\": [\n                    {\n                        \"@label\": \"Nieders?chsische Staats- und Universit?tsbibliothek G?ttingen, Germany\",\n                        \"$\": \"SUB\"\n                    },\n                    {\n                        \"@label\": \"DIGIZEITSCHRIFTEN e.V., Nieders?chsische Staats- und Universit?tsbibliothek G?ttingen, Germany\",\n                        \"$\": \"DIGIZEIT\"\n                    }\n                ],\n                \"ughbinding\": \"false\"\n            },\n            {\n                \"@key\": \"Schrifttyp\",\n                \"required\": \"false\",\n                \"source\": \"werk\",\n                \"option\": [\n                    {\n                        \"@label\": \"gemischt\",\n                        \"$\": \"gemischt\"\n                    },\n                    {\n                        \"@label\": \"Fraktur\",\n                        \"$\": \"Fraktur\"\n                    },\n                    {\n                        \"@label\": \"Antiqua\",\n                        \"$\": \"Antiqua\"\n                    }\n                ],\n                \"ughbinding\": \"false\"\n            },\n            {\n                \"@key\": \"Titel\",\n                \"required\": \"true\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"Titel (Sortierung)\",\n                \"required\": \"true\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"Titel\",\n                \"required\": \"true\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"Titel (Sortierung)\",\n                \"required\": \"true\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"Autoren\",\n                \"required\": \"false\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"ATS\",\n                \"required\": \"false\",\n                \"source\": \"werk\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"TSL\",\n                \"required\": \"false\",\n                \"source\": \"werk\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"PPN analog c-Satz\",\n                \"required\": \"true\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"PPN digital c-Satz\",\n                \"required\": \"true\",\n                \"source\": \"werk\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"PPN analog a-Satz\",\n                \"required\": \"true\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"PPN digital a-Satz\",\n                \"required\": \"true\",\n                \"source\": \"werk\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"PPN analog b-Satz\",\n                \"required\": \"true\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"PPN digital b-Satz\",\n                \"required\": \"true\",\n                \"source\": \"werk\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"ISSN\",\n                \"required\": \"true\",\n                \"source\": \"werk\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"PPN analog Band\",\n                \"required\": \"true\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"firstchild\"\n            },\n            {\n                \"@key\": \"PPN digital Band\",\n                \"required\": \"true\",\n                \"source\": \"werk\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"firstchild\"\n            },\n            {\n                \"@key\": \"Titel (Band)\",\n                \"required\": \"true\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"firstchild\"\n            },\n            {\n                \"@key\": \"Titel (Band) (Sortierung)\",\n                \"required\": \"true\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"firstchild\"\n            },\n            {\n                \"@key\": \"Autoren (Band)\",\n                \"required\": \"false\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"firstchild\"\n            },\n            {\n                \"@key\": \"Bandnummer\",\n                \"required\": \"false\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"firstchild\"\n            },\n            {\n                \"@key\": \"Nummer (Sortierung)\",\n                \"required\": \"false\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"firstchild\"\n            },\n            {\n                \"@key\": \"Nummer (Benennung)\",\n                \"required\": \"true\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"false\"\n            },\n            {\n                \"@key\": \"PPN analog f-Satz\",\n                \"required\": \"true\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"firstchild\"\n            },\n            {\n                \"@key\": \"PPN digital f-Satz\",\n                \"required\": \"true\",\n                \"source\": \"werk\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"firstchild\"\n            },\n            {\n                \"@key\": \"Erscheinungsort\",\n                \"required\": \"false\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"Erscheinungsjahr\",\n                \"required\": \"false\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"Erscheinungsjahr\",\n                \"required\": \"false\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"firstchild\"\n            },\n            {\n                \"@key\": \"Verlag\",\n                \"required\": \"false\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"firstchild\"\n            },\n            {\n                \"@key\": \"Verlag\",\n                \"required\": \"false\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"topstruct\"\n            },\n            {\n                \"@key\": \"Signatur\",\n                \"required\": \"false\",\n                \"source\": \"vorlage\",\n                \"ughbinding\": \"true\",\n                \"insertionLevel\": \"boundbook\"\n            },\n            {\n                \"@key\": \"Farbtiefe\",\n                \"required\": \"true\",\n                \"source\": \"werk\",\n                \"option\": [\n                    {\n                        \"@label\": \"Bitonal\",\n                        \"$\": \"Bitonal\"\n                    },\n                    {\n                        \"@label\": \"Farbe\",\n                        \"$\": \"Farbe\"\n                    },\n                    {\n                        \"@label\": \"Graustufen\",\n                        \"$\": \"Graustufen\"\n                    }\n                ],\n                \"ughbinding\": \"false\"\n            },\n            {\n                \"@key\": \"?ffnungswinkel\",\n                \"required\": \"true\",\n                \"source\": \"werk\",\n                \"option\": [\n                    {\n                        \"@label\": \"180?\",\n                        \"$\": \"180?\"\n                    },\n                    {\n                        \"@label\": \"90?\",\n                        \"$\": \"90?\"\n                    }\n                ],\n                \"ughbinding\": \"false\"\n            }\n        ]\n    }\n}"
  },
  {
    "path": "json-path/src/test/resources/issue_76.json",
    "content": "{\n    \"activated_slaves\": 5,\n    \"build_date\": \"2015-01-09 02:25:21\",\n    \"build_time\": 1420770321,\n    \"build_user\": \"root\",\n    \"completed_frameworks\": [\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172738-2049997834-5050-23289-0433\",\n                    \"id\": \"mesos-jenkins-172c6f74-12bc-44fe-849a-ad902ddc2b64\",\n                    \"name\": \"task mesos-jenkins-172c6f74-12bc-44fe-849a-ad902ddc2b64\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427206149.38254\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427207981.47819\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172738-2049997834-5050-23289-0433\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": -2.22044604925031e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427207787.01579,\n            \"reregistered_time\": 1427207787.0158,\n            \"resources\": {\n                \"cpus\": -2.22044604925031e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427207981.47898,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0000\",\n                    \"id\": \"mesos-jenkins-cd18b433-e2ee-4a4e-875b-6ea82d90a53a\",\n                    \"name\": \"task mesos-jenkins-cd18b433-e2ee-4a4e-875b-6ea82d90a53a\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172748-1513192458-5050-6647-S0\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427209005.01389\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427209961.51519\n                        }\n                    ]\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0000\",\n                    \"id\": \"mesos-jenkins-66fca7c0-88f7-4a1a-9796-a6de2e337b0a\",\n                    \"name\": \"task mesos-jenkins-66fca7c0-88f7-4a1a-9796-a6de2e337b0a\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427209025.84128\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427211101.4792\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-0000\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427208985.06716,\n            \"resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427211101.48013,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0001\",\n                    \"id\": \"mesos-jenkins-258ad47c-85bf-4fe0-b7c4-4f0cc70f2998\",\n                    \"name\": \"task mesos-jenkins-258ad47c-85bf-4fe0-b7c4-4f0cc70f2998\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427211139.85003\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427212121.47896\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-0001\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": 2.22044604925031e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427211125.06385,\n            \"resources\": {\n                \"cpus\": 2.22044604925031e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427212121.4797,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0002\",\n                    \"id\": \"mesos-jenkins-f30e5e34-2ef6-4993-9260-73ee3520c0a5\",\n                    \"name\": \"task mesos-jenkins-f30e5e34-2ef6-4993-9260-73ee3520c0a5\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427213316.78467\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427214401.47958\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-0002\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427213305.0687,\n            \"resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427214401.48033,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0003\",\n                    \"id\": \"mesos-jenkins-1fc0bbd8-f0ff-48cd-a7f7-24a9436ba6bc\",\n                    \"name\": \"task mesos-jenkins-1fc0bbd8-f0ff-48cd-a7f7-24a9436ba6bc\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427215879.15661\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427217701.47961\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-0003\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427215868.06173,\n            \"resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427217701.48035,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0004\",\n                    \"id\": \"mesos-jenkins-62b44026-843d-4813-a6a8-e95215250bb1\",\n                    \"name\": \"task mesos-jenkins-62b44026-843d-4813-a6a8-e95215250bb1\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427222969.79605\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427223941.48583\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-0004\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427222958.07464,\n            \"resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427223941.48665,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150225-172748-1513192458-5050-6647-0005\",\n                    \"id\": \"mesos-jenkins-807b9b8a-3283-4e78-94e1-9dc17df4df77\",\n                    \"name\": \"task mesos-jenkins-807b9b8a-3283-4e78-94e1-9dc17df4df77\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 704\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427309356.80847\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427310341.47914\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 0,\n            \"hostname\": \"ip-10-124-48-147.ec2.internal\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-0005\",\n            \"name\": \"Jenkins Scheduler\",\n            \"offered_resources\": {\n                \"cpus\": -2.22044604925031e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427309345.18029,\n            \"resources\": {\n                \"cpus\": -2.22044604925031e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 1427310341.47995,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"jenkins\",\n            \"webui_url\": \"\"\n        }\n    ],\n    \"deactivated_slaves\": 0,\n    \"elected_time\": 1427207786.0144,\n    \"failed_tasks\": 0,\n    \"finished_tasks\": 0,\n    \"flags\": {\n        \"allocation_interval\": \"1secs\",\n        \"authenticate\": \"false\",\n        \"authenticate_slaves\": \"false\",\n        \"authenticators\": \"crammd5\",\n        \"framework_sorter\": \"drf\",\n        \"help\": \"false\",\n        \"hostname\": \"10.124.49.90\",\n        \"initialize_driver_logging\": \"true\",\n        \"log_auto_initialize\": \"true\",\n        \"log_dir\": \"/var/log/mesos\",\n        \"logbufsecs\": \"0\",\n        \"logging_level\": \"INFO\",\n        \"port\": \"5050\",\n        \"quiet\": \"false\",\n        \"quorum\": \"2\",\n        \"recovery_slave_removal_limit\": \"100%\",\n        \"registry\": \"replicated_log\",\n        \"registry_fetch_timeout\": \"1mins\",\n        \"registry_store_timeout\": \"5secs\",\n        \"registry_strict\": \"false\",\n        \"root_submissions\": \"true\",\n        \"slave_reregister_timeout\": \"10mins\",\n        \"user_sorter\": \"drf\",\n        \"version\": \"false\",\n        \"webui_dir\": \"/usr/share/mesos/webui\",\n        \"whitelist\": \"*\",\n        \"work_dir\": \"/var/lib/mesos\",\n        \"zk\": \"zk://10.124.48.221:2181,10.124.49.12:2181,10.124.50.67:2181/mesos\",\n        \"zk_session_timeout\": \"10secs\"\n    },\n    \"frameworks\": [\n        {\n            \"active\": true,\n            \"checkpoint\": false,\n            \"completed_tasks\": [],\n            \"failover_timeout\": 1200,\n            \"hostname\": \"ip-10-124-50-210.us-east-1.aws.cloud.in.here.com\",\n            \"id\": \"20150203-224144-2049997834-5050-8713-0000\",\n            \"name\": \"chronos-2.2.0_mesos-0.20.0-SNAPSHOT\",\n            \"offered_resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427207787.01469,\n            \"reregistered_time\": 1427207787.0147,\n            \"resources\": {\n                \"cpus\": -8.88178419700125e-16,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"role\": \"*\",\n            \"tasks\": [],\n            \"unregistered_time\": 0,\n            \"used_resources\": {\n                \"cpus\": 0,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"user\": \"root\",\n            \"webui_url\": \"\"\n        },\n        {\n            \"active\": true,\n            \"checkpoint\": true,\n            \"completed_tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.95f49d05-c9bf-11e4-a1fc-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.a40abda6-ca02-11e4-a1fc-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.3946a287-ca67-11e4-a1fc-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.fec0c74c-ce11-11e4-a1fc-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.33d4007e-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31561-31561]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.359deb0f-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31939-31939]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.50773d6a-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31908-31908]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.638fd9ce-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31658-31658]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.81fd2852-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31160-31160]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.afedb77b-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31185-31185]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.0243c011-cf38-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31554-31554]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.4bdb1099-d1de-11e4-a1fc-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S19\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"sdp_shared_jenkins-master.eb8f2863-c9a2-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.shared.sdp\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31458-31458]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.c7865efb-cd05-11e4-a1fc-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.37684ad0-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31223-31223]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.3c2e3752-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31703-31703]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.405b3f34-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31996-31996]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.44886e26-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31141-31141]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.54a4936b-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31109-31109]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.58d1e96c-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31110-31110]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.5d97fcfd-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31167-31167]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.6986f34f-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31158-31158]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.790a33f1-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31696-31696]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.8c2149b3-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31258-31258]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.9c3d47e4-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31308-31308]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.a06a01a6-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31252-31252]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.fa821fbd-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31111-31111]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.fbb39ade-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31658-31658]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.ffe0f0e0-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31022-31022]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.04a68f42-cf38-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31583-31583]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.4ce2cc09-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31449-31449]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.a792e469-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31299-31299]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.fe166a0f-cf37-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31383-31383]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_jenkins-master.0670c7f3-cf38-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.test\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31607-31607]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_FAILED\",\n                    \"statuses\": []\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dev_frontend.3950b432-d234-11e4-bc5e-56847afe9799\",\n                    \"name\": \"frontend.dev.test\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 1024,\n                        \"ports\": \"[31980-31980, 31000-31002]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S21\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427208248.01184\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427208510.81702\n                        }\n                    ]\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.c3a7d253-d241-11e4-bc5e-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31584-31584]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S21\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427214063.25571\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427214249.31952\n                        }\n                    ]\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dv_helloworld.d7c6b3c4-d244-11e4-bc5e-56847afe9799\",\n                    \"name\": \"helloworld.dv.test\",\n                    \"resources\": {\n                        \"cpus\": 0.1,\n                        \"disk\": 0,\n                        \"mem\": 32,\n                        \"ports\": \"[31000-31000]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S27\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427215390.066\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427215571.78983\n                        }\n                    ]\n                },\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"test_dev_frontend.a0f3f185-d2e6-11e4-bc5e-56847afe9799\",\n                    \"name\": \"frontend.dev.test\",\n                    \"resources\": {\n                        \"cpus\": 0.2,\n                        \"disk\": 0,\n                        \"mem\": 1024,\n                        \"ports\": \"[31980-31980, 31000-31002]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S25\",\n                    \"state\": \"TASK_KILLED\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1427285021.3087\n                        },\n                        {\n                            \"state\": \"TASK_KILLED\",\n                            \"timestamp\": 1427285124.9842\n                        }\n                    ]\n                }\n            ],\n            \"failover_timeout\": 604800,\n            \"hostname\": \"ip-10-124-49-90.ec2.internal\",\n            \"id\": \"20150127-110351-1513192458-5050-8587-0000\",\n            \"name\": \"marathon\",\n            \"offered_resources\": {\n                \"cpus\": -2.44249065417534e-15,\n                \"disk\": 0,\n                \"mem\": 0\n            },\n            \"offers\": [],\n            \"registered_time\": 1427207786.075,\n            \"reregistered_time\": 1427289460.06666,\n            \"resources\": {\n                \"cpus\": 0.299999999999998,\n                \"disk\": 0,\n                \"mem\": 768,\n                \"ports\": \"[31583-31583]\"\n            },\n            \"role\": \"*\",\n            \"tasks\": [\n                {\n                    \"executor_id\": \"\",\n                    \"framework_id\": \"20150127-110351-1513192458-5050-8587-0000\",\n                    \"id\": \"sdp_shared_jenkins-master.ed596114-c9a2-11e4-a1fc-56847afe9799\",\n                    \"name\": \"jenkins-master.shared.sdp\",\n                    \"resources\": {\n                        \"cpus\": 0.3,\n                        \"disk\": 0,\n                        \"mem\": 768,\n                        \"ports\": \"[31583-31583]\"\n                    },\n                    \"slave_id\": \"20150225-172738-2049997834-5050-23289-S21\",\n                    \"state\": \"TASK_RUNNING\",\n                    \"statuses\": [\n                        {\n                            \"state\": \"TASK_RUNNING\",\n                            \"timestamp\": 1426266239.30745\n                        }\n                    ]\n                }\n            ],\n            \"unregistered_time\": 0,\n            \"used_resources\": {\n                \"cpus\": 0.3,\n                \"disk\": 0,\n                \"mem\": 768,\n                \"ports\": \"[31583-31583]\"\n            },\n            \"user\": \"root\",\n            \"webui_url\": \"\"\n        }\n    ],\n    \"git_sha\": \"2ae1ba91e64f92ec71d327e10e6ba9e8ad5477e8\",\n    \"git_tag\": \"0.21.1\",\n    \"hostname\": \"10.124.49.90\",\n    \"id\": \"20150225-172748-1513192458-5050-6647\",\n    \"killed_tasks\": 12,\n    \"leader\": \"master@10.124.49.90:5050\",\n    \"log_dir\": \"/var/log/mesos\",\n    \"lost_tasks\": 0,\n    \"orphan_tasks\": [],\n    \"pid\": \"master@10.124.49.90:5050\",\n    \"slaves\": [\n        {\n            \"attributes\": {\n                \"az\": \"us-east-1b\",\n                \"instance_id\": \"i-496a92b3\",\n                \"instance_type\": \"c3.large\"\n            },\n            \"hostname\": \"10.124.49.190\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-S0\",\n            \"pid\": \"slave(1)@10.124.49.190:5051\",\n            \"registered_time\": 1427207786.83581,\n            \"resources\": {\n                \"cpus\": 2,\n                \"disk\": 3966,\n                \"mem\": 2744,\n                \"ports\": \"[31000-32000]\"\n            }\n        },\n        {\n            \"attributes\": {\n                \"az\": \"us-east-1c\",\n                \"instance_id\": \"i-b57fe25a\",\n                \"instance_type\": \"c3.large\"\n            },\n            \"hostname\": \"10.124.50.153\",\n            \"id\": \"20150225-172738-2049997834-5050-23289-S27\",\n            \"pid\": \"slave(1)@10.124.50.153:5051\",\n            \"registered_time\": 1427207786.63308,\n            \"reregistered_time\": 1427207786.63309,\n            \"resources\": {\n                \"cpus\": 2,\n                \"disk\": 3966,\n                \"mem\": 2744,\n                \"ports\": \"[31000-32000]\"\n            }\n        },\n        {\n            \"attributes\": {\n                \"az\": \"us-east-1c\",\n                \"instance_id\": \"i-2467dccb\",\n                \"instance_type\": \"c3.large\"\n            },\n            \"hostname\": \"10.124.50.12\",\n            \"id\": \"20150225-172748-1513192458-5050-6647-S2\",\n            \"pid\": \"slave(1)@10.124.50.12:5051\",\n            \"registered_time\": 1427399742.96888,\n            \"resources\": {\n                \"cpus\": 2,\n                \"disk\": 3966,\n                \"mem\": 2744,\n                \"ports\": \"[31000-32000]\"\n            }\n        },\n        {\n            \"attributes\": {\n                \"az\": \"us-east-1a\",\n                \"instance_id\": \"i-b33a5842\",\n                \"instance_type\": \"c3.large\"\n            },\n            \"hostname\": \"10.124.48.198\",\n            \"id\": \"20150225-172738-2049997834-5050-23289-S25\",\n            \"pid\": \"slave(1)@10.124.48.198:5051\",\n            \"registered_time\": 1427207786.94212,\n            \"reregistered_time\": 1427207786.94213,\n            \"resources\": {\n                \"cpus\": 2,\n                \"disk\": 3966,\n                \"mem\": 2744,\n                \"ports\": \"[31000-32000]\"\n            }\n        },\n        {\n            \"attributes\": {\n                \"az\": \"us-east-1a\",\n                \"instance_id\": \"i-9bdcde6a\",\n                \"instance_type\": \"c3.large\"\n            },\n            \"hostname\": \"10.124.48.147\",\n            \"id\": \"20150225-172738-2049997834-5050-23289-S21\",\n            \"pid\": \"slave(1)@10.124.48.147:5051\",\n            \"registered_time\": 1427207786.33104,\n            \"reregistered_time\": 1427207786.33115,\n            \"resources\": {\n                \"cpus\": 2,\n                \"disk\": 3966,\n                \"mem\": 2744,\n                \"ports\": \"[31000-32000]\"\n            }\n        }\n    ],\n    \"staged_tasks\": 11,\n    \"start_time\": 1424885268.34093,\n    \"started_tasks\": 0,\n    \"unregistered_frameworks\": [\n        \"20150225-172738-2049997834-5050-23289-0433\",\n        \"20150225-172738-2049997834-5050-23289-0433\",\n        \"20150225-172738-2049997834-5050-23289-0433\",\n        \"20150225-172738-2049997834-5050-23289-0433\"\n    ],\n    \"version\": \"0.21.1\"\n}"
  },
  {
    "path": "json-path/src/test/resources/issue_76_2.json",
    "content": "{\n    \"cpus\": -8.88178419700125e-16,\n    \"disk\": 0,\n    \"mem\": 0\n}\n"
  },
  {
    "path": "json-path/src/test/resources/json-test-doc.json",
    "content": "{\n    \"id\": 100,\n    \"type\": \"donut\",\n    \"name\": \"Cake\",\n    \"available\": true,\n    \"ppu\": 0.55,\n    \"batters\":\n    {\n        \"batter\":\n                [\n                    {\n                        \"id\": \"1001\",\n                        \"type\": \"Regular\"\n                    },\n                    {\n                        \"id\": \"1002\",\n                        \"type\": \"Chocolate\"\n                    },\n                    {\n                        \"id\": \"1003\",\n                        \"type\": \"Blueberry\"\n                    },\n                    {\n                        \"id\": \"1004\",\n                        \"type\": \"Devil's Food\"\n                    }\n                ]\n    },\n    \"toppings\": [\"Glazed\", \"Sugar\", \"Chocolate\", \"Maple\"]\n}"
  },
  {
    "path": "json-path/src/test/resources/json_array.json",
    "content": "\n\n\n{\n    \"arr\": [\n        {\n            \"obj\":{\"innerArr\": [\n                {\n                    \"val\": \"bla_0\"\n                },\n                {\n                    \"val\": null\n                }\n            ]}\n        },\n        {\n            \"obj\":{\"innerArr\": [\n                {\n                    \"val\": \"bla_4\"\n                },\n                {\n                    \"val\": \"bla_5\"\n                }\n            ]}\n        }\n    ]\n}"
  },
  {
    "path": "json-path/src/test/resources/json_array_multiple_delete.json",
    "content": "{\n  \"_embedded\": {\n    \"mandates\": [\n      {\n        \"count\": \"0\",\n        \"difference\": \"+0\"\n      },\n      {\n        \"count\": \"0\",\n        \"difference\": \"+0\"\n      },\n      {\n        \"count\": \"0\",\n        \"difference\": \"+0\"\n      },\n      {\n        \"count\": \"0\",\n        \"difference\": \"+0\"\n      },\n      {\n        \"count\": \"0\",\n        \"difference\": \"+0\"\n      },\n      {\n        \"count\": \"10\",\n        \"difference\": \"+0\"\n      },\n      {\n        \"count\": \"34\",\n        \"difference\": \"+0\"\n      },\n      {\n        \"count\": \"2\",\n        \"difference\": \"+0\"\n      },\n      {\n        \"count\": \"4\",\n        \"difference\": \"+0\"\n      },\n      {\n        \"count\": \"0\",\n        \"difference\": \"+0\"\n      },\n      {\n        \"count\": \"0\",\n        \"difference\": \"+0\"\n      },\n      {\n        \"count\": \"0\",\n        \"difference\": \"+0\"\n      }\n    ]\n  }\n}"
  },
  {
    "path": "json-path/src/test/resources/keyset.json",
    "content": "{\n  \"data\" : {\n    \"a\" : \"a\",\n    \"b\" : \"b\"\n  }\n}"
  },
  {
    "path": "json-path/src/test/resources/simplelogger.properties",
    "content": "#org.slf4j.simpleLogger.log.com.jayway=debug\n#org.slf4j.simpleLogger.log.com.jayway.jsonpath.internal.filter=trace\n#org.slf4j.simpleLogger.log.com.jayway.jsonpath.internal.path.ScanPathToken=trace\n\n\n"
  },
  {
    "path": "json-path-assert/README.md",
    "content": "json-path-assert\n================\n\nA library with [hamcrest-matchers](http://hamcrest.org/JavaHamcrest/) for JsonPath.\n\n# Getting started\n\nThis library is available at the Central Maven Repository. Maven users add this to your POM.\n\n```xml\n<dependency>\n    <groupId>com.jayway.jsonpath</groupId>\n    <artifactId>json-path-assert</artifactId>\n    <version>2.6.0</version>\n</dependency>\n```\n\n# Usage guide\n\nStatically import the library entry point:\n\n    import static com.jayway.jsonpath.matchers.JsonPathMatchers.*;\n\nNOTE: The actual evaluation of JsonPath will depend on the current configuration:\n\n    Configuration.setDefaults(...);\n\nThe matchers can be used to inspect different representations of JSON:\n\n    // As a String...\n    String json = ...;\n    \n    // or a file...\n    File json = ...;\n    \n    // or an already parsed json object...\n    Object json = Configuration.defaultConfiguration().jsonProvider().parse(content);\n    \nUsage examples:\n    \n    // Verify validity of JSON\n    assertThat(json, isJson());\n\n    // Verify existence (or non-existence) of JSON path\n    assertThat(json, hasJsonPath(\"$.message\"));\n    assertThat(json, hasNoJsonPath(\"$.message\"));\n\n    // Verify evaluation of JSON path\n    assertThat(json, hasJsonPath(\"$.message\", equalTo(\"Hi there\")));\n    assertThat(json, hasJsonPath(\"$.quantity\", equalTo(5)));\n    assertThat(json, hasJsonPath(\"$.price\", equalTo(34.56)));\n    assertThat(json, hasJsonPath(\"$.store.book[*].author\", hasSize(4)));\n    assertThat(json, hasJsonPath(\"$.store.book[*].author\", hasItem(\"Evelyn Waugh\")));\n\nCombine matchers for greater expressiveness\n    \n    // This will separate the JSON parsing from the path evaluation\n    assertThat(json, isJson(withoutJsonPath(\"...\")));\n    assertThat(json, isJson(withJsonPath(\"...\", equalTo(3))));    \n    \n    // Combine several JSON path evaluations into a single statement\n    // (This will parse the JSON only once)\n    assertThat(json, isJson(allOf(\n        withJsonPath(\"$.store.name\", equalTo(\"Little Shop\")),\n        withoutJsonPath(\"$.expensive\"),\n        withJsonPath(\"$..title\", hasSize(4)))));\n\nMatch on pre-compiled complex JSON path expressions\n\n    Filter cheapFictionFilter = filter(\n        where(\"category\").is(\"fiction\").and(\"price\").lte(10D));\n    JsonPath cheapFiction = JsonPath.compile(\"$.store.book[?]\", cheapFictionFilter);\n    String json = ...;\n    assertThat(json, isJson(withJsonPath(cheapFiction)));\n        \nUse typed matchers for specific JSON representations, if needed\n\n    String json = ...\n    assertThat(json, isJsonString(withJsonPath(\"$..author\")));\n\n    File json = ...\n    assertThat(json, isJsonFile(withJsonPath(\"$..author\")));\n\n---\n\n### Regarding the use of indefinite paths\n\nWhen using indefinite path expressions (e.g with wildcards '*'), the result will yield a list. Possibly an _empty_ list if no matching entries were found. If you want to assert that the list will actually contain something, make sure to express this explicitly, e.g checking for the size of the list.\n\n    // Given a JSON like this:\n    {\n      \"items\": []\n    }\n\n    // Both of these statements will succeed(!)\n    assertThat(json, hasJsonPath(\"$.items[*]\"));\n    assertThat(json, hasJsonPath(\"$.items[*].name\"));\n    \n    // Make sure to explicitly check for size if you want to catch this scenario as a failure\n    assertThat(json, hasJsonPath(\"$.items[*]\", hasSize(greaterThan(0))));\n    \n    // However, checking for the existence of an array works fine, as is\n    assertThat(json, hasJsonPath(\"$.not_here[*]\"));\n\n---\n\n### Regarding the use of null in JSON\n\n'null' is a valid JSON value. If such a value exist, the path is still considered to be a valid path.\n\n    // Given a JSON like this:\n    { \"none\": null }\n    \n    // All of these will succeed, since '$.none' is a valid path\n    assertThat(json, hasJsonPath(\"$.none\"));\n    assertThat(json, isJson(withJsonPath(\"$.none\")));\n    assertThat(json, hasJsonPath(\"$.none\", nullValue()));\n    assertThat(json, isJson(withJsonPath(\"$.none\", nullValue())));\n    \n    // But all of these will fail, since '$.not_there' is not a valid path\n    assertThat(json, hasJsonPath(\"$.not_there\"));\n    assertThat(json, isJson(withJsonPath(\"$.not_there\")));\n    assertThat(json, hasJsonPath(\"$.not_there\", anything()));\n    assertThat(json, isJson(withJsonPath(\"$.not_there\", anything())));\n\n"
  },
  {
    "path": "json-path-assert/build.gradle",
    "content": "description = \"Assertions on Json using JsonPath\"\n\njar {\n    bnd(\n            'Implementation-Title': 'json-path-assert', 'Implementation-Version': archiveVersion\n    )\n}\n\ndependencies {\n    implementation project(':json-path')\n    implementation libs.hamcrest\n    implementation libs.slf4jApi\n\n    testImplementation libs.jsonSmart\n    testImplementation libs.test\n}\n"
  },
  {
    "path": "json-path-assert/src/main/java/com/jayway/jsonassert/JsonAssert.java",
    "content": "package com.jayway.jsonassert;\n\n\nimport com.jayway.jsonassert.impl.JsonAsserterImpl;\nimport com.jayway.jsonassert.impl.matcher.CollectionMatcher;\nimport com.jayway.jsonassert.impl.matcher.IsCollectionWithSize;\nimport com.jayway.jsonassert.impl.matcher.IsEmptyCollection;\nimport com.jayway.jsonassert.impl.matcher.IsMapContainingKey;\nimport com.jayway.jsonassert.impl.matcher.IsMapContainingValue;\nimport com.jayway.jsonpath.JsonPath;\nimport org.hamcrest.Matcher;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.Reader;\nimport java.io.StringWriter;\nimport java.io.Writer;\nimport java.text.ParseException;\nimport java.util.Collection;\nimport java.util.Map;\n\npublic class JsonAssert {\n\n    /**\n     * Creates a JSONAsserter\n     *\n     * @param json the JSON document to create a JSONAsserter for\n     * @return a JSON asserter initialized with the provided document\n     * @throws ParseException when the given JSON could not be parsed\n     */\n    public static JsonAsserter with(String json) {\n        return new JsonAsserterImpl(JsonPath.parse(json).json());\n    }\n\n    /**\n     * Creates a JSONAsserter\n     *\n     * @param reader the reader of the json document\n     * @return a JSON asserter initialized with the provided document\n     * @throws ParseException when the given JSON could not be parsed\n     */\n    public static JsonAsserter with(Reader reader) throws IOException {\n        return new JsonAsserterImpl(JsonPath.parse(convertReaderToString(reader)).json());\n\n    }\n\n    /**\n     * Creates a JSONAsserter\n     *\n     * @param is the input stream\n     * @return a JSON asserter initialized with the provided document\n     * @throws ParseException when the given JSON could not be parsed\n     */\n    public static JsonAsserter with(InputStream is) throws IOException {\n        Reader reader = new InputStreamReader(is);\n        return with(reader);\n    }\n\n    //Matchers\n\n    public static CollectionMatcher collectionWithSize(Matcher<? super Integer> sizeMatcher) {\n        return new IsCollectionWithSize(sizeMatcher);\n    }\n\n    public static Matcher<Map<String, ?>> mapContainingKey(Matcher<String> keyMatcher) {\n        return new IsMapContainingKey(keyMatcher);\n    }\n\n    public static <V> Matcher<? super Map<?, V>> mapContainingValue(Matcher<? super V> valueMatcher) {\n        return new IsMapContainingValue<V>(valueMatcher);\n    }\n\n    public static Matcher<Collection<Object>> emptyCollection() {\n        return new IsEmptyCollection<Object>();\n    }\n\n    private static String convertReaderToString(Reader reader)\n            throws IOException {\n\n        if (reader != null) {\n            Writer writer = new StringWriter();\n\n            char[] buffer = new char[1024];\n            try {\n                int n;\n                while ((n = reader.read(buffer)) != -1) {\n                    writer.write(buffer, 0, n);\n                }\n            } finally {\n                reader.close();\n            }\n            return writer.toString();\n        } else {\n            return \"\";\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "json-path-assert/src/main/java/com/jayway/jsonassert/JsonAsserter.java",
    "content": "package com.jayway.jsonassert;\n\nimport org.hamcrest.Matcher;\n\npublic interface JsonAsserter {\n\n    /**\n     * Asserts that object specified by path satisfies the condition specified by matcher.\n     * If not, an AssertionError is thrown with information about the matcher\n     * and failing value. Example:\n     * <p/>\n     * <code>\n     * with(json).assertThat(\"items[0].name\", equalTo(\"Bobby\"))\n     * .assertThat(\"items[0].age\" , equalTo(24L))\n     * </code>\n     *\n     * @param path    the json path specifying the value being compared\n     * @param matcher an expression, built of Matchers, specifying allowed values\n     * @param <T>     the static type accepted by the matcher\n     * @return this to allow fluent assertion chains\n     */\n    <T> JsonAsserter assertThat(String path, Matcher<T> matcher);\n\n    /**\n     * @param path    the json path specifying the value being compared\n     * @param matcher an expression, built of Matchers, specifying allowed values\n     * @param message the explanation message\n     * @param <T>     the static type that should be returned by the path\n     * @return this to allow fluent assertion chains\n     */\n    <T> JsonAsserter assertThat(String path, Matcher<T> matcher, String message);\n\n    /**\n     * Asserts that object specified by path is equal to the expected value.\n     * If they are not, an AssertionError is thrown with the given message.\n     *\n     * @param path     the json path specifying the value being compared\n     * @param expected the expected value\n     * @param <T>      the static type that should be returned by the path\n     * @return this to allow fluent assertion chains\n     */\n    <T> JsonAsserter assertEquals(String path, T expected);\n\n    <T> JsonAsserter assertEquals(String path, T expected, String message);\n\n    /**\n     * Checks that a path is not defined within a document. If the document contains the\n     * given path, an AssertionError is thrown\n     *\n     * @param path the path to make sure not exists\n     * @return this\n     */\n    JsonAsserter assertNotDefined(String path);\n\n    JsonAsserter assertNotDefined(String path, String message);\n\n\n    /**\n     * Asserts that object specified by path is null. If it is not, an AssertionError\n     * is thrown with the given message.\n     *\n     * @param path the json path specifying the value that should be null\n     * @return this to allow fluent assertion chains\n     */\n    JsonAsserter assertNull(String path);\n    JsonAsserter assertNull(String path, String message);\n\n    /**\n     * Asserts that object specified by path is NOT null. If it is, an AssertionError\n     * is thrown with the given message.\n     *\n     * @param path the json path specifying the value that should be NOT null\n     * @return this to allow fluent assertion chains\n     */\n    <T> JsonAsserter assertNotNull(String path);\n\n    <T> JsonAsserter assertNotNull(String path, String message);\n\n    /**\n     * Syntactic sugar to allow chaining assertions with a separating and() statement\n     * <p/>\n     * <p/>\n     * <code>\n     * with(json).assertThat(\"firstName\", is(equalTo(\"Bobby\"))).and().assertThat(\"lastName\", is(equalTo(\"Ewing\")))\n     * </code>\n     *\n     * @return this to allow fluent assertion chains\n     */\n    JsonAsserter and();\n}\n"
  },
  {
    "path": "json-path-assert/src/main/java/com/jayway/jsonassert/impl/JsonAsserterImpl.java",
    "content": "package com.jayway.jsonassert.impl;\n\n\nimport com.jayway.jsonassert.JsonAsserter;\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.JsonPath;\nimport com.jayway.jsonpath.PathNotFoundException;\nimport org.hamcrest.Matcher;\n\nimport static java.lang.String.format;\nimport static org.hamcrest.Matchers.*;\n\npublic class JsonAsserterImpl implements JsonAsserter {\n\n    private final Object jsonObject;\n\n    /**\n     * Instantiates a new JSONAsserter\n     *\n     * @param jsonObject the object to make asserts on\n     */\n    public JsonAsserterImpl(Object jsonObject) {\n        this.jsonObject = jsonObject;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @SuppressWarnings(\"unchecked\")\n    public <T> JsonAsserter assertThat(String path, Matcher<T> matcher) {\n        T obj = null;\n        \n        try {\n            obj = JsonPath.<T>read(jsonObject, path);\n        } catch (Exception e) {\n            final AssertionError assertionError = new AssertionError(String.format(\"Error reading JSON path [%s]\", path));\n            assertionError.initCause(e);\n            throw assertionError;\n        }\n\n        if (!matcher.matches(obj)) {\n\n            throw new AssertionError(String.format(\"JSON path [%s] doesn't match.\\nExpected:\\n%s\\nActual:\\n%s\", path, matcher.toString(), obj));\n        }\n        return this;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @SuppressWarnings(\"unchecked\")\n    public <T> JsonAsserter assertThat(String path, Matcher<T> matcher, String message) {\n        T obj = JsonPath.<T>read(jsonObject, path);\n        if (!matcher.matches(obj)) {\n            throw new AssertionError(String.format(\"JSON Assert Error: %s\\nExpected:\\n%s\\nActual:\\n%s\", message, matcher.toString(), obj));\n        }\n        return this;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public <T> JsonAsserter assertEquals(String path, T expected) {\n        return assertThat(path, equalTo(expected));\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public JsonAsserter assertNotDefined(String path) {\n\n        try {\n            Configuration c = Configuration.defaultConfiguration();\n\n            JsonPath.using(c).parse(jsonObject).read(path);\n            throw new AssertionError(format(\"Document contains the path <%s> but was expected not to.\", path));\n        } catch (PathNotFoundException e) {\n        }\n        return this;\n    }\n\n    @Override\n    public JsonAsserter assertNotDefined(String path, String message) {\n        try {\n            Configuration c = Configuration.defaultConfiguration();\n\n            JsonPath.using(c).parse(jsonObject).read(path);\n\n            throw new AssertionError(format(\"Document contains the path <%s> but was expected not to.\", path));\n        } catch (PathNotFoundException e) {\n        }\n        return this;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public JsonAsserter assertNull(String path) {\n        return assertThat(path, nullValue());\n    }\n\n    @Override\n    public JsonAsserter assertNull(String path, String message) {\n        return assertThat(path, nullValue(), message);\n    }\n\n    @Override\n    public <T> JsonAsserter assertEquals(String path, T expected, String message) {\n        return assertThat(path, equalTo(expected),message);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public <T> JsonAsserter assertNotNull(String path) {\n        return assertThat(path, notNullValue());\n    }\n\n    @Override\n    public <T> JsonAsserter assertNotNull(String path, String message) {\n        return assertThat(path, notNullValue(), message);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public JsonAsserter and() {\n        return this;\n    }\n\n}\n"
  },
  {
    "path": "json-path-assert/src/main/java/com/jayway/jsonassert/impl/matcher/CollectionMatcher.java",
    "content": "/*\nBSD License\n\nCopyright (c) 2000-2006, www.hamcrest.org\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this list of\nconditions and the following disclaimer. Redistributions in binary form must reproduce\nthe above copyright notice, this list of conditions and the following disclaimer in\nthe documentation and/or other materials provided with the distribution.\n\nNeither the name of Hamcrest nor the names of its contributors may be used to endorse\nor promote products derived from this software without specific prior written\npermission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY\nWAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n*/\npackage com.jayway.jsonassert.impl.matcher;\n\nimport org.hamcrest.BaseMatcher;\n\nimport java.util.Collection;\n\npublic abstract class CollectionMatcher<C extends Collection<?>> extends BaseMatcher<C> {\n    @SuppressWarnings(\"unchecked\")\n    public boolean matches(Object item) {\n        if (!(item instanceof Collection)) {\n            return false;\n        }\n        return matchesSafely((C)item);\n    }\n\n    protected abstract boolean matchesSafely(C collection);\n}"
  },
  {
    "path": "json-path-assert/src/main/java/com/jayway/jsonassert/impl/matcher/IsCollectionWithSize.java",
    "content": "/*\nBSD License\n\nCopyright (c) 2000-2006, www.hamcrest.org\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this list of\nconditions and the following disclaimer. Redistributions in binary form must reproduce\nthe above copyright notice, this list of conditions and the following disclaimer in\nthe documentation and/or other materials provided with the distribution.\n\nNeither the name of Hamcrest nor the names of its contributors may be used to endorse\nor promote products derived from this software without specific prior written\npermission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY\nWAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n*/\npackage com.jayway.jsonassert.impl.matcher;\n\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\n\nimport java.util.Collection;\n\nimport static org.hamcrest.core.IsEqual.equalTo;\n\n/**\n * Matches if collection size satisfies a nested matcher.\n */\npublic class IsCollectionWithSize<E> extends CollectionMatcher<Collection<? extends E>> {\n    private final Matcher<? super Integer> sizeMatcher;\n\n    public IsCollectionWithSize(Matcher<? super Integer> sizeMatcher) {\n        this.sizeMatcher = sizeMatcher;\n    }\n\n    @Override\n    public boolean matchesSafely(Collection<? extends E> item) {\n        return sizeMatcher.matches(item.size());\n    }\n\n    @Override\n    public void describeTo(Description description) {\n        description.appendText(\"a collection with size \")\n            .appendDescriptionOf(sizeMatcher);\n    }\n\n    /**\n     * Does collection size satisfy a given matcher?\n     */\n    public static <E> Matcher<? super Collection<? extends E>> hasSize(Matcher<? super Integer> size) {\n        return new IsCollectionWithSize<E>(size);\n    }\n\n    /**\n     * This is a shortcut to the frequently used hasSize(equalTo(x)).\n     *\n     * For example,  assertThat(hasSize(equal_to(x)))\n     *          vs.  assertThat(hasSize(x))\n     */\n    public static <E> Matcher<? super Collection<? extends E>> hasSize(int size) {\n        Matcher<? super Integer> matcher = equalTo(size);\n        return IsCollectionWithSize.<E>hasSize(matcher);\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/main/java/com/jayway/jsonassert/impl/matcher/IsEmptyCollection.java",
    "content": "/*\nBSD License\n\nCopyright (c) 2000-2006, www.hamcrest.org\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this list of\nconditions and the following disclaimer. Redistributions in binary form must reproduce\nthe above copyright notice, this list of conditions and the following disclaimer in\nthe documentation and/or other materials provided with the distribution.\n\nNeither the name of Hamcrest nor the names of its contributors may be used to endorse\nor promote products derived from this software without specific prior written\npermission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY\nWAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n*/\npackage com.jayway.jsonassert.impl.matcher;\n\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\n\nimport java.util.Collection;\n\n/**\n * Tests if collection is empty.\n */\npublic class IsEmptyCollection<E> extends CollectionMatcher<Collection<E>> {\n\n    @Override\n    public boolean matchesSafely(Collection<E> item) {\n        return item.isEmpty();\n    }\n\n    @Override\n    public void describeTo(Description description) {\n        description.appendText(\"an empty collection\");\n    }\n\n    /**\n     * Matches an empty collection.\n     */\n    public static <E> Matcher<Collection<E>> empty() {\n        return new IsEmptyCollection<E>();\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/main/java/com/jayway/jsonassert/impl/matcher/IsMapContainingKey.java",
    "content": "/*\nBSD License\n\nCopyright (c) 2000-2006, www.hamcrest.org\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this list of\nconditions and the following disclaimer. Redistributions in binary form must reproduce\nthe above copyright notice, this list of conditions and the following disclaimer in\nthe documentation and/or other materials provided with the distribution.\n\nNeither the name of Hamcrest nor the names of its contributors may be used to endorse\nor promote products derived from this software without specific prior written\npermission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY\nWAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n*/\npackage com.jayway.jsonassert.impl.matcher;\n\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\n\nimport java.util.Map;\n\nimport static org.hamcrest.core.IsEqual.equalTo;\n\npublic class IsMapContainingKey<K> extends MapTypeSafeMatcher<Map<K,?>> {\n    private final Matcher<K> keyMatcher;\n\n    public IsMapContainingKey(Matcher<K> keyMatcher) {\n        this.keyMatcher = keyMatcher;\n    }\n\n    @Override\n    public boolean matchesSafely(Map<K, ?> item) {\n        for (K key : item.keySet()) {\n            if (keyMatcher.matches(key)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public void describeTo(Description description) {\n        description.appendText(\"map with key \")\n                   .appendDescriptionOf(keyMatcher);\n    }\n\n    public static <K> Matcher<Map<K,?>> hasKey(K key) {\n        return hasKey(equalTo(key));\n    }\n\n    public static <K> Matcher<Map<K,?>> hasKey(Matcher<K> keyMatcher) {\n        return new IsMapContainingKey<K>(keyMatcher);\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/main/java/com/jayway/jsonassert/impl/matcher/IsMapContainingValue.java",
    "content": "/*\nBSD License\n\nCopyright (c) 2000-2006, www.hamcrest.org\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this list of\nconditions and the following disclaimer. Redistributions in binary form must reproduce\nthe above copyright notice, this list of conditions and the following disclaimer in\nthe documentation and/or other materials provided with the distribution.\n\nNeither the name of Hamcrest nor the names of its contributors may be used to endorse\nor promote products derived from this software without specific prior written\npermission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY\nWAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n*/\npackage com.jayway.jsonassert.impl.matcher;\n\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\n\nimport java.util.Map;\n\nimport static org.hamcrest.core.IsEqual.equalTo;\n\npublic class IsMapContainingValue<V> extends MapTypeSafeMatcher<Map<?,V>>{\n    private final Matcher<? super V> valueMatcher;\n\n    public IsMapContainingValue(Matcher<? super V> valueMatcher) {\n        this.valueMatcher = valueMatcher;\n    }\n\n    @Override\n    public boolean matchesSafely(Map<?, V> item) {\n        for (V value : item.values()) {\n            if (valueMatcher.matches(value)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public void describeTo(Description description) {\n        description.appendText(\"map with value \")\n                   .appendDescriptionOf(valueMatcher);\n    }\n\n    public static <V> Matcher<? super Map<?,V>> hasValue(V value) {\n        return IsMapContainingValue.<V>hasValue(equalTo(value));\n    }\n\n    public static <V> Matcher<? super Map<?,V>> hasValue(Matcher<? super V> valueMatcher) {\n        return new IsMapContainingValue<V>(valueMatcher);\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/main/java/com/jayway/jsonassert/impl/matcher/MapTypeSafeMatcher.java",
    "content": "/*\nBSD License\n\nCopyright (c) 2000-2006, www.hamcrest.org\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this list of\nconditions and the following disclaimer. Redistributions in binary form must reproduce\nthe above copyright notice, this list of conditions and the following disclaimer in\nthe documentation and/or other materials provided with the distribution.\n\nNeither the name of Hamcrest nor the names of its contributors may be used to endorse\nor promote products derived from this software without specific prior written\npermission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\nSHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY\nWAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n*/\npackage com.jayway.jsonassert.impl.matcher;\n\nimport org.hamcrest.BaseMatcher;\n\nimport java.util.Map;\n\npublic abstract class MapTypeSafeMatcher<M extends Map<?, ?>> extends BaseMatcher<M> {\n    @SuppressWarnings(\"unchecked\")\n    public boolean matches(Object item) {\n        return item instanceof Map && matchesSafely((M) item);\n    }\n\n    protected abstract boolean matchesSafely(M map);\n}"
  },
  {
    "path": "json-path-assert/src/main/java/com/jayway/jsonpath/matchers/IsJson.java",
    "content": "package com.jayway.jsonpath.matchers;\n\nimport com.jayway.jsonpath.JsonPath;\nimport com.jayway.jsonpath.JsonPathException;\nimport com.jayway.jsonpath.ReadContext;\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\nimport org.hamcrest.TypeSafeMatcher;\n\nimport java.io.File;\nimport java.io.IOException;\n\npublic class IsJson<T> extends TypeSafeMatcher<T> {\n    private final Matcher<? super ReadContext> jsonMatcher;\n\n    public IsJson(Matcher<? super ReadContext> jsonMatcher) {\n        this.jsonMatcher = jsonMatcher;\n    }\n\n    @Override\n    protected boolean matchesSafely(T json) {\n        try {\n            ReadContext context = parse(json);\n            return jsonMatcher.matches(context);\n        } catch (JsonPathException e) {\n            return false;\n        } catch (IOException e) {\n            return false;\n        }\n    }\n\n    public void describeTo(Description description) {\n        description.appendText(\"is json \").appendDescriptionOf(jsonMatcher);\n    }\n\n    @Override\n    protected void describeMismatchSafely(T json, Description mismatchDescription) {\n        try {\n            ReadContext context = parse(json);\n            jsonMatcher.describeMismatch(context, mismatchDescription);\n        } catch (JsonPathException e) {\n            buildMismatchDescription(json, mismatchDescription, e);\n        } catch (IOException e) {\n            buildMismatchDescription(json, mismatchDescription, e);\n        }\n    }\n\n    private static void buildMismatchDescription(Object json, Description mismatchDescription, Exception e) {\n        mismatchDescription\n                .appendText(\"was \")\n                .appendValue(json)\n                .appendText(\" which failed with \")\n                .appendValue(e.getMessage());\n    }\n\n    private static ReadContext parse(Object object) throws IOException {\n        if (object instanceof String) {\n            return JsonPath.parse((String) object);\n        } else if (object instanceof File) {\n            return JsonPath.parse((File) object);\n        } else if (object instanceof ReadContext) {\n            return (ReadContext) object;\n        } else {\n            return JsonPath.parse(object);\n        }\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/main/java/com/jayway/jsonpath/matchers/JsonPathMatchers.java",
    "content": "package com.jayway.jsonpath.matchers;\n\nimport com.jayway.jsonpath.JsonPath;\nimport com.jayway.jsonpath.Predicate;\nimport com.jayway.jsonpath.ReadContext;\nimport org.hamcrest.Matcher;\n\nimport java.io.File;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.hamcrest.Matchers.*;\n\npublic class JsonPathMatchers {\n\n    private JsonPathMatchers() {\n        throw new AssertionError(\"prevent instantiation\");\n    }\n\n    public static Matcher<? super Object> hasJsonPath(String jsonPath) {\n        return describedAs(\"has json path %0\",\n                isJson(withJsonPath(jsonPath)),\n                jsonPath);\n    }\n\n    public static <T> Matcher<? super Object> hasJsonPath(String jsonPath, Matcher<T> resultMatcher) {\n        return isJson(withJsonPath(jsonPath, resultMatcher));\n    }\n\n    public static Matcher<? super Object> hasNoJsonPath(String jsonPath) {\n        return isJson(withoutJsonPath(jsonPath));\n    }\n\n    public static Matcher<Object> isJson() {\n        return isJson(withJsonPath(\"$\", anyOf(instanceOf(Map.class), instanceOf(List.class))));\n    }\n\n    public static Matcher<Object> isJson(Matcher<? super ReadContext> matcher) {\n        return new IsJson<Object>(matcher);\n    }\n\n    public static Matcher<String> isJsonString(Matcher<? super ReadContext> matcher) {\n        return new IsJson<String>(matcher);\n    }\n\n    public static Matcher<File> isJsonFile(Matcher<? super ReadContext> matcher) {\n        return new IsJson<File>(matcher);\n    }\n\n    public static Matcher<? super ReadContext> withJsonPath(String jsonPath, Predicate... filters) {\n        return withJsonPath(JsonPath.compile(jsonPath, filters));\n    }\n\n    public static Matcher<? super ReadContext> withJsonPath(JsonPath jsonPath) {\n        return describedAs(\"with json path %0\",\n                withJsonPath(jsonPath, anything()),\n                jsonPath.getPath());\n    }\n\n    public static Matcher<? super ReadContext> withoutJsonPath(String jsonPath, Predicate... filters) {\n        return withoutJsonPath(JsonPath.compile(jsonPath, filters));\n    }\n\n    public static Matcher<? super ReadContext> withoutJsonPath(JsonPath jsonPath) {\n        return new WithoutJsonPath(jsonPath);\n    }\n\n    public static <T> Matcher<? super ReadContext> withJsonPath(String jsonPath, Matcher<T> resultMatcher) {\n        return withJsonPath(JsonPath.compile(jsonPath), resultMatcher);\n    }\n\n    public static <T> Matcher<? super ReadContext> withJsonPath(JsonPath jsonPath, Matcher<T> resultMatcher) {\n        return new WithJsonPath<T>(jsonPath, resultMatcher);\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/main/java/com/jayway/jsonpath/matchers/WithJsonPath.java",
    "content": "package com.jayway.jsonpath.matchers;\n\nimport com.jayway.jsonpath.JsonPath;\nimport com.jayway.jsonpath.JsonPathException;\nimport com.jayway.jsonpath.PathNotFoundException;\nimport com.jayway.jsonpath.ReadContext;\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\nimport org.hamcrest.TypeSafeMatcher;\n\npublic class WithJsonPath<T> extends TypeSafeMatcher<ReadContext> {\n    private final JsonPath jsonPath;\n    private final Matcher<T> resultMatcher;\n\n    public WithJsonPath(JsonPath jsonPath, Matcher<T> resultMatcher) {\n        this.jsonPath = jsonPath;\n        this.resultMatcher = resultMatcher;\n    }\n\n    @Override\n    protected boolean matchesSafely(ReadContext context) {\n        try {\n            T value = context.read(jsonPath);\n            return resultMatcher.matches(value);\n        } catch (JsonPathException e) {\n            return false;\n        }\n    }\n\n    public void describeTo(Description description) {\n        description\n                .appendText(\"with json path \")\n                .appendValue(jsonPath.getPath())\n                .appendText(\" evaluated to \")\n                .appendDescriptionOf(resultMatcher);\n    }\n\n    @Override\n    protected void describeMismatchSafely(ReadContext context, Description mismatchDescription) {\n        try {\n            T value = jsonPath.read(context.jsonString());\n            mismatchDescription\n                    .appendText(\"json path \")\n                    .appendValue(jsonPath.getPath())\n                    .appendText(\" was evaluated to \")\n                    .appendValue(value);\n        } catch (PathNotFoundException e) {\n            mismatchDescription\n                    .appendText(\"json path \")\n                    .appendValue(jsonPath.getPath())\n                    .appendText(\" was not found in \")\n                    .appendValue(context.json());\n        } catch (JsonPathException e) {\n            mismatchDescription\n                    .appendText(\"was \")\n                    .appendValue(context.json());\n        }\n    }\n\n}\n"
  },
  {
    "path": "json-path-assert/src/main/java/com/jayway/jsonpath/matchers/WithoutJsonPath.java",
    "content": "package com.jayway.jsonpath.matchers;\n\nimport com.jayway.jsonpath.JsonPath;\nimport com.jayway.jsonpath.JsonPathException;\nimport com.jayway.jsonpath.ReadContext;\nimport org.hamcrest.Description;\nimport org.hamcrest.TypeSafeDiagnosingMatcher;\n\npublic class WithoutJsonPath extends TypeSafeDiagnosingMatcher<ReadContext> {\n    private final JsonPath jsonPath;\n\n    public WithoutJsonPath(JsonPath jsonPath) {\n        this.jsonPath = jsonPath;\n    }\n\n    @Override\n    protected boolean matchesSafely(ReadContext actual, Description mismatchDescription) {\n        try {\n            Object value = actual.read(jsonPath);\n            mismatchDescription\n                    .appendText(jsonPath.getPath())\n                    .appendText(\" was evaluated to \")\n                    .appendValue(value);\n            return false;\n        } catch (JsonPathException e) {\n            return true;\n        }\n    }\n\n    @Override\n    public void describeTo(Description description) {\n        description.appendText(\"without json path \").appendValue(jsonPath.getPath());\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/test/java/com/jayway/jsonassert/JsonAssertTest.java",
    "content": "package com.jayway.jsonassert;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.io.InputStream;\n\nimport static com.jayway.jsonassert.JsonAssert.*;\nimport static org.hamcrest.Matchers.*;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\npublic class JsonAssertTest {\n\n    public final static String JSON =\n            \"{ \\\"store\\\": {\\n\" +\n                    \"    \\\"book\\\": [ \\n\" +\n                    \"      { \\\"category\\\": \\\"reference\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Nigel Rees\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Sayings of the Century\\\",\\n\" +\n                    \"        \\\"price\\\": 8.95\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Evelyn Waugh\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Sword of Honour\\\",\\n\" +\n                    \"        \\\"price\\\": 12.99\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"Herman Melville\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"Moby Dick\\\",\\n\" +\n                    \"        \\\"isbn\\\": \\\"0-553-21311-3\\\",\\n\" +\n                    \"        \\\"price\\\": 8.99\\n\" +\n                    \"      },\\n\" +\n                    \"      { \\\"category\\\": \\\"fiction\\\",\\n\" +\n                    \"        \\\"author\\\": \\\"J. R. R. Tolkien\\\",\\n\" +\n                    \"        \\\"title\\\": \\\"The Lord of the Rings\\\",\\n\" +\n                    \"        \\\"isbn\\\": \\\"0-395-19395-8\\\",\\n\" +\n                    \"        \\\"price\\\": 22.99\\n\" +\n                    \"      }\\n\" +\n                    \"    ],\\n\" +\n                    \"    \\\"bicycle\\\": {\\n\" +\n                    \"      \\\"color\\\": \\\"red\\\",\\n\" +\n                    \"      \\\"price\\\": 19.95\\n,\" +\n                    \"      \\\"gears\\\": [23, 50]\\n,\" +\n                    \"      \\\"extra\\\": {\\\"x\\\": 0}\\n,\" +\n                    \"      \\\"escape\\\" : \\\"Esc\\\\b\\\\f\\\\n\\\\r\\\\t\\\\u002A\\\",\\n\" +\n                    \"      \\\"nullValue\\\": null\\n\" +\n                    \"    }\\n\" +\n                    \"  }\\n\" +\n                    \"}\";\n\n    @Test\n    public void invalid_path() throws Exception {\n        with(JSON).assertThat(\"$.store.book[*].fooBar\", emptyCollection());\n    }\n\n\n    @Test\n    public void has_path() throws Exception {\n\n        assertThrows(AssertionError.class, () -> with(JSON).assertNotDefined(\"$.store.bicycle[?(@.color == 'red' )]\"));\n    }\n\n    @Test\n    public void assert_gears() throws Exception {\n        with(JSON).assertThat(\"$.store.bicycle[?(@.gears == [23, 50])]\", is(collectionWithSize(equalTo(1))));\n        with(JSON).assertThat(\"$.store.bicycle[?(@.gears == [23, 77])]\", is(collectionWithSize(equalTo(0))));\n        with(JSON).assertThat(\"$.store.bicycle[?(@.extra == {\\\"x\\\":0})]\", is(collectionWithSize(equalTo(1))));\n        with(JSON).assertThat(\"$.store.bicycle[?(@.escape == 'Esc\\\\b\\\\f\\\\n\\\\r\\\\t\\\\u002A')]\", is(collectionWithSize(equalTo(1))));\n    }\n\n    @Test\n    public void failed_error_message() throws Exception {\n\n        assertThrows(AssertionError.class, () -> with(JSON).assertThat(\"$.store.book[0].category\", endsWith(\"foobar\")));\n    }\n\n    @Test\n    public void links_document() throws Exception {\n\n        with(getResourceAsStream(\"links.json\")).assertEquals(\"count\", 2)\n                .assertThat(\"links['gc:this']href\", endsWith(\"?pageNumber=1&pageSize=2\"))\n                .assertNotDefined(\"links['gc:prev']\")\n                .assertNotDefined(\"links['gc:next']\")\n                .assertThat(\"rows\", collectionWithSize(equalTo(2)));\n\n    }\n\n    @Test\n    public void a_document_can_be_expected_not_to_contain_a_path() throws Exception {\n        with(JSON).assertNotDefined(\"$.store.bicycle.cool\");\n    }\n\n    @Test\n    public void a_value_can_asserted_to_be_null() throws Exception {\n        with(JSON).assertNull(\"$.store.bicycle.nullValue\");\n    }\n\n    @Test\n    public void ends_with_evalueates() throws Exception {\n        with(JSON).assertThat(\"$.store.book[0].category\", endsWith(\"nce\"));\n    }\n\n    @Test\n    public void a_path_can_be_asserted_with_matcher() throws Exception {\n\n        with(JSON).assertThat(\"$.store.bicycle.color\", equalTo(\"red\"))\n                .assertThat(\"$.store.bicycle.price\", equalTo(19.95D));\n    }\n\n    @Test\n    public void list_content_can_be_asserted_with_matcher() throws Exception {\n\n        with(JSON).assertThat(\"$..book[*].author\", hasItems(\"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\"));\n\n        with(JSON).assertThat(\"$..author\", hasItems(\"Nigel Rees\", \"Evelyn Waugh\", \"Herman Melville\", \"J. R. R. Tolkien\"))\n                .assertThat(\"$..author\", is(collectionWithSize(equalTo(4))));\n    }\n\n    @Test\n    public void list_content_can_be_asserted_with_nested_matcher() throws Exception {\n        with(JSON).assertThat(\"$..book[*]\", hasItems(hasEntry(\"author\", \"Nigel Rees\"), hasEntry(\"author\", \"Evelyn Waugh\")));\n    }\n\n    @Test\n    public void map_content_can_be_asserted_with_matcher() throws Exception {\n\n        with(JSON).assertThat(\"$.store.book[0]\", hasEntry(\"category\", \"reference\"))\n                .assertThat(\"$.store.book[0]\", hasEntry(\"title\", \"Sayings of the Century\"))\n                .and()\n                .assertThat(\"$..book[0]\", is(collectionWithSize(equalTo(1))))\n                .and()\n                .assertThat(\"$.store.book[0]\", mapContainingKey(equalTo(\"category\")))\n                .and()\n                .assertThat(\"$.store.book[0]\", mapContainingValue(equalTo(\"reference\")));\n\n        with(JSON).assertThat(\"$.['store'].['book'][0]\", hasEntry(\"category\", \"reference\"))\n                .assertThat(\"$.['store'].['book'][0]\", hasEntry(\"title\", \"Sayings of the Century\"))\n                .and()\n                .assertThat(\"$..['book'][0]\", is(collectionWithSize(equalTo(1))))\n                .and()\n                .assertThat(\"$.['store'].['book'][0]\", mapContainingKey(equalTo(\"category\")))\n                .and()\n                .assertThat(\"$.['store'].['book'][0]\", mapContainingValue(equalTo(\"reference\")));\n    }\n\n    @Test\n    public void an_empty_collection() throws Exception {\n        with(JSON).assertThat(\"$.store.book[?(@.category == 'x')]\", emptyCollection());\n    }\n\n    @Test\n    public void a_path_can_be_asserted_equal_to() throws Exception {\n\n        with(JSON).assertEquals(\"$.store.book[0].title\", \"Sayings of the Century\")\n                .assertThat(\"$.store.book[0].title\", equalTo(\"Sayings of the Century\"));\n\n        with(JSON).assertEquals(\"$['store']['book'][0].['title']\", \"Sayings of the Century\")\n                .assertThat(\"$['store'].book[0].title\", equalTo(\"Sayings of the Century\"));\n    }\n\n    @Test\n    public void path_including_wildcard_path_followed_by_another_path_concatenates_results_to_list() throws Exception {\n        with(getResourceAsStream(\"lotto.json\")).assertThat(\"lotto.winners[*].winnerId\", hasItems(23, 54));\n    }\n\n    @Test\n    public void testNotDefined() throws Exception {\n        JsonAsserter asserter = JsonAssert.with(\"{\\\"foo\\\":\\\"bar\\\"}\");\n        asserter.assertNotDefined(\"$.xxx\");\n    }\n\n\n    @Test\n    public void assert_that_invalid_path_is_thrown() {\n\n        JsonAsserter asserter = JsonAssert.with(\"{\\\"foo\\\":\\\"bar\\\"}\");\n        assertThrows(AssertionError.class, () -> asserter.assertEquals(\"$foo\", \"bar\"));\n    }\n\n    @Test\n    public void testAssertEqualsInteger() throws Exception {\n        with(getResourceAsStream(\"lotto.json\")).assertEquals(\"lotto.winners[0].winnerId\", 23);\n    }\n\n    @Test\n    public void testAssertEqualsIntegerInvalidExpected() throws Exception {\n        assertThrows(AssertionError.class, () -> with(getResourceAsStream(\"lotto.json\")).assertEquals(\"lotto.winners[0].winnerId\", 24));\n    }\n\n    @Test\n    public void testAssertEqualsIntegerInvalidField() throws Exception {\n        assertThrows(AssertionError.class, () -> with(getResourceAsStream(\"lotto.json\")).assertEquals(\"lotto.winners[0].winnerId1\", 24));\n    }\n\n    private InputStream getResourceAsStream(String resourceName) {\n        return getClass().getClassLoader().getResourceAsStream(resourceName);\n    }\n\n}\n"
  },
  {
    "path": "json-path-assert/src/test/java/com/jayway/jsonpath/matchers/DemoTest.java",
    "content": "package com.jayway.jsonpath.matchers;\n\nimport org.junit.jupiter.api.Disabled;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\n\nimport static com.jayway.jsonpath.matchers.JsonPathMatchers.*;\nimport static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resource;\nimport static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resourceAsFile;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.equalTo;\n\n@Disabled\npublic class DemoTest {\n    @Test\n    public void shouldFailOnJsonString() {\n        String json = resource(\"books.json\");\n        assertThat(json, isJson(withJsonPath(\"$.store.name\", equalTo(\"The Shop\"))));\n    }\n\n    @Test\n    public void shouldFailOnJsonFile() {\n        File json = resourceAsFile(\"books.json\");\n        assertThat(json, isJson(withJsonPath(\"$.store.name\", equalTo(\"The Shop\"))));\n    }\n\n    @Test\n    public void shouldFailOnInvalidJsonString() {\n        String json = resource(\"invalid.json\");\n        assertThat(json, isJson(withJsonPath(\"$.store.name\", equalTo(\"The Shop\"))));\n    }\n\n    @Test\n    public void shouldFailOnInvalidJsonFile() {\n        File json = resourceAsFile(\"invalid.json\");\n        assertThat(json, isJson(withJsonPath(\"$.store.name\", equalTo(\"The Shop\"))));\n    }\n\n    @Test\n    public void shouldFailOnTypedJsonString() {\n        String json = resource(\"books.json\");\n        assertThat(json, isJsonString(withJsonPath(\"$.store.name\", equalTo(\"The Shop\"))));\n    }\n\n    @Test\n    public void shouldFailOnTypedJsonFile() {\n        File json = resourceAsFile(\"books.json\");\n        assertThat(json, isJsonFile(withJsonPath(\"$.store.name\", equalTo(\"The Shop\"))));\n    }\n\n    @Test\n    public void shouldFailOnTypedInvalidJsonString() {\n        String json = resource(\"invalid.json\");\n        assertThat(json, isJsonString(withJsonPath(\"$.store.name\", equalTo(\"The Shop\"))));\n    }\n\n    @Test\n    public void shouldFailOnTypedInvalidJsonFile() {\n        File json = resourceAsFile(\"invalid.json\");\n        assertThat(json, isJsonFile(withJsonPath(\"$.store.name\", equalTo(\"The Shop\"))));\n    }\n\n    @Test\n    public void shouldFailOnNonExistingJsonPath() {\n        String json = resource(\"books.json\");\n        assertThat(json, hasJsonPath(\"$.not-here\"));\n    }\n\n    @Test\n    public void shouldFailOnExistingJsonPath() {\n        String json = resource(\"books.json\");\n        assertThat(json, hasNoJsonPath(\"$.store.name\"));\n    }\n\n    @Test\n    public void shouldFailOnExistingJsonPathAlternative() {\n        String json = resource(\"books.json\");\n        assertThat(json, isJson(withoutJsonPath(\"$.store.name\")));\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/test/java/com/jayway/jsonpath/matchers/HasNoJsonPathTest.java",
    "content": "package com.jayway.jsonpath.matchers;\n\nimport org.junit.jupiter.api.Test;\n\nimport static com.jayway.jsonpath.matchers.JsonPathMatchers.hasNoJsonPath;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.*;\n\npublic class HasNoJsonPathTest {\n    private static final String JSON_STRING = \"{\" +\n            \"\\\"none\\\": null,\" +\n            \"\\\"name\\\": \\\"Jessie\\\"\" +\n            \"}\";\n\n    @Test\n    public void shouldMatchMissingJsonPath() {\n        assertThat(JSON_STRING, hasNoJsonPath(\"$.not_there\"));\n    }\n\n    @Test\n    public void shouldNotMatchExistingJsonPath() {\n        assertThat(JSON_STRING, not(hasNoJsonPath(\"$.name\")));\n    }\n\n    @Test\n    public void shouldNotMatchExplicitNull() {\n        assertThat(JSON_STRING, not(hasNoJsonPath(\"$.none\")));\n    }\n\n    @Test\n    public void shouldBeDescriptive() {\n        assertThat(hasNoJsonPath(\"$.name\"),\n                hasToString(equalTo(\"is json without json path \\\"$['name']\\\"\")));\n    }\n\n}\n"
  },
  {
    "path": "json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonFileTest.java",
    "content": "package com.jayway.jsonpath.matchers;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.matchers.helpers.StrictParsingConfiguration;\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\nimport org.hamcrest.StringDescription;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\n\nimport static com.jayway.jsonpath.matchers.JsonPathMatchers.isJsonFile;\nimport static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resourceAsFile;\nimport static com.jayway.jsonpath.matchers.helpers.TestingMatchers.*;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.*;\n\npublic class IsJsonFileTest {\n    private static final File BOOKS_JSON = resourceAsFile(\"books.json\");\n    private static final File INVALID_JSON = resourceAsFile(\"invalid.json\");\n\n    @BeforeAll\n    public static void setupStrictJsonParsing() {\n        Configuration.setDefaults(new StrictParsingConfiguration());\n    }\n\n    @AfterAll\n    public static void setupDefaultJsonParsing() {\n        Configuration.setDefaults(null);\n    }\n\n    @Test\n    public void shouldMatchJsonFileEvaluatedToTrue() {\n        assertThat(BOOKS_JSON, isJsonFile(withPathEvaluatedTo(true)));\n    }\n\n    @Test\n    public void shouldNotMatchJsonFileEvaluatedToFalse() {\n        assertThat(BOOKS_JSON, not(isJsonFile(withPathEvaluatedTo(false))));\n    }\n\n    @Test\n    public void shouldNotMatchInvalidJsonFile() {\n        assertThat(INVALID_JSON, not(isJsonFile(withPathEvaluatedTo(true))));\n        assertThat(INVALID_JSON, not(isJsonFile(withPathEvaluatedTo(false))));\n    }\n\n    @Test\n    public void shouldBeDescriptive() {\n        Matcher<File> matcher = isJsonFile(withPathEvaluatedTo(true));\n        Description description = new StringDescription();\n        matcher.describeTo(description);\n        assertThat(description.toString(), startsWith(\"is json\"));\n        assertThat(description.toString(), containsString(MATCH_TRUE_TEXT));\n    }\n\n    @Test\n    public void shouldDescribeMismatchOfValidJson() {\n        Matcher<File> matcher = isJsonFile(withPathEvaluatedTo(true));\n        Description description = new StringDescription();\n        matcher.describeMismatch(BOOKS_JSON, description);\n        assertThat(description.toString(), containsString(MISMATCHED_TEXT));\n    }\n\n    @Test\n    public void shouldDescribeMismatchOfInvalidJson() {\n        Matcher<File> matcher = isJsonFile(withPathEvaluatedTo(true));\n        Description description = new StringDescription();\n        matcher.describeMismatch(INVALID_JSON, description);\n        assertThat(description.toString(), containsString(\"invalid.json\"));\n        assertThat(description.toString(), containsString(\"invalid-json\"));\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonStringTest.java",
    "content": "package com.jayway.jsonpath.matchers;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.matchers.helpers.StrictParsingConfiguration;\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\nimport org.hamcrest.StringDescription;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static com.jayway.jsonpath.matchers.JsonPathMatchers.isJsonString;\nimport static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resource;\nimport static com.jayway.jsonpath.matchers.helpers.TestingMatchers.*;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.*;\n\npublic class IsJsonStringTest {\n    private static final String BOOKS_JSON = resource(\"books.json\");\n\n    @BeforeAll\n    public static void setupStrictJsonParsing() {\n        Configuration.setDefaults(new StrictParsingConfiguration());\n    }\n\n    @AfterAll\n    public static void setupDefaultJsonParsing() {\n        Configuration.setDefaults(null);\n    }\n\n    @Test\n    public void shouldMatchJsonStringEvaluatedToTrue() {\n        assertThat(BOOKS_JSON, isJsonString(withPathEvaluatedTo(true)));\n    }\n\n    @Test\n    public void shouldNotMatchJsonStringEvaluatedToFalse() {\n        assertThat(BOOKS_JSON, not(isJsonString(withPathEvaluatedTo(false))));\n    }\n\n    @Test\n    public void shouldNotMatchInvalidJsonString() {\n        assertThat(\"invalid-json\", not(isJsonString(withPathEvaluatedTo(true))));\n        assertThat(\"invalid-json\", not(isJsonString(withPathEvaluatedTo(false))));\n    }\n\n    @Test\n    public void shouldBeDescriptive() {\n        Matcher<String> matcher = isJsonString(withPathEvaluatedTo(true));\n        Description description = new StringDescription();\n        matcher.describeTo(description);\n        assertThat(description.toString(), startsWith(\"is json\"));\n        assertThat(description.toString(), containsString(MATCH_TRUE_TEXT));\n    }\n\n    @Test\n    public void shouldDescribeMismatchOfValidJson() {\n        Matcher<String> matcher = isJsonString(withPathEvaluatedTo(true));\n        Description description = new StringDescription();\n        matcher.describeMismatch(BOOKS_JSON, description);\n        assertThat(description.toString(), containsString(MISMATCHED_TEXT));\n    }\n\n    @Test\n    public void shouldDescribeMismatchOfInvalidJson() {\n        Matcher<String> matcher = isJsonString(withPathEvaluatedTo(true));\n        Description description = new StringDescription();\n        matcher.describeMismatch(\"invalid-json\", description);\n        assertThat(description.toString(), containsString(\"\\\"invalid-json\\\"\"));\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/test/java/com/jayway/jsonpath/matchers/IsJsonTest.java",
    "content": "package com.jayway.jsonpath.matchers;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.matchers.helpers.StrictParsingConfiguration;\nimport com.jayway.jsonpath.matchers.helpers.TestingMatchers;\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\nimport org.hamcrest.StringDescription;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\n\nimport static com.jayway.jsonpath.matchers.JsonPathMatchers.isJson;\nimport static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resource;\nimport static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resourceAsFile;\nimport static com.jayway.jsonpath.matchers.helpers.TestingMatchers.withPathEvaluatedTo;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.*;\n\npublic class IsJsonTest {\n    private static final String VALID_JSON = resource(\"example.json\");\n    private static final String INVALID_JSON = \"{ invalid-json }\";\n    private static final String BOOKS_JSON_STRING = resource(\"books.json\");\n    private static final File BOOKS_JSON_FILE = resourceAsFile(\"books.json\");\n    private static final Object BOOKS_JSON_PARSED = parseJson(BOOKS_JSON_STRING);\n\n    @BeforeAll\n    public static void setupStrictJsonParsing() {\n        Configuration.setDefaults(new StrictParsingConfiguration());\n    }\n\n    @AfterAll\n    public static void setupDefaultJsonParsing() {\n        Configuration.setDefaults(null);\n    }\n\n    @Test\n    public void shouldMatchOnEmptyJsonObject() {\n        assertThat(\"{}\", isJson());\n    }\n\n    @Test\n    public void shouldMatchOnJsonObject() {\n        assertThat(\"{ \\\"hi\\\" : \\\"there\\\" }\", isJson());\n    }\n\n    @Test\n    public void shouldMatchOnEmptyJsonArray() {\n        assertThat(\"[]\", isJson());\n    }\n\n    @Test\n    public void shouldMatchOnJsonArray() {\n        assertThat(\"[\\\"hi\\\", \\\"there\\\"]\", isJson());\n    }\n\n    @Test\n    public void shouldMatchValidJson() {\n        assertThat(VALID_JSON, isJson());\n        assertThat(BOOKS_JSON_STRING, isJson());\n    }\n\n    @Test\n    public void shouldNotMatchInvalidJson() {\n        assertThat(INVALID_JSON, not(isJson()));\n        assertThat(new Object(), not(isJson()));\n        assertThat(new Object[]{}, not(isJson()));\n        assertThat(\"hi there\", not(isJson()));\n        assertThat(new Integer(42), not(isJson()));\n        assertThat(Boolean.TRUE, not(isJson()));\n        assertThat(false, not(isJson()));\n        assertThat(null, not(isJson()));\n    }\n\n    @Test\n    public void shouldMatchJsonObjectEvaluatedToTrue() {\n        assertThat(BOOKS_JSON_PARSED, isJson(withPathEvaluatedTo(true)));\n    }\n\n    @Test\n    public void shouldNotMatchJsonObjectEvaluatedToFalse() {\n        assertThat(BOOKS_JSON_PARSED, not(isJson(withPathEvaluatedTo(false))));\n    }\n\n    @Test\n    public void shouldMatchJsonStringEvaluatedToTrue() {\n        assertThat(BOOKS_JSON_STRING, isJson(withPathEvaluatedTo(true)));\n    }\n\n    @Test\n    public void shouldNotMatchJsonStringEvaluatedToFalse() {\n        assertThat(BOOKS_JSON_STRING, not(isJson(withPathEvaluatedTo(false))));\n    }\n\n    @Test\n    public void shouldMatchJsonFileEvaluatedToTrue() {\n        assertThat(BOOKS_JSON_FILE, isJson(withPathEvaluatedTo(true)));\n    }\n\n    @Test\n    public void shouldNotMatchJsonFileEvaluatedToFalse() {\n        assertThat(BOOKS_JSON_FILE, not(isJson(withPathEvaluatedTo(false))));\n    }\n\n    @Test\n    public void shouldNotMatchNonExistingJsonFile() {\n        File nonExistingFile = new File(\"missing-file\");\n        assertThat(nonExistingFile, not(isJson()));\n    }\n\n    @Test\n    public void shouldBeDescriptive() {\n        Matcher<Object> matcher = isJson(withPathEvaluatedTo(true));\n        Description description = new StringDescription();\n        matcher.describeTo(description);\n        assertThat(description.toString(), startsWith(\"is json\"));\n        assertThat(description.toString(), containsString(TestingMatchers.MATCH_TRUE_TEXT));\n    }\n\n    @Test\n    public void shouldDescribeMismatchOfValidJson() {\n        Matcher<Object> matcher = isJson(withPathEvaluatedTo(true));\n        Description description = new StringDescription();\n        matcher.describeMismatch(BOOKS_JSON_STRING, description);\n        assertThat(description.toString(), containsString(TestingMatchers.MISMATCHED_TEXT));\n    }\n\n    @Test\n    public void shouldDescribeMismatchOfInvalidJson() {\n        Matcher<Object> matcher = isJson(withPathEvaluatedTo(true));\n        Description description = new StringDescription();\n        matcher.describeMismatch(\"invalid-json\", description);\n        assertThat(description.toString(), containsString(\"\\\"invalid-json\\\"\"));\n    }\n\n    private static Object parseJson(String json) {\n        return Configuration.defaultConfiguration().jsonProvider().parse(json);\n    }\n\n}\n"
  },
  {
    "path": "json-path-assert/src/test/java/com/jayway/jsonpath/matchers/JsonPathMatchersTest.java",
    "content": "package com.jayway.jsonpath.matchers;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.JsonPath;\nimport com.jayway.jsonpath.ReadContext;\nimport com.jayway.jsonpath.matchers.helpers.StrictParsingConfiguration;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.jayway.jsonpath.matchers.JsonPathMatchers.*;\nimport static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resource;\nimport static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resourceAsFile;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.*;\n\npublic class JsonPathMatchersTest {\n    private static final String BOOKS_JSON = resource(\"books.json\");\n    private static final String INVALID_JSON = \"{ invalid-json }\";\n    private static final File BOOKS_JSON_FILE = resourceAsFile(\"books.json\");\n\n    @BeforeAll\n    public static void setupStrictJsonParsing() {\n        // NOTE: Evaluation depends on the default configuration of JsonPath\n        Configuration.setDefaults(new StrictParsingConfiguration());\n    }\n\n    @AfterAll\n    public static void setupDefaultJsonParsing() {\n        Configuration.setDefaults(null);\n    }\n\n    @Test\n    public void shouldMatchJsonPathToStringValue() {\n        final String json = \"{\\\"name\\\": \\\"Jessie\\\"}\";\n\n        assertThat(json, hasJsonPath(\"$.name\"));\n        assertThat(json, isJson(withJsonPath(\"$.name\")));\n        assertThat(json, hasJsonPath(\"$.name\", equalTo(\"Jessie\")));\n        assertThat(json, isJson(withJsonPath(\"$.name\", equalTo(\"Jessie\"))));\n\n        assertThat(json, not(hasJsonPath(\"$.name\", equalTo(\"John\"))));\n        assertThat(json, not(isJson(withJsonPath(\"$.name\", equalTo(\"John\")))));\n    }\n\n    @Test\n    public void shouldMatchJsonPathToIntegerValue() {\n        final String json = \"{\\\"number\\\": 10}\";\n\n        assertThat(json, hasJsonPath(\"$.number\"));\n        assertThat(json, isJson(withJsonPath(\"$.number\")));\n        assertThat(json, hasJsonPath(\"$.number\", equalTo(10)));\n        assertThat(json, isJson(withJsonPath(\"$.number\", equalTo(10))));\n\n        assertThat(json, not(hasJsonPath(\"$.number\", equalTo(3))));\n        assertThat(json, not(isJson(withJsonPath(\"$.number\", equalTo(3)))));\n    }\n\n    @Test\n    public void shouldMatchJsonPathToDoubleValue() {\n        final String json = \"{\\\"price\\\": 19.95}\";\n\n        assertThat(json, hasJsonPath(\"$.price\"));\n        assertThat(json, isJson(withJsonPath(\"$.price\")));\n        assertThat(json, hasJsonPath(\"$.price\", equalTo(19.95)));\n        assertThat(json, isJson(withJsonPath(\"$.price\", equalTo(19.95))));\n\n        assertThat(json, not(hasJsonPath(\"$.price\", equalTo(3.3))));\n        assertThat(json, not(isJson(withJsonPath(\"$.price\", equalTo(42)))));\n    }\n\n    @Test\n    public void shouldMatchJsonPathToBooleanValue() {\n        final String json = \"{\\\"flag\\\": false}\";\n\n        assertThat(json, hasJsonPath(\"$.flag\"));\n        assertThat(json, isJson(withJsonPath(\"$.flag\")));\n        assertThat(json, hasJsonPath(\"$.flag\", equalTo(false)));\n        assertThat(json, isJson(withJsonPath(\"$.flag\", equalTo(false))));\n\n        assertThat(json, not(hasJsonPath(\"$.flag\", equalTo(true))));\n        assertThat(json, not(isJson(withJsonPath(\"$.flag\", equalTo(true)))));\n    }\n\n    @Test\n    public void shouldMatchJsonPathToJsonObject() {\n        final String json = \"{\\\"object\\\": { \\\"name\\\":\\\"Oscar\\\"}}\";\n\n        assertThat(json, hasJsonPath(\"$.object\"));\n        assertThat(json, isJson(withJsonPath(\"$.object\")));\n        assertThat(json, hasJsonPath(\"$.object\", instanceOf(Map.class)));\n        assertThat(json, isJson(withJsonPath(\"$.object\", instanceOf(Map.class))));\n\n        assertThat(json, not(hasJsonPath(\"$.object\", instanceOf(List.class))));\n        assertThat(json, not(isJson(withJsonPath(\"$.object\", instanceOf(List.class)))));\n    }\n\n    @Test\n    public void shouldMatchJsonPathToEmptyJsonObject() {\n        final String json = \"{\\\"empty_object\\\": {}}\";\n\n        assertThat(json, hasJsonPath(\"$.empty_object\"));\n        assertThat(json, isJson(withJsonPath(\"$.empty_object\")));\n        assertThat(json, hasJsonPath(\"$.empty_object\", instanceOf(Map.class)));\n        assertThat(json, isJson(withJsonPath(\"$.empty_object\", instanceOf(Map.class))));\n\n        assertThat(json, not(hasJsonPath(\"$.empty_object\", instanceOf(List.class))));\n        assertThat(json, not(isJson(withJsonPath(\"$.empty_object\", instanceOf(List.class)))));\n    }\n\n    @Test\n    public void shouldMatchJsonPathToJsonArray() {\n        final String json = \"{\\\"list\\\": [ \\\"one\\\",\\\"two\\\",\\\"three\\\"]}\";\n\n        assertThat(json, hasJsonPath(\"$.list\"));\n        assertThat(json, hasJsonPath(\"$.list[*]\"));\n        assertThat(json, isJson(withJsonPath(\"$.list\")));\n        assertThat(json, isJson(withJsonPath(\"$.list[*]\")));\n        assertThat(json, hasJsonPath(\"$.list\", contains(\"one\", \"two\", \"three\")));\n        assertThat(json, isJson(withJsonPath(\"$.list\", hasItem(\"two\"))));\n\n        assertThat(json, not(hasJsonPath(\"$.list\", hasSize(2))));\n        assertThat(json, not(isJson(withJsonPath(\"$.list\", contains(\"four\")))));\n    }\n\n    @Test\n    public void shouldMatchJsonPathToEmptyJsonArray() {\n        final String json = \"{\\\"empty_list\\\": []}\";\n\n        assertThat(json, hasJsonPath(\"$.empty_list\"));\n        assertThat(json, hasJsonPath(\"$.empty_list[*]\"));\n        assertThat(json, isJson(withJsonPath(\"$.empty_list\")));\n        assertThat(json, isJson(withJsonPath(\"$.empty_list[*]\")));\n        assertThat(json, hasJsonPath(\"$.empty_list\", empty()));\n        assertThat(json, isJson(withJsonPath(\"$.empty_list\", hasSize(0))));\n\n        assertThat(json, not(hasJsonPath(\"$.empty_list\", hasSize(2))));\n        assertThat(json, not(isJson(withJsonPath(\"$.empty_list\", contains(\"four\")))));\n    }\n\n    @Test\n    public void willMatchIndefiniteJsonPathsEvaluatedToEmptyLists() {\n        // This is just a test to demonstrate that indefinite paths\n        // will always match, regardless of result. This is because\n        // the evaluation of these expressions will return lists,\n        // even though they may be empty.\n        String json = \"{\\\"items\\\": []}\";\n        assertThat(json, hasJsonPath(\"$.items[*].name\"));\n        assertThat(json, hasJsonPath(\"$.items[*]\"));\n        assertThat(json, hasJsonPath(\"$.items[*]\", hasSize(0)));\n    }\n\n    @Test\n    public void shouldMatchJsonPathToNullValue() {\n        final String json = \"{\\\"none\\\": null}\";\n\n        assertThat(json, hasJsonPath(\"$.none\"));\n        assertThat(json, isJson(withJsonPath(\"$.none\")));\n        assertThat(json, hasJsonPath(\"$.none\", nullValue()));\n        assertThat(json, isJson(withJsonPath(\"$.none\", nullValue())));\n\n        assertThat(json, not(hasJsonPath(\"$.none\", equalTo(\"something\"))));\n        assertThat(json, not(isJson(withJsonPath(\"$.none\", empty()))));\n    }\n\n    @Test\n    public void shouldNotMatchNonExistingJsonPath() {\n        final String json = \"{}\";\n\n        assertThat(json, not(hasJsonPath(\"$.not_there\")));\n        assertThat(json, not(hasJsonPath(\"$.not_there\", anything())));\n        assertThat(json, not(hasJsonPath(\"$.not_there[*]\")));\n        assertThat(json, not(hasJsonPath(\"$.not_there[*]\", anything())));\n        assertThat(json, not(isJson(withJsonPath(\"$.not_there\"))));\n        assertThat(json, not(isJson(withJsonPath(\"$.not_there\", anything()))));\n        assertThat(json, not(isJson(withJsonPath(\"$.not_there[*]\"))));\n        assertThat(json, not(isJson(withJsonPath(\"$.not_there[*]\", anything()))));\n    }\n\n    @Test\n    public void shouldNotMatchInvalidJsonWithPath() {\n        assertThat(INVALID_JSON, not(hasJsonPath(\"$.path\")));\n        assertThat(new Object(), not(hasJsonPath(\"$.path\")));\n        assertThat(null, not(hasJsonPath(\"$.path\")));\n    }\n\n    @Test\n    public void shouldNotMatchInvalidJsonWithPathAndValue() {\n        assertThat(INVALID_JSON, not(hasJsonPath(\"$.path\", anything())));\n        assertThat(new Object(), not(hasJsonPath(\"$.path\", anything())));\n        assertThat(null, not(hasJsonPath(\"$.message\", anything())));\n    }\n\n    @Test\n    public void shouldMatchJsonPathOnFile() {\n        assertThat(BOOKS_JSON_FILE, hasJsonPath(\"$.store.name\", equalTo(\"Little Shop\")));\n    }\n\n    @Test\n    public void shouldNotMatchJsonPathOnNonExistingFile() {\n        File nonExistingFile = new File(\"missing-file\");\n        assertThat(nonExistingFile, not(hasJsonPath(\"$..*\", anything())));\n    }\n\n    @Test\n    public void shouldMatchJsonPathOnParsedJsonObject() {\n        Object json = Configuration.defaultConfiguration().jsonProvider().parse(BOOKS_JSON);\n        assertThat(json, hasJsonPath(\"$.store.name\", equalTo(\"Little Shop\")));\n    }\n\n    @Test\n    public void shouldMatchJsonPathOnReadContext() {\n        String test = \"{\\\"foo\\\":\\\"bar\\\"}\";\n        ReadContext context = JsonPath.parse(test);\n        assertThat(context, hasJsonPath(\"$.foo\"));\n        assertThat(context, hasJsonPath(\"$.foo\", equalTo(\"bar\")));\n        assertThat(context, hasNoJsonPath(\"$.zoo\"));\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/test/java/com/jayway/jsonpath/matchers/WithJsonPathTest.java",
    "content": "package com.jayway.jsonpath.matchers;\n\nimport com.jayway.jsonpath.InvalidPathException;\nimport com.jayway.jsonpath.JsonPath;\nimport com.jayway.jsonpath.ReadContext;\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\nimport org.hamcrest.StringDescription;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collection;\nimport java.util.List;\n\nimport static com.jayway.jsonpath.JsonPath.compile;\nimport static com.jayway.jsonpath.matchers.JsonPathMatchers.withJsonPath;\nimport static com.jayway.jsonpath.matchers.helpers.ResourceHelpers.resource;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.*;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\npublic class WithJsonPathTest {\n    private static final ReadContext BOOKS_JSON = JsonPath.parse(resource(\"books.json\"));\n\n    @Test\n    public void shouldMatchExistingCompiledJsonPath() {\n        assertThat(BOOKS_JSON, withJsonPath(compile(\"$.expensive\")));\n        assertThat(BOOKS_JSON, withJsonPath(compile(\"$.store.bicycle\")));\n        assertThat(BOOKS_JSON, withJsonPath(compile(\"$.store.book[2].title\")));\n        assertThat(BOOKS_JSON, withJsonPath(compile(\"$.store.book[*].author\")));\n    }\n\n    @Test\n    public void shouldMatchExistingStringJsonPath() {\n        assertThat(BOOKS_JSON, withJsonPath(\"$.expensive\"));\n        assertThat(BOOKS_JSON, withJsonPath(\"$.store.bicycle\"));\n        assertThat(BOOKS_JSON, withJsonPath(\"$.store.book[2].title\"));\n        assertThat(BOOKS_JSON, withJsonPath(\"$.store.book[*].author\"));\n    }\n\n    @Test\n    public void shouldNotMatchNonExistingJsonPath() {\n        assertThat(BOOKS_JSON, not(withJsonPath(compile(\"$.not_there\"))));\n        assertThat(BOOKS_JSON, not(withJsonPath(compile(\"$.store.book[5].title\"))));\n        assertThat(BOOKS_JSON, not(withJsonPath(compile(\"$.store.book[1].not_there\"))));\n    }\n\n    @Test\n    public void shouldNotMatchNonExistingStringJsonPath() {\n        assertThat(BOOKS_JSON, not(withJsonPath(\"$.not_there\")));\n        assertThat(BOOKS_JSON, not(withJsonPath(\"$.store.book[5].title\")));\n        assertThat(BOOKS_JSON, not(withJsonPath(\"$.store.book[1].not_there\")));\n    }\n\n    @Test\n    public void shouldMatchJsonPathEvaluatedToStringValue() {\n        assertThat(BOOKS_JSON, withJsonPath(compile(\"$.store.bicycle.color\"), equalTo(\"red\")));\n        assertThat(BOOKS_JSON, withJsonPath(compile(\"$.store.book[2].title\"), equalTo(\"Moby Dick\")));\n        assertThat(BOOKS_JSON, withJsonPath(\"$.store.name\", equalTo(\"Little Shop\")));\n        assertThat(BOOKS_JSON, withJsonPath(\"$.store.book[2].title\", equalTo(\"Moby Dick\")));\n    }\n\n    @Test\n    public void shouldMatchJsonPathEvaluatedToIntegerValue() {\n        assertThat(BOOKS_JSON, withJsonPath(compile(\"$.expensive\"), equalTo(10)));\n        assertThat(BOOKS_JSON, withJsonPath(\"$.expensive\", equalTo(10)));\n    }\n\n    @Test\n    public void shouldMatchJsonPathEvaluatedToDoubleValue() {\n        assertThat(BOOKS_JSON, withJsonPath(compile(\"$.store.bicycle.price\"), equalTo(19.95)));\n        assertThat(BOOKS_JSON, withJsonPath(\"$.store.bicycle.price\", equalTo(19.95)));\n    }\n\n    @Test\n    public void shouldMatchJsonPathEvaluatedToCollectionValue() {\n        assertThat(BOOKS_JSON, withJsonPath(compile(\"$.store.book[*].author\"), instanceOf(List.class)));\n        assertThat(BOOKS_JSON, withJsonPath(compile(\"$.store.book[*].author\"), hasSize(4)));\n        assertThat(BOOKS_JSON, withJsonPath(compile(\"$.store.book[*].author\"), hasItem(\"Evelyn Waugh\")));\n        assertThat(BOOKS_JSON, withJsonPath(compile(\"$..book[2].title\"), hasItem(\"Moby Dick\")));\n        assertThat(BOOKS_JSON, withJsonPath(\"$.store.book[*].author\", instanceOf(Collection.class)));\n        assertThat(BOOKS_JSON, withJsonPath(\"$.store.book[*].author\", hasSize(4)));\n        assertThat(BOOKS_JSON, withJsonPath(\"$.store.book[*].author\", hasItem(\"Evelyn Waugh\")));\n        assertThat(BOOKS_JSON, withJsonPath(\"$..book[2].title\", hasItem(\"Moby Dick\")));\n    }\n\n    @Test\n    public void shouldFailOnInvalidJsonPath() {\n        assertThrows(InvalidPathException.class, () -> withJsonPath(\"$[}\"));\n    }\n\n    @Test\n    public void shouldNotMatchOnInvalidJson() {\n        ReadContext invalidJson = JsonPath.parse(\"invalid-json\");\n        assertThat(invalidJson, not(withJsonPath(\"$.expensive\", equalTo(10))));\n    }\n\n    @Test\n    public void shouldBeDescriptive() {\n        Matcher<? super ReadContext> matcher = withJsonPath(\"path\", equalTo(2));\n        Description description = new StringDescription();\n        matcher.describeTo(description);\n        assertThat(description.toString(), containsString(\"path\"));\n        assertThat(description.toString(), containsString(\"<2>\"));\n    }\n\n    @Test\n    public void shouldDescribeMismatchOfEvaluation() {\n        Matcher<? super ReadContext> matcher = withJsonPath(\"expensive\", equalTo(3));\n        Description description = new StringDescription();\n        matcher.describeMismatch(BOOKS_JSON, description);\n        assertThat(description.toString(), containsString(\"expensive\"));\n        assertThat(description.toString(), containsString(\"<10>\"));\n    }\n\n    @Test\n    public void shouldDescribeMismatchOfPathNotFound() {\n        Matcher<? super ReadContext> matcher = withJsonPath(\"not-here\", equalTo(3));\n        Description description = new StringDescription();\n        matcher.describeMismatch(BOOKS_JSON, description);\n        assertThat(description.toString(), containsString(\"not-here\"));\n        assertThat(description.toString(), containsString(\"was not found\"));\n    }\n\n}\n"
  },
  {
    "path": "json-path-assert/src/test/java/com/jayway/jsonpath/matchers/WithoutJsonPathTest.java",
    "content": "package com.jayway.jsonpath.matchers;\n\nimport com.jayway.jsonpath.JsonPath;\nimport com.jayway.jsonpath.ReadContext;\nimport org.junit.jupiter.api.Test;\n\nimport static com.jayway.jsonpath.JsonPath.compile;\nimport static com.jayway.jsonpath.matchers.JsonPathMatchers.withoutJsonPath;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.*;\n\npublic class WithoutJsonPathTest {\n    private static final String JSON_STRING = \"{\" +\n            \"\\\"name\\\": \\\"Jessie\\\",\" +\n            \"\\\"flag\\\": false,\" +\n            \"\\\"empty_array\\\": [],\" +\n            \"\\\"empty_object\\\": {},\" +\n            \"\\\"none\\\": null\" +\n            \"}\";\n    private static final ReadContext JSON = JsonPath.parse(JSON_STRING);\n\n    @Test\n    public void shouldMatchNonExistingJsonPath() {\n        assertThat(JSON, withoutJsonPath(compile(\"$.not_there\")));\n        assertThat(JSON, withoutJsonPath(\"$.not_there\"));\n    }\n\n    @Test\n    public void shouldNotMatchExistingJsonPath() {\n        assertThat(JSON, not(withoutJsonPath(compile(\"$.name\"))));\n        assertThat(JSON, not(withoutJsonPath(\"$.name\")));\n        assertThat(JSON, not(withoutJsonPath(\"$.flag\")));\n        assertThat(JSON, not(withoutJsonPath(\"$.empty_array\")));\n        assertThat(JSON, not(withoutJsonPath(\"$.empty_object\")));\n        assertThat(JSON, not(withoutJsonPath(\"$.none\")));\n    }\n\n    @Test\n    public void shouldBeDescriptive() {\n        assertThat(withoutJsonPath(\"$.name\"),\n                hasToString(equalTo(\"without json path \\\"$['name']\\\"\")));\n    }\n\n}\n"
  },
  {
    "path": "json-path-assert/src/test/java/com/jayway/jsonpath/matchers/helpers/ResourceHelpers.java",
    "content": "package com.jayway.jsonpath.matchers.helpers;\n\nimport org.apache.commons.io.IOUtils;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.net.URL;\n\nimport static java.lang.ClassLoader.getSystemResource;\nimport static java.lang.ClassLoader.getSystemResourceAsStream;\n\npublic class ResourceHelpers {\n    public static String resource(String resource) {\n        try {\n            return IOUtils.toString(getSystemResourceAsStream(resource));\n        } catch (IOException e) {\n            throw new AssertionError(\"Resource not found: \" + e.getMessage());\n        }\n    }\n\n    public static File resourceAsFile(String resource) {\n        try {\n            URL systemResource = getSystemResource(resource);\n            return new File(systemResource.toURI());\n        } catch (URISyntaxException e) {\n            throw new AssertionError(\"URI syntax error:\" + e.getMessage());\n        }\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/test/java/com/jayway/jsonpath/matchers/helpers/StrictParsingConfiguration.java",
    "content": "package com.jayway.jsonpath.matchers.helpers;\n\nimport com.jayway.jsonpath.Configuration;\nimport com.jayway.jsonpath.Option;\nimport com.jayway.jsonpath.spi.json.JsonProvider;\nimport com.jayway.jsonpath.spi.json.JsonSmartJsonProvider;\nimport com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider;\nimport com.jayway.jsonpath.spi.mapper.MappingProvider;\nimport net.minidev.json.parser.JSONParser;\n\nimport java.util.EnumSet;\nimport java.util.Set;\n\npublic class StrictParsingConfiguration implements Configuration.Defaults {\n\n    private final JsonProvider jsonProvider = new JsonSmartJsonProvider(JSONParser.MODE_STRICTEST);\n    private final MappingProvider mappingProvider = new JsonSmartMappingProvider();\n\n    public JsonProvider jsonProvider() {\n        return jsonProvider;\n    }\n\n    public MappingProvider mappingProvider() {\n        return mappingProvider;\n    }\n\n    public Set<Option> options() {\n        return EnumSet.noneOf(Option.class);\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/test/java/com/jayway/jsonpath/matchers/helpers/TestingMatchers.java",
    "content": "package com.jayway.jsonpath.matchers.helpers;\n\nimport com.jayway.jsonpath.ReadContext;\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\nimport org.hamcrest.TypeSafeMatcher;\n\n/**\n * Dummy matchers to simplify testing\n */\npublic class TestingMatchers {\n\n    public static final String MISMATCHED_TEXT = \"with path mismatched\";\n    public static final String MATCH_TRUE_TEXT = \"with path evaluated to <true>\";\n\n    public static Matcher<ReadContext> withPathEvaluatedTo(final boolean result) {\n        return new TypeSafeMatcher<ReadContext>() {\n            public void describeTo(Description description) {\n                description.appendText(\"with path evaluated to \").appendValue(result);\n            }\n\n            @Override\n            protected boolean matchesSafely(ReadContext ignored) {\n                return result;\n            }\n\n            @Override\n            protected void describeMismatchSafely(ReadContext ignore, Description mismatchDescription) {\n                mismatchDescription.appendText(MISMATCHED_TEXT);\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "json-path-assert/src/test/resources/books.json",
    "content": "{\n  \"store\": {\n    \"name\": \"Little Shop\",\n    \"none\": null,\n    \"switch\": true,\n    \"magazine\": [],\n    \"truck\": {},\n    \"book\": [\n      {\n        \"category\": \"reference\",\n        \"author\": \"Nigel Rees\",\n        \"title\": \"Sayings of the Century\",\n        \"price\": 8.95\n      },\n      {\n        \"category\": \"fiction\",\n        \"author\": \"Evelyn Waugh\",\n        \"title\": \"Sword of Honour\",\n        \"price\": 12.99\n      },\n      {\n        \"category\": \"fiction\",\n        \"author\": \"Herman Melville\",\n        \"title\": \"Moby Dick\",\n        \"isbn\": \"0-553-21311-3\",\n        \"price\": 8.99\n      },\n      {\n        \"category\": \"fiction\",\n        \"author\": \"J. R. R. Tolkien\",\n        \"title\": \"The Lord of the Rings\",\n        \"isbn\": \"0-395-19395-8\",\n        \"price\": 22.99\n      }\n    ],\n    \"bicycle\": {\n      \"color\": \"red\",\n      \"price\": 19.95\n    }\n  },\n  \"expensive\": 10\n}"
  },
  {
    "path": "json-path-assert/src/test/resources/example.json",
    "content": "{\n  \"message\": \"Hi there!\",\n  \"number\": 5\n}"
  },
  {
    "path": "json-path-assert/src/test/resources/invalid.json",
    "content": "invalid-json"
  },
  {
    "path": "json-path-assert/src/test/resources/links.json",
    "content": "{\n    \"links\": {\n        \"gc:this\": {\n            \"rel\": \"gc:this\",\n            \"href\": \"/rest/account/market/incentives?pageNumber=1&pageSize=2\"\n        }\n    },\n    \"count\": 2,\n    \"pageNumber\": 1,\n    \"pageSize\": 2,\n    \"rows\": [{\n        \"id\": \"cd646745-5834-4244-9126-fa631c32693c\",\n        \"price\": 10,\n        \"title\": \"A TITLE\",\n        \"description\": \"description\",\n        \"smallIcon\": \"small.ico\",\n        \"categories\": [\"cd646745-5834-4244-9126-fa631c32693c\"],\n        \"brand\": {\n            \"id\": \"8d0280ae-8ea3-4ae1-b46c-f0fc0b293066\",\n            \"name\": \"brand.name\",\n            \"picture\": \"brand.picture\"\n        },\n        \"links\": {\n            \"gc:market:incentive\": {\n                \"rel\": \"gc:market:incentive\",\n                \"href\": \"/rest/account/market/incentives/cd646745-5834-4244-9126-fa631c32693c\"\n            }\n        }\n    },\n    {\n        \"id\": \"cd646745-5834-4244-9126-fa631c32693c2\",\n        \"price\": 10,\n        \"title\": \"B TITLE\",\n        \"description\": \"description\",\n        \"smallIcon\": \"small.ico\",\n        \"categories\": [\"cd646745-5834-4244-9126-fa631c32693c\"],\n        \"brand\": {\n            \"id\": \"8d0280ae-8ea3-4ae1-b46c-f0fc0b293066\",\n            \"name\": \"brand.name\",\n            \"picture\": \"brand.picture\"\n        },\n        \"links\": {\n            \"gc:market:incentive\": {\n                \"rel\": \"gc:market:incentive\",\n                \"href\": \"/rest/account/market/incentives/cd646745-5834-4244-9126-fa631c32693c2\"\n            }\n        }\n    }]\n}\n"
  },
  {
    "path": "json-path-assert/src/test/resources/lotto.json",
    "content": "{\"lotto\":{\"lottoId\":5,\"winning-numbers\":[2,45,34,23,7,5,3],\"winners\":[{\"winnerId\":23,\"numbers\":[2,45,34,23,3,5]},{\"winnerId\":54,\"numbers\":[52,3,12,11,18,22]}]}}"
  },
  {
    "path": "settings.gradle",
    "content": "rootProject.name = 'json-path-parent'\ninclude ':json-path', ':json-path-assert'"
  },
  {
    "path": "system.properties",
    "content": "java.runtime.version=17"
  }
]